import logging import logging.handlers import json import sys import os from datetime import datetime, timezone class JsonFormatter(logging.Formatter): """JSON 日志格式化器 (适合生产环境日志聚合)""" def format(self, record: logging.LogRecord) -> str: log_entry = { "timestamp": datetime.now(timezone.utc).isoformat(), "level": record.levelname, "logger": record.name, "message": record.getMessage(), } if hasattr(record, "trace_id"): log_entry["trace_id"] = record.trace_id if record.exc_info and record.exc_info[0]: log_entry["exception"] = self.formatException(record.exc_info) return json.dumps(log_entry, ensure_ascii=False) def setup_logging(level: str = "INFO", json_format: bool = False): root = logging.getLogger() root.setLevel(getattr(logging, level.upper(), logging.INFO)) root.handlers.clear() # 控制台 handler console_handler = logging.StreamHandler(sys.stdout) if json_format: console_handler.setFormatter(JsonFormatter()) else: console_handler.setFormatter(logging.Formatter( "%(asctime)s [%(levelname)s] %(name)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S", )) root.addHandler(console_handler) # 可选:文件落盘 (LOG_FILE 环境变量指定路径,默认不开启) log_file = os.getenv("LOG_FILE") if log_file: file_handler = logging.handlers.RotatingFileHandler( log_file, maxBytes=10 * 1024 * 1024, backupCount=5, encoding="utf-8" ) file_handler.setFormatter(JsonFormatter()) root.addHandler(file_handler) logging.getLogger("httpx").setLevel(logging.WARNING) logging.getLogger("chromadb").setLevel(logging.WARNING) logging.getLogger("langchain").setLevel(logging.WARNING)