import logging import json from datetime import datetime import os import sys from typing import Dict, Any from pathlib import Path # 确保日志目录存在 LOG_DIR = Path("chat_logs") LOG_DIR.mkdir(exist_ok=True) # 详细日志目录结构 DETAILED_LOG_DIR = LOG_DIR / "detailed" DETAILED_LOG_DIR.mkdir(exist_ok=True) # 全局变量 current_log_date = datetime.now().strftime("%Y%m%d") chat_logger = None # 初始化为None,在setup_logging中初始化 def setup_logging(force_reconfigure=False): """配置日志系统""" global chat_logger # 创建或重新获取logger logger = logging.getLogger("chat_logger") logger.setLevel(logging.INFO) # 文件处理器 - 按天分割 today_str = datetime.now().strftime("%Y%m%d") log_file = LOG_DIR / f"chat_{today_str}.log" # 检查是否需要重新配置(强制重新配置或没有handlers) needs_reconfigure = force_reconfigure or not logger.handlers if needs_reconfigure: # 清理旧的handler for handler in logger.handlers[:]: handler.close() logger.removeHandler(handler) # 创建新的文件处理器 file_handler = logging.FileHandler(log_file, encoding="utf-8") file_handler.setLevel(logging.INFO) # 控制台处理器 console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) # 确保控制台编码 try: if hasattr(sys.stdout, "reconfigure") and sys.stdout.encoding != "utf-8": sys.stdout.reconfigure(encoding="utf-8") except: pass # 格式化 formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) file_handler.setFormatter(formatter) console_handler.setFormatter(formatter) logger.addHandler(file_handler) logger.addHandler(console_handler) chat_logger = logger return logger # 初始化日志 chat_logger = setup_logging() def get_detailed_log_path(user_id: str, timestamp: datetime = None) -> Path: """获取详细日志文件的路径""" if timestamp is None: timestamp = datetime.now() # 按日期创建目录 date_str = timestamp.strftime("%Y%m%d") date_dir = DETAILED_LOG_DIR / date_str date_dir.mkdir(exist_ok=True) # 生成文件名 filename = f"{user_id}_{timestamp.strftime('%Y%m%d_%H%M%S')}.json" return date_dir / filename def _reconfigure_logging(): """重新配置日志处理器,用于处理跨日情况""" global chat_logger, current_log_date today = datetime.now().strftime("%Y%m%d") if today != current_log_date: # 记录日期变化信息到当前日志文件 if chat_logger: chat_logger.info( f"检测到日期变化: {current_log_date} -> {today}, 重新配置日志处理器" ) current_log_date = today # 强制重新配置日志处理器 setup_logging(force_reconfigure=True) def log_chat_entry(user_id: str, user_message: str, agent_response: Dict[str, Any]): """记录完整的对话日志""" try: # 每次调用都检查日期是否变化 _reconfigure_logging() timestamp = datetime.now() # 构建日志条目 log_entry = { "timestamp": timestamp.isoformat(), "user_id": user_id, "user_message": user_message, "thread_id": agent_response.get("thread_id", ""), "agent_response": { "final_answer": agent_response.get("final_answer", ""), "all_ai_messages_count": len(agent_response.get("all_ai_messages", [])), "all_messages_count": len(agent_response.get("all_messages", [])), "tool_calls_count": len(agent_response.get("tool_calls", [])), }, "all_messages": [ { "type": msg.get("type"), "content": msg.get("content", "")[:500], # 限制长度 "tool_calls": msg.get("tool_calls"), "index": msg.get("index"), } for msg in agent_response.get("all_messages", []) ], "tool_calls": agent_response.get("tool_calls", []), } # 记录到日志文件 chat_logger.info(f"对话记录 - Thread: {user_id}") chat_logger.info(f"用户消息: {user_message}") chat_logger.info( f"Agent响应: {agent_response.get('final_answer', '')[:200]}..." ) # 保存详细日志到单独文件 detailed_log_file = get_detailed_log_path(user_id, timestamp) with open(detailed_log_file, "w", encoding="utf-8") as f: json.dump(log_entry, f, ensure_ascii=False, indent=2) chat_logger.info(f"详细日志已保存到: {detailed_log_file}") except Exception as e: chat_logger.error(f"记录日志时出错: {str(e)}")