Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 104 additions & 57 deletions astrbot/core/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
import os
import sys
import threading
import time
from asyncio import Queue
from collections import deque
Expand Down Expand Up @@ -173,6 +174,7 @@ class LogManager:
_console_sink_id: int | None = None
_file_sink_id: int | None = None
_trace_sink_id: int | None = None
_reconfigure_lock = threading.RLock()
_NOISY_LOGGER_LEVELS: dict[str, int] = {
"aiosqlite": logging.WARNING,
"filelock": logging.WARNING,
Expand Down Expand Up @@ -337,40 +339,22 @@ def _add_file_sink(
)

@classmethod
def configure_logger(
def _replace_file_sink(
cls,
*,
logger: logging.Logger,
config: dict | None,
override_level: str | None = None,
enable_file: bool,
file_path: str | None,
max_mb: int | None,
) -> None:
if not config:
return

level = override_level or config.get("log_level")
if level:
try:
logger.setLevel(level)
except Exception:
logger.setLevel(logging.INFO)

if "log_file" in config:
file_conf = config.get("log_file") or {}
enable_file = bool(file_conf.get("enable", False))
file_path = file_conf.get("path")
max_mb = file_conf.get("max_mb")
else:
enable_file = bool(config.get("log_file_enable", False))
file_path = config.get("log_file_path")
max_mb = config.get("log_file_max_mb")

cls._remove_sink(cls._file_sink_id)
cls._file_sink_id = None

if not enable_file:
old_sink_id = cls._file_sink_id
cls._file_sink_id = None
cls._remove_sink(old_sink_id)
return

try:
cls._file_sink_id = cls._add_file_sink(
new_sink_id = cls._add_file_sink(
file_path=cls._resolve_log_path(file_path),
level=logger.level,
max_mb=max_mb,
Expand All @@ -379,39 +363,102 @@ def configure_logger(
)
except Exception as e:
logger.error(f"Failed to add file sink: {e}")

@classmethod
def configure_trace_logger(cls, config: dict | None) -> None:
if not config:
return

enable = bool(
config.get("trace_log_enable")
or (config.get("log_file", {}) or {}).get("trace_enable", False)
)
path = config.get("trace_log_path")
max_mb = config.get("trace_log_max_mb")
if "log_file" in config:
legacy = config.get("log_file") or {}
path = path or legacy.get("trace_path")
max_mb = max_mb or legacy.get("trace_max_mb")

trace_logger = logging.getLogger("astrbot.trace")
cls._ensure_logger_enricher_filter(trace_logger)
cls._ensure_logger_intercept_handler(trace_logger)
trace_logger.setLevel(logging.INFO)
trace_logger.propagate = False

cls._remove_sink(cls._trace_sink_id)
cls._trace_sink_id = None
old_sink_id = cls._file_sink_id
cls._file_sink_id = new_sink_id
cls._remove_sink(old_sink_id)

@classmethod
def _replace_trace_sink(
cls,
*,
enable: bool,
path: str | None,
max_mb: int | None,
) -> None:
if not enable:
old_sink_id = cls._trace_sink_id
cls._trace_sink_id = None
cls._remove_sink(old_sink_id)
return

cls._trace_sink_id = cls._add_file_sink(
file_path=cls._resolve_log_path(path or "logs/astrbot.trace.log"),
level=logging.INFO,
max_mb=max_mb,
backup_count=3,
trace=True,
)
try:
new_sink_id = cls._add_file_sink(
file_path=cls._resolve_log_path(path or "logs/astrbot.trace.log"),
level=logging.INFO,
max_mb=max_mb,
backup_count=3,
trace=True,
)
except Exception as e:
logging.getLogger("astrbot").error(f"Failed to add trace sink: {e}")
Comment thread
Sisyphbaous-DT-Project marked this conversation as resolved.
return

old_sink_id = cls._trace_sink_id
cls._trace_sink_id = new_sink_id
cls._remove_sink(old_sink_id)

@classmethod
def configure_logger(
cls,
logger: logging.Logger,
config: dict | None,
override_level: str | None = None,
) -> None:
with cls._reconfigure_lock:
if not config:
return

level = override_level or config.get("log_level")
if level:
try:
logger.setLevel(level)
except Exception:
logger.setLevel(logging.INFO)

if "log_file" in config:
file_conf = config.get("log_file") or {}
enable_file = bool(file_conf.get("enable", False))
file_path = file_conf.get("path")
max_mb = file_conf.get("max_mb")
else:
enable_file = bool(config.get("log_file_enable", False))
file_path = config.get("log_file_path")
max_mb = config.get("log_file_max_mb")

cls._replace_file_sink(
logger=logger,
enable_file=enable_file,
file_path=file_path,
max_mb=max_mb,
)

@classmethod
def configure_trace_logger(cls, config: dict | None) -> None:
with cls._reconfigure_lock:
if not config:
return

enable = bool(
config.get("trace_log_enable")
or (config.get("log_file", {}) or {}).get("trace_enable", False)
)
path = config.get("trace_log_path")
max_mb = config.get("trace_log_max_mb")
if "log_file" in config:
legacy = config.get("log_file") or {}
path = path or legacy.get("trace_path")
max_mb = max_mb or legacy.get("trace_max_mb")

trace_logger = logging.getLogger("astrbot.trace")
cls._ensure_logger_enricher_filter(trace_logger)
cls._ensure_logger_intercept_handler(trace_logger)
trace_logger.setLevel(logging.INFO)
trace_logger.propagate = False

cls._replace_trace_sink(
enable=enable,
path=path,
max_mb=max_mb,
)
Loading
Loading