Django 用 Loguru 完美替换标准 Logging,实现优雅的日志管理方案

Django 用 Loguru 完美替换标准 Logging,实现优雅的日志管理方案

这篇文章将详细拆解如何将强大的 loguru 库深度集成到 Django 项目中,彻底解决原生 logging 配置冗长、难以维护的痛点。


为什么要进行方案替换

Django 默认的日志配置通过 LOGGING 字典实现,嵌套层级多且语法繁琐。相比之下,loguru 提供了更直观的 API 和自动化的日志轮转管理。

核心技术要点

  • 全量拦截 :通过自定义 InterceptHandler 类,将 Django 内置、Gunicorn 容器以及第三方库产生的标准 logging 消息全部重定向至 loguru

  • 精准溯源 :利用 sys._getframe 动态查找调用栈,确保日志中显示的文件名和行号是真实的业务逻辑位置,而非拦截器本身。

  • 自动化策略:配置文件输出时,只需一行代码即可实现凌晨定时切割日志(rotation)和 30 天自动清理(retention)。

  • 并发安全 :开启 enqueue=True 选项,利用多线程/进程安全的队列机制,防止高并发下日志写入冲突。

部署实践:一键接管 Django 日志

在项目中创建日志工具模块后,只需在 settings.py 顶部导入,并设置 LOGGING_CONFIG = None 即可禁用 Django 原生逻辑。

Python

复制代码
import os
import sys
import logging
from pathlib import Path
from loguru import logger

# 路径初始化
BASE_DIR = Path(__file__).resolve().parent.parent
log_dir = os.path.join(BASE_DIR, "logs")
log_file_path = os.path.join(log_dir, "dt_test.log")
if not os.path.exists(log_dir):
    os.makedirs(log_dir)

# 拦截器定义:核心在于深度(depth)的计算
class InterceptHandler(logging.Handler):
    def emit(self, record):
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno
        frame, depth = sys._getframe(6), 6
        while frame and frame.f_code.co_filename == logging.__file__:
            frame = frame.f_back
            depth += 1
        logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())

# 彻底接管配置
LOGGING_CONFIG = None

def setup_loguru(debug_mode: bool = True):
    logger.remove()
    log_format = "{time:YYYY-MM-DD HH:mm:ss,SSS} | {level: <8} | {name} [{module}.{function}:{line}] | {message}"
    
    # 控制台调试输出
    if debug_mode:
        logger.add(sys.stdout, level="DEBUG", format=log_format, enqueue=True)

    # 文件持久化配置:支持每天凌晨切割与压缩
    logger.add(
        log_file_path, level="DEBUG", format=log_format, rotation="00:00", 
        retention="30 days", encoding="utf-8", enqueue=True, compression="zip"
    )

    # 重定向系统级日志
    logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
    for name in ["django", "django.server", "gunicorn.access", "gunicorn.error"]:
        _log = logging.getLogger(name)
        _log.handlers = [InterceptHandler()]
        _log.propagate = False

setup_loguru()

放在settings.py顶部或者原来日志配置信息全部删除后的地方

效果

相关推荐
hanxiuchao18 小时前
告别客户端臃肿!网页端 M3U8 播放调试方案,适配全办公场景
运维·python·django·m3u8·m3u8播放
程序员羽痕18 小时前
基于深度学习的眼疾识别系统
人工智能·pytorch·深度学习·分类·django
流云鹤1 天前
1. 配置环境、创建导航栏
python·django
流云鹤2 天前
2.登录模块
python·django
流云鹤2 天前
专题栏说明
python·django
XGeFei3 天前
【Django学习笔记】—— Django 高并发通俗讲解
笔记·学习·django
weixin_BYSJ19873 天前
springboot美食食谱小程序---附源码24044
java·spring boot·python·spring cloud·django·tomcat·php
许彰午4 天前
87_Python Django模型与数据库
数据库·python·django
weixin_BYSJ19874 天前
SpringBoot + MySQL 乒乓球运动员信息管理系统项目实战--附源码04954
java·javascript·spring boot·python·django·flask·php
Database_Cool_6 天前
RAG 混合检索首选:阿里云 Lindorm 向量+全文一体化检索
数据库·阿里云·django·云计算