Django日志系统配置详解
日志是应用程序运行状态的重要载体,为问题诊断和性能分析提供关键依据。在Django框架中,日志系统基于Python标准库的logging模块构建,提供了灵活且强大的记录机制。
日志记录的核心要素
每条日志条目包含以下关键信息:
- 时间戳:事件发生的精确时刻
- 位置标识:代码中的具体来源
- 严重等级:事件的紧急程度分类
- 详细描述:事件的具体内容说明
Python定义了五个标准日志等级,按严重程度递增:
| 等级 | 数值 | 用途说明 |
|---|---|---|
| DEBUG | 10 | 开发阶段的详细调试信息 |
| INFO | 20 | 常规运行状态报告 |
| WARNING | 30 | 潜在问题预警,不影响核心功能 |
| ERROR | 40 | 功能异常,需要关注处理 |
| CRITICAL | 50 | 严重故障,可能导致服务中断 |
Django日志架构组件
日志系统由四个协作组件构成:
记录器(Logger)
作为日志系统的入口点,Logger承担三项职责:
- 向应用代码暴露记录接口(debug()、info()、warning()、error()、critical())
- 基于自身配置的阈值等级过滤传入的消息
- 将符合条件的消息分发给关联的处理器
消息等级匹配规则:当传入消息的等级数值≥Logger设定的等级时,该消息被接受处理。
处理器(Handler)
Handler决定日志的最终去向,常见类型包括:
- StreamHandler:输出到标准输出流
- FileHandler:写入磁盘文件
- RotatingFileHandler:按大小轮转的文件存储
- TimedRotatingFileHandler:按时间轮转的文件存储
- SMTPHandler:邮件告警发送
每个Handler可独立配置等级阈值,实现分级分流。例如:控制台显示DEBUG及以上信息,文件记录INFO及以上,邮件仅发送CRITICAL级别。
过滤器(Filter)
Filter在Logger到Handler的传递链中提供细粒度控制,支持:
- 基于自定义条件放行或拦截特定日志
- 动态修改日志记录的属性(如调整等级、附加上下文)
格式化器(Formatter)
Formatter定义输出字符串的模板结构,常用字段包括:
- %(asctime)s — 时间戳
- %(levelname)s — 等级名称
- %(name)s — Logger名称
- %(message)s — 日志内容
- %(pathname)s — 源文件完整路径
- %(lineno)d — 代码行号
- %(process)d — 进程ID
- %(thread)d — 线程ID
生产环境配置示例
以下配置实现了多通道分级日志策略:
import os
from pathlib import Path
# 项目根目录
PROJECT_ROOT = Path(__file__).resolve().parent.parent
# 日志存储目录
LOG_PATH = PROJECT_ROOT / "storage" / "logs"
LOG_PATH.mkdir(parents=True, exist_ok=True)
# 管理员接收告警邮箱
ADMIN_CONTACTS = [
("运维值班", "ops@example.com"),
("开发负责人", "dev@example.com"),
]
LOGGING_CONFIG = {
"version": 1,
"disable_existing_loggers": False,
"filters": {
"production_only": {
"()": "django.utils.log.RequireDebugFalse"
},
"debug_mode": {
"()": "django.utils.log.RequireDebugTrue"
}
},
"formatters": {
"detailed": {
"format": "{levelname} | {asctime} | {module}:{funcName}:{lineno} | {message}",
"style": "{",
"datefmt": "%Y-%m-%d %H:%M:%S"
},
"compact": {
"format": "[{levelname}] {asctime} {message}",
"style": "{",
"datefmt": "%H:%M:%S"
},
"json_style": {
"()": "pythonjsonlogger.jsonlogger.JsonFormatter",
"format": "%(levelname)s %(asctime)s %(name)s %(message)s"
}
},
"handlers": {
# 控制台输出(开发调试)
"terminal": {
"level": "DEBUG",
"filters": ["debug_mode"],
"class": "logging.StreamHandler",
"formatter": "compact"
},
# 应用日志文件(按大小轮转)
"app_file": {
"level": "INFO",
"class": "logging.handlers.RotatingFileHandler",
"filename": LOG_PATH / "application.log",
"maxBytes": 50 * 1024 * 1024, # 50MB
"backupCount": 10,
"formatter": "detailed",
"encoding": "utf-8"
},
# 错误日志文件(单独收集)
"err_file": {
"level": "ERROR",
"class": "logging.handlers.RotatingFileHandler",
"filename": LOG_PATH / "errors.log",
"maxBytes": 20 * 1024 * 1024, # 20MB
"backupCount": 5,
"formatter": "detailed",
"encoding": "utf-8"
},
# 邮件告警(生产环境)
"email_alert": {
"level": "ERROR",
"filters": ["production_only"],
"class": "django.utils.log.AdminEmailHandler",
"include_html": True,
"formatter": "compact"
}
},
"root": {
"level": "WARNING",
"handlers": ["terminal", "app_file"]
},
"loggers": {
# Django框架请求日志
"django.server": {
"level": "INFO",
"handlers": ["app_file"],
"propagate": False
},
# 数据库查询日志(调试用)
"django.db.backends": {
"level": "DEBUG",
"handlers": ["terminal"],
"propagate": False,
"filters": ["debug_mode"]
},
# 安全相关日志
"django.security": {
"level": "WARNING",
"handlers": ["err_file", "email_alert"],
"propagate": False
},
# 项目业务代码日志
"myproject": {
"level": "DEBUG",
"handlers": ["app_file", "err_file", "email_alert"],
"propagate": False
}
}
}
在代码中使用日志
推荐在每个模块中创建命名规范的Logger实例:
import logging
# 使用__name__确保层级命名空间
module_logger = logging.getLogger(__name__)
def process_payment(order_id, amount):
module_logger.info("开始处理订单支付", extra={
"order_id": order_id,
"amount": amount
})
try:
# 业务逻辑...
result = execute_transaction(order_id, amount)
module_logger.debug("支付网关返回: %s", result)
except PaymentException as exc:
module_logger.error(
"支付处理失败: %s",
exc,
exc_info=True, # 包含堆栈跟踪
extra={"order_id": order_id}
)
raise
通过extra参数附加结构化数据,便于后续日志分析和聚合查询。