文章目录
- [日志不是 print------Python logging 模块的生产级用法](#日志不是 print——Python logging 模块的生产级用法)
日志不是 print------Python logging 模块的生产级用法
📖 文章简介: 大部分 Django 新手写日志的方式是 print(f"用户 {user.id} 登录成功")------在公司项目中这行代码迟早要被替换。print 没有日志级别、没有时间戳、不能按模块过滤、不能输出到文件或外部日志系统。本文从 logging 模块的四层架构(Logger / Handler / Formatter / Filter)讲起,覆盖 Django 项目的日志配置、日志轮转策略、结构化日志(JSON格式输出)以及与 ELK 系统的对接。穿插真实事故------因为没有日志导致一个订单丢失问题排查了三天。

🎬 个人主页: 源码骑士
❄ 专栏传送门: 《Android开发基础》《python基础课程》
⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂
🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以源码拆解为特色,被读者评价为"看一篇胜过啃一周文档"
导入语
2020 年,一个电商系统出现了一个 Bug------顾客支付了但订单状态没更新。DBA 查了数据库,发现某笔订单的 UPDATE 语句没执行。但我们不知道为什么没执行------因为那段代码里只有一行 print("更新订单"),而线上 Gunicorn 的 stdout 被重定向到了 Docker 日志------容器重启后全没了。
从那以后我定了一条规矩:所有 Django 项目必须使用 logging 模块,print 只能用于本地调试。
1 ~> logging 模块的四层架构
bash
Logger → Handler → Formatter → 输出目标(文件/控制台/ELK)
Logger: 记录日志的入口(每个模块一个 Logger)
Handler: 决定日志输出到哪里(文件、邮件、HTTP)
Formatter:决定日志的格式(时间、模块名、级别、消息)
Filter: 按条件过滤日志
1.1 基础使用
python
import logging
logger = logging.getLogger(__name__) # 每个模块用自己的 Logger
logger.debug("调试信息") # 10
logger.info("用户 %s 登录成功", user.id) # 20
logger.warning("磁盘使用率 85%") # 30
logger.error("数据库连接失败") # 40
logger.exception("异常信息", exc_info=True)# 自动包含堆栈
2 ~> Django 项目中的日志配置
python
# settings.py
LOGGING = {
"version": 1,
"disable_existing_loggers": False, # 保留 Django 内置日志
"formatters": {
"verbose": {
"format": "{levelname} {asctime} {module} {message}",
"style": "{",
},
"json": {
"format": '{"time":"%(asctime)s","level":"%(levelname)s","module":"%(module)s","message":"%(message)s"}',
},
},
"handlers": {
"file": {
"class": "logging.handlers.RotatingFileHandler",
"filename": "/var/log/django/app.log",
"maxBytes": 10 * 1024 * 1024, # 10MB 滚动
"backupCount": 5, # 保留 5 个旧日志文件
"formatter": "verbose",
},
"console": {
"class": "logging.StreamHandler",
"formatter": "verbose",
},
},
"loggers": {
"django": {
"handlers": ["file", "console"],
"level": "INFO",
"propagate": False,
},
"myapp": { # 你自己的应用
"handlers": ["file"],
"level": "DEBUG",
},
},
}
3 ~> 日志轮转------别让日志文件塞满磁盘
| Handler | 用途 |
|---|---|
RotatingFileHandler |
按文件大小轮转(达到N MB 自动切新文件) |
TimedRotatingFileHandler |
按时间轮转(每天/每小时一个新文件) |
python
"handlers": {
"daily": {
"class": "logging.handlers.TimedRotatingFileHandler",
"filename": "/var/log/django/app.log",
"when": "midnight", # 每天午夜切新文件
"backupCount": 30, # 保留最近 30 天日志
}
}
4 ~> 结构化日志------JSON 格式输出
生产环境推荐用 JSON 格式,方便 ELK(Elasticsearch + Logstash + Kibana)解析:
python
import json_log_formatter
LOGGING = {
"formatters": {
"json": {
"()": "json_log_formatter.VerboseJSONFormatter",
},
},
}
思考 && 总结
Python logging 三项必备:
- 日志分级------ DEBUG 只在开发本地打开,生产改为 INFO,ERROR 和 CRITICAL 触发告警。
RotatingFileHandler------ 别让日志文件无限增长。10MB 轮转 + 保留 5-10 个历史文件。- 结构化日志------ JSON 格式 + ELK 分析 = 可视化告警。print 做不到这些。
结尾
日志规范到这里讲完。感谢阅读!
源码骑士 --- 源码级拆解,从底层看透技术
👀 关注:跟博主一起从源码视角深耕底层原理
❤️ 点赞:让优质内容被更多人看见
⭐ 收藏:核心知识点存好,随用随查
💬 评论:分享你的经验或疑问,一起交流
🔄 一键四连:别忘了给博主一键四连!
🗡️ 寄语:print 让你看到当下,logging 让你能看到昨天。
结语:logging 不是 print 的高级版------是运维、排查、告警的基础设施。最后一篇收官------在线图书管理系统,从零到上线。一键四连!