第32章:日志管理系统
32.1 概述
日志管理系统是剪映小助手的核心基础设施之一,负责记录系统运行状态、调试信息和错误日志。该系统采用Python标准库logging实现,通过自定义格式化器和配置管理,提供了结构化、可读性强的日志输出,为系统调试、监控和故障排查提供重要支持。
32.2 核心组件设计
32.2.1 相对路径格式化器
RelativePathFormatter 类是日志系统的核心组件,用于在日志中显示相对路径:
python
class RelativePathFormatter(logging.Formatter):
def __init__(self, *args, project_root: Optional[str] = None, **kwargs):
super().__init__(*args, **kwargs)
# 把项目根目录传进来
self.project_root = project_root or os.getcwd()
def format(self, record: logging.LogRecord) -> str:
record.rel_path = os.path.relpath(record.pathname, self.project_root)
return super().format(record)
该格式化器通过计算日志记录文件相对于项目根目录的路径,使日志输出更加简洁清晰,便于快速定位问题代码位置。
32.2.2 日志配置结构
日志系统采用字典配置方式,定义了完整的日志格式和处理规则:
python
LOGGING_CONFIG = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"()": RelativePathFormatter,
"fmt": "%(asctime)s.%(msecs)03d | %(levelname)s | %(name)s | %(rel_path)s:%(lineno)d | %(message)s",
"datefmt": "%Y-%m-%d %H:%M:%S",
},
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
},
"loggers": {
"uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False},
"uvicorn.error": {"level": "INFO"},
"uvicorn.access": {"handlers": ["default"], "level": "INFO", "propagate": False},
"src.utils.logger": {"handlers": ["default"], "level": "INFO", "propagate": False}
},
}
32.3 日志格式详解
32.3.1 标准日志格式
系统采用结构化的日志格式,包含以下信息:
2024-01-15 14:30:25.123 | INFO | src.service.add_videos | src\service\add_videos.py:45 | 开始处理视频添加请求
格式说明:
- 时间戳:精确到毫秒的日期时间
- 日志级别:INFO、DEBUG、WARNING、ERROR、CRITICAL
- 模块名称:记录日志的模块路径
- 相对路径和行号:相对于项目根目录的文件路径和代码行号
- 日志消息:具体的日志内容
32.3.2 日志级别定义
系统支持标准的Python日志级别:
- DEBUG:详细的调试信息,主要用于开发环境
- INFO:一般信息,记录系统正常运行状态
- WARNING:警告信息,表示可能的问题但不影响系统运行
- ERROR:错误信息,表示系统运行中出现的问题
- CRITICAL:严重错误,可能导致系统崩溃的问题
32.4 集成与使用
32.4.1 配置加载
日志配置通过dictConfig函数加载到系统中:
python
dictConfig(LOGGING_CONFIG)
logger = logging.getLogger(__name__)
32.4.2 模块级日志记录器
每个模块都创建自己的日志记录器实例:
python
# 在模块顶部创建logger实例
logger = logging.getLogger(__name__)
# 在代码中使用logger记录日志
def some_function():
logger.info("函数开始执行")
try:
# 业务逻辑
result = do_something()
logger.debug(f"处理结果: {result}")
except Exception as e:
logger.error(f"处理失败: {str(e)}", exc_info=True)
raise
32.5 日志输出特性
32.5.1 相对路径显示
通过RelativePathFormatter实现相对路径显示:
python
# 绝对路径:d:\Github\capcut-mate\src\service\add_videos.py
# 相对路径显示:src\service\add_videos.py
这种显示方式使日志更加简洁,同时保留了足够的路径信息用于定位问题。
32.5.2 毫秒级时间精度
日志格式中的%(msecs)03d确保时间显示精确到毫秒:
2024-01-15 14:30:25.123 # 精确到毫秒
32.5.3 模块隔离
不同模块的日志记录器相互隔离,便于独立控制日志级别:
python
# Uvicorn服务器日志
"uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False}
# 访问日志
"uvicorn.access": {"handlers": ["default"], "level": "INFO", "propagate": False}
# 自定义模块日志
"src.utils.logger": {"handlers": ["default"], "level": "INFO", "propagate": False}
32.6 日志使用最佳实践
32.6.1 日志级别选择
python
# 记录系统状态变化
logger.info("草稿创建成功: %s", draft_id)
# 记录调试信息
logger.debug("视频参数: width=%d, height=%d, duration=%d", width, height, duration)
# 记录警告信息
logger.warning("文件大小接近限制: %dMB", file_size_mb)
# 记录错误信息
logger.error("视频添加失败: %s", error_msg, exc_info=True)
# 记录严重错误
logger.critical("系统配置错误: %s", config_error)
32.6.2 异常日志记录
python
try:
result = risky_operation()
except SomeException as e:
# 记录异常信息和堆栈
logger.error("操作失败: %s", str(e), exc_info=True)
# 或者使用exception方法(自动包含异常信息)
logger.exception("操作失败: %s", str(e))
32.6.3 性能考虑
python
# 避免在循环中频繁记录日志
for item in large_list:
# 不好的做法
logger.debug("处理项目: %s", item)
# 更好的做法
if logger.isEnabledFor(logging.DEBUG):
logger.debug("处理项目: %s", item)
32.7 扩展性设计
32.7.1 多处理器支持
日志配置支持添加多个处理器:
python
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
"file": {
"formatter": "default",
"class": "logging.FileHandler",
"filename": "app.log",
"mode": "a",
},
},
32.7.2 环境适配
相对路径格式化器支持自定义项目根目录:
python
formatter = RelativePathFormatter(
fmt="%(asctime)s | %(levelname)s | %(rel_path)s:%(lineno)d | %(message)s",
project_root="/custom/path/to/project"
)
32.7.3 动态配置
支持在运行时动态调整日志配置:
python
import logging
# 动态调整日志级别
logging.getLogger("uvicorn").setLevel(logging.DEBUG)
# 添加新的处理器
file_handler = logging.FileHandler("debug.log")
file_handler.setLevel(logging.DEBUG)
logging.getLogger().addHandler(file_handler)
32.8 日志管理优势
32.8.1 结构化输出
统一的日志格式便于日志收集和分析:
- 支持日志聚合工具(如ELK Stack)
- 便于编写日志解析规则
- 支持自动化监控和告警
32.8.2 开发友好
相对路径显示和精确时间戳为开发者提供便利:
- 快速定位问题代码位置
- 精确的性能分析
- 便于调试和故障排查
32.8.3 性能优化
合理的日志级别控制避免不必要的性能开销:
- 生产环境使用INFO级别
- 调试环境使用DEBUG级别
- 避免在热路径中记录过多日志
附录
代码仓库地址:
- GitHub:
https://github.com/Hommy-master/capcut-mate - Gitee:
https://gitee.com/taohongmin-gitee/capcut-mate
接口文档地址:
- API文档地址:
https://docs.jcaigc.cn