import atexit import sys from fluent import sender from loguru import logger from pathlib import Path from config.setting import settings FLUENTD_HOST = 'host.docker.internal' FLUENTD_PORT = 24224 TOPIC_TAG = 'blog-service' # 日志目录 LOG_DIR = Path(__file__).parent.parent / "logs" LOG_DIR.mkdir(exist_ok=True) # 日志级别 LOG_LEVEL = settings.LOG_LEVEL.upper() # 日志格式 STDOUT_FORMAT = ( "{time:YYYY-MM-DD HH:mm:ss.SSS} | " "{level: <8} | " "{name}:{function}:{line} - " "{message}" ) FILE_FORMAT = ( "{time:YYYY-MM-DD HH:mm:ss.SSS} | " "{level: <8} | " "{name}:{function}:{line} - {message}" ) fluent_sender = sender.FluentSender( tag=TOPIC_TAG, host=FLUENTD_HOST, port=FLUENTD_PORT, buffer_max_size=8 * 1024 * 1024, timeout=3.0, retry_timeout=60 ) def log_to_fluent(message): try: record = message.record # 构建结构化日志数据 log_data = { 'topic': TOPIC_TAG, 'timestamp': record['time'].timestamp(), 'level': record['level'].name.lower(), 'message': record['message'], 'source': f"{record['file'].path}:{record['line']}", 'module': record['module'], 'function': record['function'], 'process_id': record['process'].id, 'thread_id': record['thread'].id, **record['extra'] } if not fluent_sender.emit(TOPIC_TAG, log_data): print(f"Fluentd 发送失败: {fluent_sender.last_error}") except Exception as e: print(f"日志处理异常: {str(e)}") # 移除默认处理器 logger.remove() # 添加控制台处理器 logger.add( sink=sys.stdout, level=LOG_LEVEL, format=STDOUT_FORMAT, colorize=True, backtrace=True, # 显示完整异常堆栈 diagnose=True, # 显示详细异常信息 ) logger.add( log_to_fluent, level="INFO", # 处理 INFO 及以上级别 format="{message}", # 原始消息(实际使用结构化数据) backtrace=True, # 启用堆栈回溯 diagnose=True # 显示诊断信息 ) # # 添加文件处理器 - 常规日志 # logger.add( # sink=LOG_DIR / "app.log", # level="INFO", # format=FILE_FORMAT, # rotation="10 MB", # 日志文件大小达到10MB时自动分割 # retention="7 days", # 保留7天的日志 # compression="zip", # 归档时压缩为zip # enqueue=True, # 异步写入 # serialize=False, # 不使用JSON格式 # ) # # # 添加文件处理器 - 错误日志 # logger.add( # sink=LOG_DIR / "error.log", # level="ERROR", # format=FILE_FORMAT, # rotation="10 MB", # retention="30 days", # compression="zip", # enqueue=True, # serialize=False, # ) atexit.register(fluent_sender.close) # 导出配置好的logger __all__ = ["logger"]