日志

Django's logging module extends Python's builtin logging.

Logging is configured as part of the general Django django.setup() function, so it's always available unless explicitly disabled.

Django 的默认日志配置

By default, Django uses Python's logging.config.dictConfig format.

Default logging conditions

The full set of default logging conditions are:

DEBUGTrue 时:

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

DEBUGFalse 时:

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

Independently of the value of DEBUG:

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

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

Python's own defaults send records of level WARNING and higher to the console.

Default logging definition

Django's default logging configuration inherits Python's defaults. It's available as django.utils.log.DEFAULT_LOGGING and defined in 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,
        },
    },
}

See 日志模块的配置 on how to complement or replace this default logging configuration.

Django logging extensions

Django provides a number of utilities to handle the particular requirements of logging in a web server environment.

Loggers

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

django

The parent logger for messages in the django named logger hierarchy. Django does not post messages using this name. Instead, it uses one of the loggers below.

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:产生记录信息的请求对象。

django.template

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

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

django.db.backends

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

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

  • duration:执行 SQL 语句所需时间。
  • sql:所执行的 SQL 语句。
  • params:SQL 调用中使用的参数。
  • alias: The alias of the database used in the SQL call.

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

This logging does not include framework-level initialization (e.g. SET TIMEZONE). Turn on query logging in your database if you wish to view all database queries.

Changed in Django 4.2:

Support for logging transaction management queries (BEGIN, COMMIT, and ROLLBACK) was added.

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

Django provides one log handler in addition to those provided by the Python logging module.

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

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

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

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

The include_html argument of AdminEmailHandler is used to control whether the traceback email includes an HTML attachment containing the full content of the debug web page that would have been produced if DEBUG were True. To set this value in your configuration, include it in the handler definition for django.utils.log.AdminEmailHandler, like this:

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

Be aware of the security implications of logging when using the 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 时才会传递记录。