# 日志系统配置 import logging import json import os from datetime import datetime from typing import Optional import uuid from logging.handlers import RotatingFileHandler class JSONFormatter(logging.Formatter): """JSON 格式日志处理器""" def format(self, record): log_data = { 'timestamp': datetime.now().strftime('%Y-%m-%dT%H:%M:%S'), 'level': record.levelname, 'logger': record.name, 'message': record.getMessage(), 'trace_id': getattr(record, 'trace_id', str(uuid.uuid4())), 'user_id': getattr(record, 'user_id', None), 'request_id': getattr(record, 'request_id', str(uuid.uuid4())), 'ip_address': getattr(record, 'ip_address', None), 'duration_ms': getattr(record, 'duration_ms', None), } # 添加额外字段 if hasattr(record, 'data'): log_data['data'] = record.data # 添加异常信息 if record.exc_info: log_data['exception'] = self.formatException(record.exc_info) return json.dumps(log_data, ensure_ascii=False, default=str) def setup_logging( log_file: str = 'logs/app.log', level: str = 'INFO', max_bytes: int = 10*1024*1024, # 10MB backup_count: int = 5 ): """配置日志系统""" # 创建日志目录 os.makedirs(os.path.dirname(log_file), exist_ok=True) # 根日志器 logger = logging.getLogger() logger.setLevel(level) # 清空现有处理器 logger.handlers.clear() # 文件处理器(带轮转) file_handler = RotatingFileHandler( log_file, maxBytes=max_bytes, backupCount=backup_count, encoding='utf-8' ) file_handler.setFormatter(JSONFormatter()) logger.addHandler(file_handler) # 控制台处理器(仅开发环境) if os.getenv('ENV', 'development') == 'development': console_handler = logging.StreamHandler() console_handler.setFormatter(JSONFormatter()) logger.addHandler(console_handler) return logger # 创建日志器实例 logger = setup_logging() # 日志装饰器 def log_operation(operation_name: str): """记录操作日志的装饰器""" def decorator(func): import functools @functools.wraps(func) def wrapper(*args, **kwargs): import time start_time = time.time() try: result = func(*args, **kwargs) duration = (time.time() - start_time) * 1000 logger.info( f"{operation_name} 成功", extra={ 'duration_ms': duration, 'data': {'function': func.__name__} } ) return result except Exception as e: duration = (time.time() - start_time) * 1000 logger.error( f"{operation_name} 失败:{str(e)}", extra={ 'duration_ms': duration, 'data': {'function': func.__name__, 'error': str(e)} }, exc_info=True ) raise return wrapper return decorator