日志记录

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 服务器环境中日志记录的特定要求。

记录器

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)。如果您希望查看所有数据库查询,请在数据库中启用查询日志记录。

Django 4.2 中已更改

增加了对记录事务管理查询(BEGINCOMMITROLLBACK)的支持。

django.utils.autoreload

与 Django 开发服务器执行期间的自动代码重新加载相关的日志消息。此记录器在检测到源代码文件中的修改时会生成 INFO 消息,并且在文件系统检查和事件订阅过程中可能会生成 WARNING 消息。

django.contrib.gis

在不同时间点与 GeoDjango 相关的日志消息:在加载外部 GeoSpatial 库(GEOS、GDAL 等)期间以及报告错误时。每个 ERROR 日志记录都包括捕获到的异常和相关的上下文数据。

django.dispatch

此记录器用于 信号,特别是在 Signal 类中,用于在向连接的接收器分发信号时报告问题。 ERROR 日志记录将捕获到的异常作为 exc_info 包含在内,并添加以下额外上下文

  • receiver:接收器的名称。
  • err:在调用接收器时发生的异常。

django.security.*

安全记录器将接收任何 SuspiciousOperation 和其他与安全相关的错误发生时的消息。对于每种安全错误子类型都有一个子记录器,包括所有 SuspiciousOperation。日志事件的级别取决于异常处理的位置。大多数发生情况都会记录为警告,而到达 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

记录由 迁移框架 对数据库进行架构更改期间执行的 SQL 查询。请注意,它不会记录由 RunPython 执行的查询。发送到此记录器的信息在其额外上下文中具有 paramssql(但与 django.db.backends 不同,不具有持续时间)。这些值具有与 django.db.backends 中说明的相同含义。

处理程序

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

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

此处理程序为它接收的每条日志消息向网站 ADMINS 发送一封电子邮件。

如果日志记录包含 request 属性,则请求的完整详细信息将包含在电子邮件中。如果客户端的 IP 地址位于 INTERNAL_IPS 设置中,则电子邮件主题将包含短语“内部 IP”;如果不是,则它将包含“外部 IP”。

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

AdminEmailHandlerinclude_html 参数用于控制回溯电子邮件是否包含一个 HTML 附件,其中包含如果 DEBUGTrue,则会生成的调试网页的全部内容。要在配置中设置此值,请将其包含在 django.utils.log.AdminEmailHandler 的处理程序定义中,如下所示

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

使用 AdminEmailHandler 时,请注意 日志记录的安全影响

通过设置 AdminEmailHandleremail_backend 参数,可以覆盖处理程序正在使用的 电子邮件后端,如下所示

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

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

AdminEmailHandlerreporter_class 参数允许提供一个 django.views.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 时才传递记录。

返回顶部