ForcePilot/backend/package/yuxi/utils/logging_config.py
Kris fb754d82f1 feat(channel): 添加全渠道网关核心基础架构
新增渠道扩展框架的核心基础层,为所有渠道扩展提供统一的基础设施。

主要变更:
- channel/extensions/__init__.py: 渠道扩展包初始化与注册
- channel/extensions/base.py: 渠道插件基类,定义统一接口规范
- channel_service.py: 渠道服务核心业务逻辑
- models_channels.py: 渠道相关数据库模型
- 8 个 channel_*_repo.py: 渠道数据仓库层
- storage/postgres/manager.py: 数据库管理器,新增渠道表
- models_business.py: 业务模型更新
- config/app.py: 应用配置更新
- conversation_repository.py: 会话仓库更新
- oidc_service.py: OIDC 服务更新
- logging_config.py: 日志配置更新
2026-05-21 12:08:03 +08:00

114 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import logging
import os
import sys
from loguru import logger as loguru_logger
from yuxi.utils.datetime_utils import shanghai_now
SAVE_DIR = os.getenv("SAVE_DIR") or "saves"
DATETIME = shanghai_now().strftime("%Y-%m-%d")
LOG_FILE = f"{SAVE_DIR}/logs/yuxi-{DATETIME}.log"
class LoguruHandler(logging.Handler):
"""将 Python logging 桥接到 loguru 的 handler自动注入 trace_id"""
def emit(self, record: logging.LogRecord):
level_map = {
logging.DEBUG: "DEBUG",
logging.INFO: "INFO",
logging.WARNING: "WARNING",
logging.ERROR: "ERROR",
logging.CRITICAL: "CRITICAL",
}
level = level_map.get(record.levelno, "DEBUG")
try:
msg = self.format(record)
except Exception:
msg = record.getMessage()
trace_id = getattr(record, "trace_id", "-") or "-"
msg = f"[{trace_id}] {msg}"
loguru_logger.opt(depth=1, exception=record.exc_info).log(level, msg)
def _setup_logging_bridge():
"""配置 logging 到 loguru 的桥接,捕获第三方库日志(如 LightRAG
同时为 yuxi.channel 模块日志安装 trace_id filter 实现全链路追踪。
"""
from yuxi.channel.runtime.trace_ctx import TraceIdFilter
loguru_handler = LoguruHandler()
loguru_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
loguru_handler.setFormatter(formatter)
# 桥接 LightRAG 日志
lightrag_logger = logging.getLogger("lightrag")
lightrag_logger.addHandler(loguru_handler)
lightrag_logger.setLevel(logging.DEBUG)
lightrag_logger.propagate = False # 避免重复
# 桥接其他常见第三方库(降低级别减少噪音)
for lib in ["httpx", "openai", "neo4j", "urllib3"]:
lib_logger = logging.getLogger(lib)
lib_logger.addHandler(loguru_handler)
lib_logger.setLevel(logging.WARNING)
lib_logger.propagate = False
# 桥接 yuxi.channel 模块日志,并安装 trace_id filter
channel_logger = logging.getLogger("yuxi.channel")
channel_logger.addHandler(loguru_handler)
channel_logger.setLevel(logging.DEBUG)
channel_logger.propagate = False
trace_filter = TraceIdFilter()
channel_logger.addFilter(trace_filter)
def setup_logger(name, level="DEBUG", console=True):
"""使用 loguru 设置日志记录器"""
os.makedirs(f"{SAVE_DIR}/logs", exist_ok=True)
# 移除默认的 handler
loguru_logger.remove()
# 添加文件日志(无颜色)
loguru_logger.add(
LOG_FILE,
level=level,
format="{time:YYYY-MM-DD HH:mm:ss} - {level} - {file}:{line} - {message}",
encoding="utf-8",
rotation="10 MB",
retention="30 days",
compression="zip",
enqueue=True,
)
# 添加控制台日志(有颜色)
if console:
loguru_logger.add(
sys.stderr,
level=level,
format=(
"<green>{time:MM-DD HH:mm:ss}</green> "
"<level>{level}</level> "
"<cyan>{file}:{line}</cyan>: "
"<level>{message}</level>"
),
colorize=True,
enqueue=True,
)
return loguru_logger
# 设置根日志记录器
logger = setup_logger("Yuxi")
# 初始化 logging 桥接
_setup_logging_bridge()
__all__ = ["logger"]