logging_best_practices.md 3.0 KB

日志配置最佳实践

问题背景

在项目中出现了重复日志的问题,主要原因是:

  1. 多重日志处理器配置:多个模块都手动配置了 StreamHandler
  2. 日志传播机制:子 logger 的日志会传播到父 logger,如果都有处理器就会重复输出
  3. 缺乏统一配置:各个模块独立配置日志,没有统一的配置模式

解决方案

1. 统一日志配置工具

创建了 app/utils/logger_config.py 提供统一的日志配置功能:

from app.utils.logger_config import get_api_logger

# 在API模块中使用
logger = get_api_logger(__name__)
logger.info("这是API日志")

2. 避免重复配置的关键点

# ✅ 正确的配置方式
logger = logging.getLogger(__name__)
if not logger.handlers:  # 检查是否已配置
    logger.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.propagate = False  # 关闭传播,避免重复输出

# ❌ 错误的配置方式(会导致重复日志)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()  # 每次都添加新的处理器
logger.addHandler(handler)  # 重复添加处理器

3. 不同模块的使用方式

API模块

from app.utils.logger_config import get_api_logger

logger = get_api_logger(__name__)
logger.info("API操作日志")

Service模块

from app.utils.logger_config import get_service_logger

logger = get_service_logger(__name__)
logger.info("业务逻辑日志")

工具模块

from app.utils.logger_config import get_utils_logger

logger = get_utils_logger(__name__)
logger.info("工具函数日志")

修复的文件

已修复以下文件中的重复日志配置:

  1. app/api/water.py - 添加了处理器检查和传播控制
  2. app/api/cd_flux.py - 添加了处理器检查和传播控制
  3. app/services/cd_flux_service.py - 添加了处理器检查和传播控制
  4. app/utils/mapping_utils.py - 已经有正确的配置

测试方法

运行演示脚本来验证修复效果:

conda activate GeoSys
python scripts/demos/logging_demo.py

最佳实践总结

  1. 使用统一配置工具:优先使用 app/utils/logger_config.py 中的函数
  2. 检查处理器:配置前检查 if not logger.handlers:
  3. 控制传播:设置 logger.propagate = False 避免重复输出
  4. 避免重复配置:不要在多个地方配置同一个logger
  5. 根日志配置:只在应用启动时配置一次根日志系统

注意事项

  • 在类中使用日志时,建议在 __init__ 方法中配置,避免每次调用都重新配置
  • 对于 FastAPI 应用,uvicorn 已经有自己的日志配置,避免与其冲突
  • 测试环境和生产环境可能需要不同的日志级别和输出方式