Files
ai-g3sb-backman2.0/backend/utils/repo_logging.py
T
2026-04-16 10:53:10 +08:00

81 lines
2.5 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.
"""
Text2SQL API 仓库级日志:控制台 + 单一磁盘文件(每次进程启动清空 logs/*.log 后重写)。
由 ``api_server`` 在导入早期调用;与 ``uvicorn.run(..., log_config=False)`` 配合,
使 uvicorn / FastAPI 的日志经 root 统一落到文件。
"""
from __future__ import annotations
import logging
from pathlib import Path
def configure_text2sql_api_logging(repo_root: Path) -> Path:
"""
配置 root logger:控制台(INFO,简短格式)+ ``logs/text2sql_api.log``(INFO,含文件名/行号/函数)。
每次调用会删除 ``logs`` 目录下所有 ``*.log``,再新建 ``text2sql_api.log``(覆盖写),
保证一次运行仅保留一个日志文件。
Returns:
主日志文件绝对路径。
"""
log_dir = (repo_root / "logs").resolve()
log_dir.mkdir(parents=True, exist_ok=True)
for p in log_dir.glob("*.log"):
try:
p.unlink()
except OSError:
pass
log_path = log_dir / "text2sql_api.log"
root = logging.getLogger()
root.setLevel(logging.INFO)
for h in list(root.handlers):
root.removeHandler(h)
try:
h.close()
except Exception:
pass
fmt_console = logging.Formatter(
"%(asctime)s [%(levelname)s] %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
fmt_file = logging.Formatter(
"%(asctime)s %(levelname)-7s [%(name)s] %(filename)s:%(lineno)d %(funcName)s() | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
fh = logging.FileHandler(log_path, mode="w", encoding="utf-8")
fh.setLevel(logging.INFO)
fh.setFormatter(fmt_file)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(fmt_console)
root.addHandler(fh)
root.addHandler(ch)
# 依赖库降噪(避免 httpx 每条请求刷屏;Chroma 遥测与新版 posthog 不兼容时会打 ERROR)
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("httpcore").setLevel(logging.WARNING)
for _name in (
"chromadb.telemetry",
"chromadb.telemetry.product.posthog",
"posthog",
):
logging.getLogger(_name).disabled = True
# Uvicorn 默认自带 handler;与 log_config=False 合用时改为只往 root 冒泡
for name in ("uvicorn", "uvicorn.error", "uvicorn.access"):
lg = logging.getLogger(name)
lg.handlers.clear()
lg.propagate = True
logging.getLogger(__name__).info("日志文件: %s", log_path)
return log_path