日志

Django 的日志模块扩展了 Python 内置的 logging

日志记录是作为 Django 的通用 django.setup() 函数的一部分进行配置的,因此除非明确禁用,否则始终可用。

Django 的默认日志配置

默认情况下,Django 使用 Python 的 logging.config.dictConfig 格式

默认的日志记录条件

完整的默认日志记录条件如下:

DEBUGTrue 时:

  • django 记录器将 django 层次结构(django.server 除外)中的 INFO 级别或更高的消息发送到控制台。

DEBUGFalse 时:

  • django 记录器将 django 层次结构(django.server 除外)中带有 ERRORCRITICAL 级别的消息发送到 AdminEmailHandler

无论 DEBUG 的值如何:

  • django.server 记录器向控制台发送 INFO 或更高等级的消息。

除了 django.server 之外,所有的日志记录器都会将日志记录传播给它们的父辈,直到 django 的根日志记录器。consolemail_admins 处理程序被附加到根记录器上,以提供上述行为。

Python 的默认设置会将级别为 WARNING 及更高级别的记录发送到控制台。

默认的日志定义

Django 的默认日志配置继承了 Python 的默认设置。它以 django.utils.log.DEFAULT_LOGGING 的形式可用,并在 django/utils/log.py 中定义如下:

{
    "version": 1,
    "disable_existing_loggers": False,
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse",
        },
        "require_debug_true": {
            "()": "django.utils.log.RequireDebugTrue",
        },
    },
    "formatters": {
        "django.server": {
            "()": "django.utils.log.ServerFormatter",
            "format": "[{server_time}] {message}",
            "style": "{",
        }
    },
    "handlers": {
        "console": {
            "level": "INFO",
            "filters": ["require_debug_true"],
            "class": "logging.StreamHandler",
        },
        "django.server": {
            "level": "INFO",
            "class": "logging.StreamHandler",
            "formatter": "django.server",
        },
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler",
        },
    },
    "loggers": {
        "django": {
            "handlers": ["console", "mail_admins"],
            "level": "INFO",
        },
        "django.server": {
            "handlers": ["django.server"],
            "level": "INFO",
            "propagate": False,
        },
    },
}

请参阅 日志模块的配置 了解如何补充或替换此默认日志配置。

Django 日志扩展

Django 提供了许多工具来处理在 Web 服务器环境中的日志记录特定要求。

Loggers

Django 提供了几种内置的记录器。

django

django 命名的日志层次结构 中,用于消息的父日志记录器。Django 不使用这个名称发布消息。而是使用以下其中一个日志记录器。

django.request

记录与处理请求有关的信息。5XX 的响应以 ERROR 消息的形式出现;4XX 的响应以 WARNING 消息的形式出现。记录在 django.security 记录器中的请求不会记录在 django.request 中。

发送给此记录器的消息有以下额外的上下文:

  • status_code:与请求相关的 HTTP 响应代码。
  • request:产生记录信息的请求对象。

django.server

记录与处理由 runserver 命令调用的服务器收到的请求有关的消息。HTTP 5XX 响应被记录为 ERROR 消息,4XX 响应被记录为 WARNING 消息,其他所有消息被记录为 INFO

发送给此记录器的消息有以下额外的上下文:

  • status_code:与请求相关的 HTTP 响应代码。
  • request:生成日志消息的请求对象(一个 socket.socket)。

django.template

记录与模板渲染相关的消息。

  • 缺少的上下文变量会被记录为 DEBUG 消息。

django.db.backends

与代码与数据库互动有关的信息。例如,请求执行的每一条应用程序级别的 SQL 语句都会以 DEBUG 级别记录到这个记录器。

发送给此记录器的消息有以下额外的上下文:

  • duration:执行 SQL 语句所需时间。
  • sql:所执行的 SQL 语句。
  • params:SQL 调用中使用的参数。
  • alias:SQL 调用中使用的数据库的别名。

出于性能考虑,只有当 settings.DEBUG 设置为 True 时,才会启用 SQL 日志记录,而不考虑日志级别或安装的处理程序。

这个日志记录不包括框架级别的初始化(例如 SET TIMEZONE)。如果希望查看所有数据库查询,请在数据库中启用查询日志记录。

Changed in Django 4.2:

已添加对事务管理查询(BEGINCOMMITROLLBACK)的日志记录支持。

django.security.*

安全记录器将接收任何发生 SuspiciousOperation 和其他安全相关错误的消息。每个子类型的安全错误都有一个子记录器,包括所有 SuspiciousOperations。日志事件的级别取决于异常处理的位置。 大多数发生的事件被记录为警告,而任何到达 WSGI 处理程序的 SuspiciousOperation 将被记录为错误。例如,当客户端的请求中包含一个 HTTP Host 头,而这个头不符合 ALLOWED_HOSTS 时,Django 会返回一个 400 的响应,并且错误信息会被记录到 django.security.DisallowedHost 记录器中。

这些日志事件默认会到达 django 日志器,当 DEBUG=False 时,记录器会将错误事件发送给管理员。由于 SuspiciousOperation 导致 400 响应的请求不会被记录到 django.request 记录器,而只会记录到 django.security 记录器。

要使某一特定类型的 SuspiciousOperation 保持沉默,你可以按照以下示例覆盖该特定的记录器:

LOGGING = {
    # ...
    "handlers": {
        "null": {
            "class": "logging.NullHandler",
        },
    },
    "loggers": {
        "django.security.DisallowedHost": {
            "handlers": ["null"],
            "propagate": False,
        },
    },
    # ...
}

其他不基于 SuspiciousOperationdjango.security 记录器是:

django.db.backends.schema

记录 migrations framework 对数据库进行模式变更时执行的 SQL 查询。请注意,它不会记录 RunPython 执行的查询。给这个记录器的消息在其额外的上下文中有 paramssql (但与 django.db.backends 不同,不是 duration)。这些值的含义与 django.db.backends 中的解释相同。

Handlers

除了 Python 日志模块提供的处理程序外,Django 还提供了一个日志处理程序。

class AdminEmailHandler(include_html=False, email_backend=None, reporter_class=None)

该处理程序对收到的每条日志消息都会向站点 ADMINS 发送一封邮件。

如果日志记录中包含 request 属性,电子邮件中会包含请求的全部细节。如果客户的 IP 地址在 INTERNAL_IPS 设置中,电子邮件主题将包括“内部 IP”;如果没有,则包括“外部 IP”。

如果日志记录中包含堆栈跟踪信息,该堆栈跟踪信息将包含在电子邮件中。

AdminEmailHandlerinclude_html 参数用于控制是否在 traceback 邮件中包含一个 HTML 附件,该附件包含了如果 DEBUGTrue 时会生成的完整调试网页的内容。要在配置中设置此值,将其包含在 django.utils.log.AdminEmailHandler 的处理程序定义中,如下所示:

"handlers": {
    "mail_admins": {
        "level": "ERROR",
        "class": "django.utils.log.AdminEmailHandler",
        "include_html": True,
    },
}

在使用 AdminEmailHandler 时要注意 日志记录的安全性影响

通过设置 AdminEmailHandleremail_backend 参数,处理程序使用的 email 后端 可以被覆盖,就像这样:

"handlers": {
    "mail_admins": {
        "level": "ERROR",
        "class": "django.utils.log.AdminEmailHandler",
        "email_backend": "django.core.mail.backends.filebased.EmailBackend",
    },
}

默认情况下,将使用 EMAIL_BACKEND 中指定的电子邮件后端实例。

AdminEmailHandlerreporter_class 参数允许提供一个 django.view.debug.ExceptionReporter 子类来自定义邮件正文中发送的回溯文本。你提供一个字符串的导入路径到你想使用的类,像这样:

"handlers": {
    "mail_admins": {
        "level": "ERROR",
        "class": "django.utils.log.AdminEmailHandler",
        "include_html": True,
        "reporter_class": "somepackage.error_reporter.CustomErrorReporter",
    },
}
send_mail(subject, message, *args, **kwargs)

向管理员用户发送邮件。要自定义这个行为,你可以将 AdminEmailHandler 类子类化,并覆盖这个方法。

过滤器

除了 Python 日志模块提供的日志过滤器外,Django 还提供了一些日志过滤器。

class CallbackFilter(callback)

这个过滤器接受一个回调函数(它应该接受一个单一的参数,即要记录的记录),并对每个通过过滤器的记录进行调用。如果回调函数返回 False,则不会对该记录进行处理。

例如,要从管理员邮件中过滤掉 UnreadablePostError (当用户取消上传时引发),你可以创建一个过滤函数:

from django.http import UnreadablePostError


def skip_unreadable_post(record):
    if record.exc_info:
        exc_type, exc_value = record.exc_info[:2]
        if isinstance(exc_value, UnreadablePostError):
            return False
    return True

然后将其添加到你的日志记录配置中:

LOGGING = {
    # ...
    "filters": {
        "skip_unreadable_posts": {
            "()": "django.utils.log.CallbackFilter",
            "callback": skip_unreadable_post,
        },
    },
    "handlers": {
        "mail_admins": {
            "level": "ERROR",
            "filters": ["skip_unreadable_posts"],
            "class": "django.utils.log.AdminEmailHandler",
        },
    },
    # ...
}
class RequireDebugFalse

只有当 settings.DEBUG 为 False 时,该过滤器才会传递记录。

该过滤器在默认的 logging 配置中使用如下,以确保 AdminEmailHandler 只在 DEBUGFalse 时向管理员发送错误邮件:

LOGGING = {
    # ...
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse",
        },
    },
    "handlers": {
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler",
        },
    },
    # ...
}
class RequireDebugTrue

该过滤器类似于 RequireDebugFalse,但只有当 DEBUGTrue 时才会传递记录。

Back to Top