Django 日志实战:settings.py 配置、请求日志与生产化落地

Django 日志怎么配?本文讲解 Django 基于标准库 logging 的 LOGGING 配置字典、内置 logger 体系(django.request 等)、自定义业务 logger、生产 JSON 结构化与多 handler 分流,并给出接入观测云实现集中检索与告警的路径。

最佳实践
Django 日志实战:settings.py 配置、请求日志与生产化落地技术指南封面

Django 日志基于 Python 标准库 logging 模块实现,通过 settings.py 中的 LOGGING 配置字典统一定义格式、handler 与 logger,同时框架内置了 django.request、django.server 等一批按职责划分的 logger。 理解"Django 自己没有发明日志体系,而是给标准库包了一层配置约定",就抓住了全部关键。

核心要点速览

  • Django 日志 = 标准库 logging + settings.py 里的 LOGGING 字典(dictConfig 格式);
  • 内置 logger 各有分工:django.request 记 4xx/5xx、django.server 记开发服务器请求、django.db.backends 记 SQL;
  • 业务代码用 logging.getLogger(__name__) 建模块 logger,配置集中在 settings.py
  • 生产 JSON 化用 python-json-logger,采集上报交给 DataKit + 观测云。

内置 logger 都在记什么?

Logger 记录内容
django 兜底父 logger,捕获未细分的事件
django.request HTTP 请求相关:5xx 记 ERROR、4xx 记 WARNING
django.server runserver 开发服务器的请求行
django.db.backends 数据库 SQL 语句(DEBUG 级)
django.security.* 安全事件(SuspiciousOperation 等)

不给任何配置时,Django 默认只把 django logger 的 WARNING 及以上输出到控制台——所以默认状态下你看到的大多是 500 报错。

LOGGING 配置字典怎么写?

# settings.py
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,   # 关键:别禁用 Django 内置 logger
    "formatters": {
        "verbose": {
            "format": "{asctime} | {levelname} | {name} | {message}",
            "style": "{",
        },
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "verbose",
        },
        "file": {
            "class": "logging.handlers.RotatingFileHandler",
            "filename": BASE_DIR / "logs" / "django.log",
            "maxBytes": 10 * 1024 * 1024,
            "backupCount": 5,
            "formatter": "verbose",
        },
    },
    "loggers": {
        "django": {"handlers": ["console", "file"], "level": "INFO"},
        "myapp": {"handlers": ["console", "file"], "level": "DEBUG", "propagate": False},
    },
}

注意 disable_existing_loggers: False——设成 True 会把 Django 内置 logger 全部静默,是很多"配置后反而没日志"事故的根源。

业务代码中:

# myapp/views.py
import logging

logger = logging.getLogger(__name__)

def order_create(request):
    logger.info("创建订单", extra={"user_id": request.user.id})
    try:
        ...
    except Exception:
        logger.exception("订单创建失败")

生产化:JSON 输出与请求 ID

Web 服务的日志最终要进平台检索,JSON 是必选项:

"formatters": {
    "json": {
        "()": "pythonjsonlogger.jsonlogger.JsonFormatter",
        "format": "%(asctime)s %(levelname)s %(name)s %(message)s",
        "rename_fields": {"levelname": "level", "asctime": "time"},
    },
},

请求级追踪可以加一个简单中间件,为每个请求生成 request_id 并通过 LoggerAdapterextra 透传;需要更完整的方案(自动绑定 IP、UA、用户、request_id)可直接用 django-structlog(见本系列《Structlog 实战指南》)。

接入观测云

观测云落地:部署形态决定采集方式——容器化部署让 Django(经 Gunicorn/uWSGI)输出 JSON 到 stdout,DataKit 容器采集;虚拟机部署采集 logs/django.log 文件 。Pipeline 确认 time/status 标准字段映射(ERROR/CRITICAL → errorWARNING → warning)。随后:

  • 日志查看器:按 name: django.request 过滤框架日志,按自定义字段(user_id、request_id)追踪业务链路 ;
  • 监控器(日志检测):对"5xx 计数超阈值""SuspiciousOperation 出现"等配置告警,推送钉钉/企业微信/飞书 ;
  • 链路关联:接入观测云 APM(支持 OpenTelemetry/ddtrace 方式的 Python 探针)并把 trace_id 注入日志,实现 Trace 与日志双向跳转 。

总结

Django 日志三板斧:LOGGING 字典集中配置、disable_existing_loggers 保持 False、生产 JSON 输出交给采集器。框架自带的 django.request 已经帮你盯住 4xx/5xx,剩下的就是把业务 logger 建起来、把日志汇入观测云。

常见问题(FAQ)

Q:配了 LOGGING 后 Django 自带的报错日志不见了?
多半是设置了 disable_existing_loggers: True,它会禁用所有已存在的 logger(包括 Django 内置的)。改为 False 即可。

Q:如何在日志里记录每个请求的 ID?
轻量做法:写中间件生成 uuid 放入 request,视图里通过 extra={"request_id": ...} 传递;完整做法:使用 django-structlog,中间件自动绑定 request_id/IP/UA 到全部请求日志。

Q:Django 的 SQL 日志能在生产开吗?
不建议。django.db.backends 的 DEBUG 级 SQL 日志量巨大且可能含敏感参数。排查慢查询请用观测云 APM 的数据库追踪能力,而不是开 SQL 日志。

Q:Gunicorn 部署后日志去哪了?
Gunicorn 有自己的 access/error 日志配置(--access-logfile - 输出到 stdout)。容器化部署把所有输出(Django + Gunicorn)都指向 stdout,由 DataKit 统一采集即可。


系列阅读:Python 日志模块详解Flask 日志实战

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台