记录¶
快速记录引擎¶
Django使用Python的内置 logging
模块来执行系统日志记录。这个模块的用法在Python自己的文档中详细讨论。但是,如果你从来没有使用Python的日志框架(或者即使你有),这里有一个快速入门。
玩家的演员¶
Python日志记录配置包括四个部分:
记录器¶
记录器是进入记录系统的入口点。每个记录器是一个命名桶,消息可以写入其中进行处理。
记录器配置为具有 日志级别。此日志级别描述记录器将处理的消息的严重性。 Python定义了以下日志级别:
DEBUG
:用于调试目的的低级系统信息INFO
:一般系统信息WARNING
:描述发生的小问题的信息。ERROR
:描述发生的主要问题的信息。CRITICAL
:描述发生的关键问题的信息。
写入记录器的每条消息都是 日志记录。每个日志记录还具有指示该特定消息的严重性的 日志级别。日志记录还可以包含描述正在记录的事件的有用元数据。这可以包括诸如堆栈跟踪或错误代码的详细信息。
当向记录器发送消息时,将消息的日志级别与记录器的日志级别进行比较。如果消息的日志级别满足或超过日志记录器本身的日志级别,消息将进行进一步处理。如果没有,消息将被忽略。
一旦记录器确定消息需要被处理,它被传递到 Handler。
处理程序¶
处理程序是确定日志记录器中每条消息发生的引擎。它描述了特定的日志记录行为,例如将消息写入屏幕,文件或网络套接字。
像日志记录器一样,处理程序也有日志级别。如果日志记录的日志级别不满足或超过处理程序的级别,处理程序将忽略该消息。
记录器可以有多个处理程序,每个处理程序可以有不同的日志级别。以这种方式,可以根据消息的重要性提供不同形式的通知。例如,您可以安装一个处理程序,将 ERROR
和 CRITICAL
消息转发到分页服务,而另一个处理程序将所有消息(包括 ERROR
和 CRITICAL
消息)记录到文件以供日后分析。
过滤器¶
过滤器用于提供对日志记录从记录器传递到处理程序的附加控制。
默认情况下,将处理满足日志级别要求的任何日志消息。但是,通过安装过滤器,可以在日志记录过程中添加其他条件。例如,您可以安装一个只允许来自特定源的 ERROR
消息的过滤器。
过滤器还可用于在发出日志记录之前修改日志记录。例如,如果满足特定的一组条件,您可以编写一个过滤器,将 ERROR
日志记录降级到 WARNING
记录。
过滤器可以安装在记录仪上或处理程序上;可以在链中使用多个过滤器来执行多个过滤动作。
格式化¶
最终,日志记录需要作为文本呈现。格式化程序描述该文本的确切格式。格式化器通常由包含 LogRecord属性 的Python格式化字符串组成;但是,您也可以编写自定义格式化程序来实现特定的格式化行为。
使用日志记录¶
配置记录器,处理程序,过滤器和格式化程序后,您需要将日志调用放入代码中。使用日志框架非常简单。这里有一个例子:
# import the logging library
import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
def my_view(request, arg1, arg):
...
if bad_mojo:
# Log an error message
logger.error('Something went wrong!')
就是这样!每次激活 bad_mojo
条件时,将写入错误日志记录。
命名记录器¶
对 logging.getLogger()
的调用获得(如果必要的话)创建记录器的实例。日志记录器实例由名称标识。此名称用于标识记录器以进行配置。
按照惯例,记录器名称通常是 __name__
,包含记录器的python模块的名称。这允许您基于每个模块过滤和处理日志记录调用。但是,如果您有其他方式组织记录消息,您可以提供任何点分隔的名称来标识记录器:
# Get an instance of a specific named logger
logger = logging.getLogger('project.interesting.stuff')
记录器名称的虚线路径定义层次结构。 project.interesting
记录器被认为是 project.interesting.stuff
记录器的父节点; project
记录器是 project.interesting
记录器的父级。
为什么层次结构很重要?好吧,因为记录器可以设置为 propagate,他们的记录调用到他们的父母。这样,您可以在记录器树的根目录中定义一组处理程序,并捕获记录器子树中的所有日志记录调用。在 project
命名空间中定义的日志处理程序将捕获在 project.interesting
和 project.interesting.stuff
日志记录器上发出的所有日志消息。
这种传播可以在每个记录器的基础上进行控制。如果不想将特定的记录器传播到其父节点,则可以关闭此行为。
记录呼叫¶
记录器实例包含每个默认日志级别的条目方法:
logger.debug()
logger.info()
logger.warning()
logger.error()
logger.critical()
还有两个其他日志记录可用:
logger.log()
:手动发出具有特定日志级别的日志记录消息。logger.exception()
:创建包装当前异常堆栈帧的ERROR
级别日志记录消息。
配置日志记录¶
当然,仅仅将日志调用放入代码是不够的。您还需要配置记录器,处理程序,过滤器和格式化程序,以确保日志输出以有用的方式输出。
Python日志库提供了几种配置日志记录的技术,从编程接口到配置文件。默认情况下,Django使用 dictConfig格式。
为了配置日志记录,您使用 LOGGING
定义日志设置的字典。这些设置描述了日志记录设置中所需的日志记录器,处理程序,过滤器和格式化程序,以及希望这些组件具有的日志级别和其他属性。
默认情况下,使用以下方案将 LOGGING
设置与 Django默认日志配置 合并。
如果 LOGGING
dictConfig中的 disable_existing_loggers
密钥设置为 True
(这是默认值),则将禁用默认配置中的所有记录器。禁用的记录器不同于删除;记录器仍然存在,但会静默地丢弃任何记录到它的东西,甚至不传播条目到父记录器。因此你应该非常小心使用 'disable_existing_loggers': True
;它可能不是你想要的。相反,您可以将 disable_existing_loggers
设置为 False
,并重新定义部分或全部默认记录器;或者您可以将 LOGGING_CONFIG
设置为 None
和 自己处理日志配置。
日志记录配置为常规Django setup()
功能的一部分。因此,您可以确定记录器总是可以在您的项目代码中使用。
例子¶
dictConfig格式 的完整文档是有关日志配置字典的最佳信息来源。然而,给你一个可能的味道,这里有几个例子。
首先,这里有一个简单的配置,将所有日志记录从 django 记录器写入本地文件:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/path/to/django/debug.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
如果使用此示例,请务必将 'filename'
路径更改为运行Django应用程序的用户可写入的位置。
第二,这里有一个例子,让日志系统打印Django的日志到控制台。它可能在地方发展中有用。
默认情况下,此配置仅向控制台发送级别 INFO
或更高级别的消息(与Django的默认日志记录配置相同,除非默认值仅在 DEBUG=True
时显示日志记录)。 Django不记录很多这样的消息。但是,使用此配置,您还可以设置环境变量 DJANGO_LOG_LEVEL=DEBUG
以查看Django的所有调试日志记录,这非常详细,因为它包括所有数据库查询:
import os
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
},
},
}
Django的默认日志配置已更改。有关更改的说明,请参阅 发布说明。
最后,这里有一个相当复杂的日志设置的例子:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'filters': {
'special': {
'()': 'project.logging.SpecialFilter',
'foo': 'bar',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
}
},
'loggers': {
'django': {
'handlers': ['console'],
'propagate': True,
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'myproject.custom': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
'filters': ['special']
}
}
}
此日志配置执行以下操作:
将配置标识为“dictConfig版本1”格式。目前,这是唯一的dictConfig格式版本。
定义两个格式化程序:
simple
,它只是输出日志级别名称(例如,DEBUG
)和日志消息。format
字符串是一个普通的Python格式化字符串,用于描述要在每个日志行上输出的详细信息。可以输出的详细信息的完整列表可以在 Formatter Objects 中找到。verbose
,它输出日志级别名称,日志消息,以及生成日志消息的时间,进程,线程和模块。
定义两个过滤器:
project.logging.SpecialFilter
,使用别名special
。如果此过滤器需要其他参数,则它们可以作为过滤器配置字典中的附加键。在这种情况下,当实例化SpecialFilter
时,参数foo
将被赋予值bar
。django.utils.log.RequireDebugTrue
,当DEBUG
为True
时传递记录。
定义两个处理程序:
console
,一个StreamHandler,它将打印任何DEBUG
(或更高)消息到stderr。此处理程序使用simple
输出格式。mail_admins
,一个AdminEmailHandler,它将电子邮件任何ERROR
(或更高)消息到网站管理员。此处理程序使用special
过滤器。
配置三个记录器:
django
,它将所有消息传递给console
处理程序。django.request
,它将所有ERROR
消息传递给mail_admins
处理程序。此外,此记录器被标记为 not 传播消息。这意味着写入django.request
的日志消息不会被django
记录器处理。myproject.custom
,它传递所有在INFO
或更高的消息,也通过special
过滤器到两个处理程序 -console
和mail_admins
。这意味着所有INFO
级别消息(或更高级别)将被打印到控制台;ERROR
和CRITICAL
消息也将通过电子邮件输出。
自定义日志配置¶
如果不想使用Python的dictConfig格式配置记录器,可以指定自己的配置方案。
LOGGING_CONFIG
设置定义将用于配置Django的记录器的可调用。默认情况下,它指向Python的 logging.config.dictConfig()
函数。但是,如果要使用不同的配置过程,可以使用任何其他可调用,只需要一个参数。当配置日志记录时,LOGGING
的内容将作为该参数的值提供。
禁用日志配置¶
如果您不想完全配置日志记录(或者您想使用自己的方法手动配置日志记录),您可以将 LOGGING_CONFIG
设置为 None
。这将禁用 Django默认日志记录 的配置过程。这里有一个例子,禁用Django的日志配置,然后手动配置日志记录:
LOGGING_CONFIG = None
import logging.config
logging.config.dictConfig(...)
将 LOGGING_CONFIG
设置为 None
仅意味着禁用自动配置过程,而不是记录自身。如果禁用配置过程,Django仍将进行日志调用,回退到定义的任何默认日志记录行为。
Django日志扩展¶
Django提供了许多实用程序来处理Web服务器环境中日志记录的独特需求。
记录器¶
Django提供了几个内置的记录器。
django
¶
django
是所有的记录器。没有邮件直接发布到此记录器。
django.request
¶
与请求处理相关的日志消息。 5XX响应作为 ERROR
消息提出; 4XX响应作为 WARNING
消息提出。
到这个记录器的消息有以下额外的上下文:
status_code
:与请求相关联的HTTP响应代码。request
:生成日志记录消息的请求对象。
django.server
¶
与由 runserver
命令调用的服务器接收的请求的处理相关的日志消息。 HTTP 5XX响应记录为 ERROR
消息,4XX响应记录为 WARNING
消息,其他一切记录为 INFO
。
到这个记录器的消息有以下额外的上下文:
status_code
:与请求相关联的HTTP响应代码。request
:生成日志记录消息的请求对象。
django.template
¶
与模板呈现相关的日志消息。
缺少的上下文变量记录为
DEBUG
消息。在调试模式关闭时,在
{% include %}
呈现期间引发的未捕获异常记录为WARNING
消息(由于{% include %}
使异常静默并在这种情况下返回空字符串,因此有帮助)。
django.db.backends
¶
与代码与数据库的交互相关的消息。例如,由请求执行的每个应用程序级SQL语句都在 DEBUG
级别记录到此记录器。
到这个记录器的消息有以下额外的上下文:
duration
:执行SQL语句所需的时间。sql
:已执行的SQL语句。params
:在SQL调用中使用的参数。
出于性能原因,仅当 settings.DEBUG
设置为 True
时才会启用SQL日志记录,而不考虑安装的日志记录级别或处理程序。
此日志记录不包括框架级初始化(例如 SET TIMEZONE
)或事务管理查询(例如 BEGIN
,COMMIT
和 ROLLBACK
)。如果希望查看所有数据库查询,请在数据库中打开查询日志记录。
django.security.*
¶
安全记录器将在任何 SuspiciousOperation
发生时接收消息。对于SuspiciousOperation的每个子类型都有一个子日志记录器。日志事件的级别取决于处理异常的位置。大多数事件被记录为警告,而到达WSGI处理程序的任何 SuspiciousOperation
将被记录为错误。例如,当来自不匹配 ALLOWED_HOSTS
的客户机的请求中包括HTTP Host
头部时,Django将返回400响应,并且将错误消息记录到 django.security.DisallowedHost
记录器。
默认情况下,这些日志事件将到达“django”记录器,当 DEBUG=False
时,它会向管理员发送错误事件。导致由 SuspiciousOperation
引起的400响应的请求不会记录到 django.request
记录器,而只记录到 django.security
记录器。
要使特定类型的 SuspiciousOperation
静默,可以按照此示例覆盖特定的记录器:
'handlers': {
'null': {
'class': 'logging.NullHandler',
},
},
'loggers': {
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
},
django.db.backends.schema
¶
将在 迁移框架 对数据库进行模式更改期间执行的SQL查询记录。请注意,它不会记录 RunPython
执行的查询。给这个记录器的消息在它们的额外上下文中具有 params
和 sql
(但不同于 django.db.backends
,而不是持续时间)。这些值具有与 django.db.backends 中所解释的相同的含义。
添加了 extra
上下文。
处理程序¶
除了Python日志模块提供的日志处理程序之外,Django还提供了一个日志处理程序。
-
class
AdminEmailHandler
(include_html=False, email_backend=None)[源代码]¶ 此处理程序向网站管理员发送电子邮件,以接收每个日志消息。
如果日志记录包含
request
属性,则该请求的完整详细信息将包含在电子邮件中。如果客户端的IP地址在INTERNAL_IPS
设置中,电子邮件主题将包括短语“内部IP”;如果没有,它将包括“EXTERNAL IP”。如果日志记录包含堆栈跟踪信息,那么该堆栈跟踪将包含在电子邮件中。
AdminEmailHandler
的include_html
参数用于控制追溯电子邮件是否包括包含调试网页的完整内容的HTML附件,如果DEBUG
是True
,则该附件将被产生。要在配置中设置此值,请将其包含在django.utils.log.AdminEmailHandler
的处理程序定义中,如下所示:'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, } },
请注意,此电子邮件的HTML版本包含完整的追溯,在堆栈的每个级别具有局部变量的名称和值,以及您的Django设置的值。此信息可能非常敏感,您可能不想通过电子邮件发送。考虑使用诸如 Sentry 之类的东西来获得两个世界中最好的 - 完整追踪的丰富信息以及 not 通过电子邮件发送信息的安全性。您还可以明确指定要从错误报告中滤除某些敏感信息 - 了解有关 Filtering error reports 的更多信息。
通过设置
AdminEmailHandler
的email_backend
参数,处理程序正在使用的 电子邮件后端 可以被覆盖,如下所示:'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'email_backend': 'django.core.mail.backends.filebased.EmailBackend', } },
默认情况下,将使用在
EMAIL_BACKEND
中指定的电子邮件后端的实例。-
send_mail
(subject, message, *args, **kwargs)[源代码]¶ 向管理用户发送电子邮件。要自定义此行为,您可以子类化
AdminEmailHandler
类并覆盖此方法。
-
过滤器¶
Django除了Python日志记录模块提供的日志过滤器之外,还提供了两个日志过滤器。
-
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
然后将其添加到您的日志记录配置:
'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
只在DEBUG
为False
时向管理员发送错误电子邮件:'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
,除了记录仅当DEBUG
是True
时传递。
Django默认日志配置¶
默认情况下,Django配置以下日志记录:
当 DEBUG
是 True
时:
django
捕获所有记录器将所有在INFO
级别或更高级别的消息发送到控制台。
当 DEBUG
是 False
时:
django
记录器将具有ERROR
或CRITICAL
级别的消息发送到AdminEmailHandler
。
独立于 DEBUG
的价值:
django.server 记录器将所有
INFO
级别或更高级别的消息发送到控制台。
Django的默认日志配置已更改。有关更改的说明,请参阅 发布说明。
另请参阅 配置日志记录 以了解如何补充或替换此默认日志记录配置。