企业级 Django 日志配置示例

发布于:2025-09-08 ⋅ 阅读:(14) ⋅ 点赞:(0)

settings.py 日志配置

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# 日志目录
LOG_DIR = os.path.join(BASE_DIR, "logs")
os.makedirs(LOG_DIR, exist_ok=True)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 不屏蔽已有的 logger
    'formatters': {
        'verbose': {  # 详细格式
            'format': '[{asctime}] [{levelname}] [{name}] '
                      '[PID:{process}] [TID:{thread}] '
                      '{message}',
            'style': '{',
            'datefmt': '%Y-%m-%d %H:%M:%S'
        },
        'simple': {  # 简单格式
            'format': '[{levelname}] {message}',
            'style': '{'
        },
        'json': {  # JSON 格式(方便 ELK/Splunk)
            'format': '{{"time": "{asctime}", "level": "{levelname}", '
                      '"logger": "{name}", "message": "{message}"}}',
            'style': '{',
            'datefmt': '%Y-%m-%dT%H:%M:%S'
        }
    },
    'handlers': {
        'console': {  # 控制台输出
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'info_file': {  # 普通业务日志
            'level': 'INFO',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': os.path.join(LOG_DIR, 'app_info.log'),
            'when': 'midnight',  # 每天切割
            'backupCount': 30,   # 保留 30 天
            'encoding': 'utf-8',
            'formatter': 'verbose'
        },
        'error_file': {  # 错误日志
            'level': 'ERROR',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': os.path.join(LOG_DIR, 'app_error.log'),
            'when': 'midnight',
            'backupCount': 60,
            'encoding': 'utf-8',
            'formatter': 'verbose'
        },
        'audit_file': {  # 审计日志(单独存)
            'level': 'INFO',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': os.path.join(LOG_DIR, 'audit.log'),
            'when': 'midnight',
            'backupCount': 180,  # 保留半年
            'encoding': 'utf-8',
            'formatter': 'json'
        }
    },
    'loggers': {
        'django': {  # Django 自带日志
            'handlers': ['console', 'info_file', 'error_file'],
            'level': 'INFO',
            'propagate': True
        },
        'audit': {  # 审计日志专用 logger
            'handlers': ['audit_file'],
            'level': 'INFO',
            'propagate': False
        },
        'myapp': {  # 业务日志
            'handlers': ['console', 'info_file', 'error_file'],
            'level': 'DEBUG',
            'propagate': False
        }
    }
}

基础路径和日志目录

BASE_DIR = Path(__file__).resolve().parent.parent
LOG_DIR = os.path.join(BASE_DIR, "logs")
os.makedirs(LOG_DIR, exist_ok=True)
  • BASE_DIR:项目根目录路径。

  • LOG_DIR:日志文件存放目录(logs 文件夹)。

  • os.makedirs(..., exist_ok=True):如果目录不存在则创建,避免写日志时报错。

LOGGING 配置结构

Django 的 LOGGING 配置遵循 Python logging 模块的字典配置格式,主要分为:

  • version:固定为 1

  • disable_existing_loggersFalse 表示不屏蔽 Django 默认的日志器。

  • formatters:定义日志输出格式。

  • handlers:定义日志输出方式(控制台、文件等)。

  • loggers:定义具体的日志记录器(logger),指定用哪些 handler 和日志级别。

formatters(日志格式)

'verbose': {  # 详细格式
    'format': '[{asctime}] [{levelname}] [{name}] '
              '[PID:{process}] [TID:{thread}] '
              '{message}',
    'style': '{',
    'datefmt': '%Y-%m-%d %H:%M:%S'
},
'simple': {  # 简单格式
    'format': '[{levelname}] {message}',
    'style': '{'
},
'json': {  # JSON 格式(方便 ELK/Splunk)
    'format': '{{"time": "{asctime}", "level": "{levelname}", '
              '"logger": "{name}", "message": "{message}"}}',
    'style': '{',
    'datefmt': '%Y-%m-%dT%H:%M:%S'
}
  • verbose:详细日志,包含时间、级别、logger 名称、进程 ID、线程 ID、消息。

  • simple:简化版,只显示级别和消息。

  • json:结构化 JSON 格式,方便日志收集系统(ELK、Splunk)解析。

handlers(日志输出方式)

'console': {  # 控制台输出
    'level': 'DEBUG',
    'class': 'logging.StreamHandler',
    'formatter': 'simple'
},
'info_file': {  # 普通业务日志
    'level': 'INFO',
    'class': 'logging.handlers.TimedRotatingFileHandler',
    'filename': os.path.join(LOG_DIR, 'app_info.log'),
    'when': 'midnight',  # 每天切割
    'backupCount': 30,   # 保留 30 天
    'encoding': 'utf-8',
    'formatter': 'verbose'
},
'error_file': {  # 错误日志
    'level': 'ERROR',
    'class': 'logging.handlers.TimedRotatingFileHandler',
    'filename': os.path.join(LOG_DIR, 'app_error.log'),
    'when': 'midnight',
    'backupCount': 60,
    'encoding': 'utf-8',
    'formatter': 'verbose'
},
'audit_file': {  # 审计日志(单独存)
    'level': 'INFO',
    'class': 'logging.handlers.TimedRotatingFileHandler',
    'filename': os.path.join(LOG_DIR, 'audit.log'),
    'when': 'midnight',
    'backupCount': 180,  # 保留半年
    'encoding': 'utf-8',
    'formatter': 'json'
}
  • console:输出到终端,调试用。

  • info_file:业务日志,按天切割,保留 30 天。

  • error_file:错误日志,按天切割,保留 60 天。

  • audit_file:审计日志(安全相关),按天切割,保留半年,JSON 格式。

TimedRotatingFileHandler 会在每天午夜生成新文件,旧文件按 backupCount 保留。

loggers(日志记录器)

'django': {  # Django 自带日志
    'handlers': ['console', 'info_file', 'error_file'],
    'level': 'INFO',
    'propagate': True
},
'audit': {  # 审计日志专用 logger
    'handlers': ['audit_file'],
    'level': 'INFO',
    'propagate': False
},
'myapp': {  # 业务日志
    'handlers': ['console', 'info_file', 'error_file'],
    'level': 'DEBUG',
    'propagate': False
}
  • django:Django 内部日志(SQL、请求等)。

  • audit:专门记录安全审计事件(登录、权限变更等)。

  • myapp:你的业务模块日志。

propagate 表示是否向上冒泡到父 logger,False 表示只用自己定义的 handlers。

使用方式

import logging

# 业务日志
logger = logging.getLogger('myapp')
logger.info("用户访问首页")
logger.error("数据库连接失败", exc_info=True)

# 审计日志
audit_logger = logging.getLogger('audit')
audit_logger.info({
    "event": "login_success",
    "username": "admin",
    "ip": "192.168.1.10",
    "ua": "Mozilla/5.0 ..."
})

使用方法

1. 普通业务日志

import logging
logger = logging.getLogger('myapp')

logger.info("用户访问首页")
logger.error("数据库连接失败", exc_info=True)

2. 审计日志(安全追踪)

import logging
audit_logger = logging.getLogger('audit')

audit_logger.info({
    "event": "login_success",
    "username": user.username,
    "ip": request.META.get('REMOTE_ADDR'),
    "ua": request.META.get('HTTP_USER_AGENT')
})

审计日志会单独写入 logs/audit.log,且是 JSON 格式,方便后续接入 ELK/Splunk 分析。

企业级建议

  • 开发环境console 输出 DEBUG 级别,方便调试

  • 生产环境:文件日志为主,控制台只输出 WARNING 及以上

  • 日志切割:用 TimedRotatingFileHandler 按天切割,防止单个文件过大

  • 安全日志:审计日志单独存储,且长期保留(半年或一年)

  • 集中化:生产环境建议把日志推送到 ELK、阿里云日志、腾讯 CLS 等平台


网站公告

今日签到

点亮在社区的每一天
去签到