ai-chat-ui/server/utils/logger.py

243 lines
7.1 KiB
Python

"""
统一日志管理系统
提供结构化日志记录功能,支持不同日志级别、文件输出、轮转等
"""
import logging
import os
import sys
from datetime import datetime
from pathlib import Path
from logging.handlers import RotatingFileHandler
import json
class LoggerSetup:
"""日志系统配置类"""
def __init__(self, name: str = "ai-chat-server", log_level: str = "INFO",
log_dir: str = "logs", max_bytes: int = 10 * 1024 * 1024, backup_count: int = 5):
"""
初始化日志系统
Args:
name: 日志记录器名称
log_level: 日志级别 ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
log_dir: 日志文件存储目录
max_bytes: 单个日志文件最大大小(字节)
backup_count: 保留的备份文件数量
"""
self.name = name
self.log_level = getattr(logging, log_level.upper(), logging.INFO)
self.log_dir = Path(log_dir)
self.max_bytes = max_bytes
self.backup_count = backup_count
# 创建日志目录
self.log_dir.mkdir(exist_ok=True)
# 设置日志格式
self.formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
)
# 创建logger实例
self.logger = self._setup_logger()
def _setup_logger(self):
"""设置logger实例"""
logger = logging.getLogger(self.name)
logger.setLevel(self.log_level)
# 避免重复添加处理器
if logger.handlers:
logger.handlers.clear()
# 控制台处理器
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(self.log_level)
console_handler.setFormatter(self.formatter)
logger.addHandler(console_handler)
# 文件处理器 - 按日期分割
date_str = datetime.now().strftime("%Y-%m-%d")
log_file = self.log_dir / f"{self.name}_{date_str}.log"
file_handler = RotatingFileHandler(
str(log_file),
maxBytes=self.max_bytes,
backupCount=self.backup_count,
encoding='utf-8'
)
file_handler.setLevel(self.log_level)
file_handler.setFormatter(self.formatter)
logger.addHandler(file_handler)
return logger
def get_logger(self):
"""获取配置好的logger实例"""
return self.logger
# 全局日志实例
_logger_instance = None
def setup_global_logger(name: str = "ai-chat-server", log_level: str = "INFO",
log_dir: str = "logs", max_bytes: int = 10 * 1024 * 1024,
backup_count: int = 5):
"""
设置全局日志系统
Args:
name: 日志记录器名称
log_level: 日志级别
log_dir: 日志文件目录
max_bytes: 最大文件大小
backup_count: 备份文件数
"""
global _logger_instance
logger_setup = LoggerSetup(name, log_level, log_dir, max_bytes, backup_count)
_logger_instance = logger_setup.get_logger()
return _logger_instance
def get_logger(name: str = None):
"""
获取日志记录器实例
Args:
name: 如果提供,返回子记录器;否则返回全局记录器
"""
global _logger_instance
if _logger_instance is None:
# 如果没有初始化,默认创建一个
_logger_instance = setup_global_logger()
if name and name != _logger_instance.name:
return _logger_instance.getChild(name)
return _logger_instance
# 便捷的日志记录函数
def log_debug(message: str, *args, **kwargs):
"""记录DEBUG级别日志"""
logger = get_logger()
logger.debug(message, *args, **kwargs)
def log_info(message: str, *args, **kwargs):
"""记录INFO级别日志"""
logger = get_logger()
logger.info(message, *args, **kwargs)
def log_warning(message: str, *args, **kwargs):
"""记录WARNING级别日志"""
logger = get_logger()
logger.warning(message, *args, **kwargs)
def log_error(message: str, *args, **kwargs):
"""记录ERROR级别日志"""
logger = get_logger()
logger.error(message, *args, **kwargs)
def log_critical(message: str, *args, **kwargs):
"""记录CRITICAL级别日志"""
logger = get_logger()
logger.critical(message, *args, **kwargs)
def log_exception(message: str = ""):
"""记录异常信息"""
logger = get_logger()
logger.exception(message)
def log_structured(level: str, message: str, **details):
"""
记录结构化日志
Args:
level: 日志级别
message: 日志消息
**details: 额外的结构化数据
"""
logger = get_logger()
structured_log = {
"timestamp": datetime.now().isoformat(),
"level": level.upper(),
"message": message,
"details": details
}
getattr(logger, level.lower())(json.dumps(structured_log, ensure_ascii=False))
def log_request_info(method: str, path: str, client_ip: str = "unknown",
user_agent: str = "", referer: str = ""):
"""记录请求信息日志"""
log_structured(
"info",
"API Request",
method=method,
path=path,
client_ip=client_ip,
user_agent=user_agent,
referer=referer
)
def log_response_info(status_code: int, process_time: float, path: str = "",
method: str = "", client_ip: str = ""):
"""记录响应信息日志"""
log_structured(
"info",
"API Response",
status_code=status_code,
process_time_ms=process_time,
path=path,
method=method,
client_ip=client_ip
)
def log_error_detail(error_type: str, error_message: str, traceback_info: str = "",
context: dict = None):
"""记录详细的错误信息"""
log_structured(
"error",
f"{error_type}: {error_message}",
traceback=traceback_info,
context=context or {}
)
def log_chat_interaction(user_input: str, ai_response: str, model: str = "",
conversation_id: str = "", tokens_used: dict = None):
"""记录聊天交互日志"""
log_structured(
"info",
"Chat Interaction",
user_input=user_input[:100] + "..." if len(user_input) > 100 else user_input, # 截断长输入
ai_response=ai_response[:100] + "..." if len(ai_response) > 100 else ai_response,
model=model,
conversation_id=conversation_id,
tokens_used=tokens_used
)
def log_system_status(status: str, uptime: float = 0, cpu_usage: float = 0,
memory_usage: float = 0, disk_usage: float = 0):
"""记录系统状态日志"""
log_structured(
"info",
"System Status",
status=status,
uptime_seconds=uptime,
cpu_percent=cpu_usage,
memory_percent=memory_usage,
disk_percent=disk_usage
)