29-Python-logging日志模块-print不是日志的生产级实战

文章目录

  • [日志不是 print------Python logging 模块的生产级用法](#日志不是 print——Python logging 模块的生产级用法)
    • 导入语
    • [1 ~> logging 模块的四层架构](#1 ~> logging 模块的四层架构)
      • [1.1 基础使用](#1.1 基础使用)
    • [2 ~> Django 项目中的日志配置](#2 ~> Django 项目中的日志配置)
    • [3 ~> 日志轮转------别让日志文件塞满磁盘](#3 ~> 日志轮转——别让日志文件塞满磁盘)
    • [4 ~> 结构化日志------JSON 格式输出](#4 ~> 结构化日志——JSON 格式输出)
    • [思考 && 总结](#思考 && 总结)
    • 结尾

📖 文章简介: 大部分 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 三项必备:

  1. 日志分级------ DEBUG 只在开发本地打开,生产改为 INFO,ERROR 和 CRITICAL 触发告警。
  2. RotatingFileHandler------ 别让日志文件无限增长。10MB 轮转 + 保留 5-10 个历史文件。
  3. 结构化日志------ JSON 格式 + ELK 分析 = 可视化告警。print 做不到这些。

结尾

日志规范到这里讲完。感谢阅读!

源码骑士 --- 源码级拆解,从底层看透技术

👀 关注:跟博主一起从源码视角深耕底层原理

❤️ 点赞:让优质内容被更多人看见

收藏:核心知识点存好,随用随查

💬 评论:分享你的经验或疑问,一起交流

🔄 一键四连:别忘了给博主一键四连!

🗡️ 寄语:print 让你看到当下,logging 让你能看到昨天。

结语:logging 不是 print 的高级版------是运维、排查、告警的基础设施。最后一篇收官------在线图书管理系统,从零到上线。一键四连!

相关推荐
疋瓞6 分钟前
python和C++对比(1)_数据类型和数据结构
数据结构·c++·python
C语言小火车19 分钟前
C++ 堆排序深度精讲:基于完全二叉树的选择排序进化,最坏情况 O(n log n) 的稳定王者
开发语言·c++·算法·排序算法·堆排序
北冥you鱼19 分钟前
abigen 最佳实践:从入门到精通,高效生成 Go 语言合约绑定
开发语言·golang·区块链
ALex_zry1 小时前
C++26 std::complex 结构化绑定详解:auto [re, im] = c
c语言·开发语言·c++
如此这般英俊1 小时前
手搓Claude Code-第六章 subagent
数据结构·人工智能·python·语言模型·自然语言处理
她说..2 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
元Y亨H2 小时前
Python - FastAPI 全方位介绍
python·fastapi
忧郁的紫菜2 小时前
基础实现:单篇 Markdown 转 Word
开发语言·c#·word
甜美的小天鹅2 小时前
Swifter C#之inline还是不inline,这是个问题
开发语言·c#
小短腿的代码世界2 小时前
Qt Bluetooth源码深度解析:从HCI协议到跨平台API的完整架构
开发语言·qt·架构