如何配置和使用日志

参见

Django 提供了一个可扩展的 默认日志配置

发起基本的 logging 调用

要从代码中发送日志消息,你需要在代码中添加日志调用。

不要在 settings.py 中使用日志调用。

Django 日志配置作为 setup() 函数的一部分配置的方式意味着在 settings.py 中放置的日志调用可能不会按预期工作,因为在那个时候 日志还没有设置好。要探索日志,请使用下面示例中建议的视图函数。

首先,导入Python的日志库,然后使用 logging.getLogger() 获取一个日志记录器实例。为 getLogger() 方法提供一个用于识别它和它发出的记录的名称。一个好的选择是使用 __name__ (参见下面的 命名日志记录器 了解更多信息),它将提供当前Python模块的名称作为一个点分路径:

  1. import logging
  2. logger = logging.getLogger(__name__)

在模块级别执行此声明是一个好的约定。

然后在函数中,例如在视图中,向日志记录器发送一条记录:

  1. def some_view(request):
  2. ...
  3. if some_risky_state:
  4. logger.warning("Platform is running at risk")

当执行此代码时,将发送一个包含该消息的 LogRecord 到日志记录器。如果你正在使用 Django 的默认日志配置,该消息将出现在控制台中。

上面示例中使用的 WARNING 级别是多个 日志严重级别 中的一个:DEBUG, INFO, WARNING, ERROR, CRITICAL。因此,另一个示例可能如下所示:

  1. logger.critical("Payment system is not responding")

重要

级别低于 WARNING 的记录默认情况下不会出现在控制台中。要更改此行为,需要额外的配置。

自定义日志配置

虽然 Django 的日志配置可以直接使用,但您可以通过一些额外的配置来精确控制日志发送到各种目标的方式,如日志文件、外部服务、电子邮件等。

你可以配置:

  • 使用日志记录器映射来确定将哪些记录发送到哪些处理程序。
  • 使用处理程序来确定它们接收到的记录的处理方式
  • 使用过滤器来对记录的传递进行额外控制,甚至可以对记录进行原地修改
  • 格式化器,用于将 LogRecord 对象转换为字符串或其他形式,以供人类或其他系统使用。

有各种配置日志的方式。在Django中,最常用的是 LOGGING 设置。该设置使用 dictConfig 格式,并扩展了 默认的日志配置

请参阅 日志模块的配置 以了解如何将你的自定义设置与 Django 的默认设置合并的解释。

有关其他配置日志的方式的详细信息,请参阅 Python 日志文档。为了简单起见,本文档将仅考虑通过 LOGGING 设置进行配置。

基础日志配置

在配置日志时,以下操作是有意义的

创建一个 LOGGING 目录

在你的 settings.py:: 中

  1. LOGGING = {
  2. "version": 1, # the dictConfig format version
  3. "disable_existing_loggers": False, # retain the default loggers
  4. }

通常情况下,将 disable_existing_loggers 设置为 False,保留并扩展默认的日志配置是有意义的。

配置一个处理程序

这个示例配置了一个名为 file 的处理程序,使用Python的 FileHandler 将级别为 DEBUG 及更高的日志保存到文件 general.log (位于项目根目录)中:

  1. LOGGING = {
  2. # ...
  3. "handlers": {
  4. "file": {
  5. "class": "logging.FileHandler",
  6. "filename": "general.log",
  7. },
  8. },
  9. }

不同的处理程序类接受不同的配置选项。有关可用处理程序类的更多信息,请参阅 Django 提供的 AdminEmailHandler 以及 Python 提供的各种 处理程序类

日志级别也可以在处理程序上进行设置(默认情况下,它们接受所有级别的日志消息)。使用上面的示例,添加以下内容:

  1. {
  2. "class": "logging.FileHandler",
  3. "filename": "general.log",
  4. "level": "DEBUG",
  5. }

可以定义一个处理程序配置,该配置只接受级别为 DEBUG 及更高级别的记录。

配置一个日志记录器映射

要将记录发送到该处理程序,请配置一个日志记录器映射,例如:

  1. LOGGING = {
  2. # ...
  3. "loggers": {
  4. "": {
  5. "level": "DEBUG",
  6. "handlers": ["file"],
  7. },
  8. },
  9. }

映射的名称决定了它将处理哪些日志记录。此配置('')是 无名称 的。这意味着它将处理 所有 记录器的记录(请参阅下面的 命名记录器 以了解如何使用映射名称来确定它将处理哪些记录器的记录)。

它将级别为 DEBUG 及更高的消息发送给名为 file 的处理程序。

请注意,一个日志记录器可以将消息转发给多个处理程序,因此日志记录器和处理程序之间的关系是多对多的。

如果您执行以下操作:

  1. logger.debug("Attempting to connect to API")

在你的代码中,你将在项目根目录中的文件 general.log 中找到该消息。

配置格式化器

默认情况下,最终的日志输出包含每个 日志记录 的消息部分。如果想要包含附加数据,可以使用格式化器。首先命名并定义你的格式化器 - 以下示例定义了名为 verbosesimple 的格式化器:

  1. LOGGING = {
  2. # ...
  3. "formatters": {
  4. "verbose": {
  5. "format": "{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}",
  6. "style": "{",
  7. },
  8. "simple": {
  9. "format": "{levelname} {message}",
  10. "style": "{",
  11. },
  12. },
  13. }

style 关键字允许你指定 { 用于 str.format()$ 用于 string.Template 格式化;默认值是 $

查看 LogRecord attributes 以了解可以包含的 LogRecord 属性。

要将格式化器应用到处理程序,可以在处理程序的字典中添加一个指向格式化器的名称的 formatter 条目,例如:

  1. "handlers": {
  2. "file": {
  3. "class": "logging.FileHandler",
  4. "filename": "general.log",
  5. "formatter": "verbose",
  6. },
  7. }

使用命名空间日志记录器

未命名的日志配置 '' 捕获来自任何 Python 应用程序的日志。命名的日志配置将仅捕获名称匹配的记录器的日志。

日志记录器实例的命名空间是使用 getLogger() 定义的。例如,在 my_appviews.py 中:

  1. logger = logging.getLogger(__name__)

将在 my_app.views 命名空间中创建一个日志记录器。__name__ 允许你自动根据项目中应用程序的来源组织日志消息。它还确保你不会遇到名称冲突。

一个名为 my_app.views 的日志记录器映射将捕获来自这个记录器的记录:

  1. LOGGING = {
  2. # ...
  3. "loggers": {
  4. "my_app.views": {...},
  5. },
  6. }

一个名为 my_app 的日志记录器映射将更加宽松,捕获来自 my_app 命名空间中任何地方的记录器(包括 my_app.viewsmy_app.utils 等等):

  1. LOGGING = {
  2. # ...
  3. "loggers": {
  4. "my_app": {...},
  5. },
  6. }

您还可以明确定义日志记录器的命名空间:

  1. logger = logging.getLogger("project.payment")

并相应地设置日志记录器映射。

使用日志记录器层次结构和传播

日志记录器的命名是 分层 的。my_appmy_app.views 的父级,my_app.viewsmy_app.views.private 的父级。除非另有说明,否则日志记录器映射将将它们处理的记录传播给它们的父级 - 来自 my_app.views.private 命名空间中的记录器的记录将由 my_appmy_app.views 的映射处理。

为了管理这种行为,请在您定义的映射中设置传播键:

  1. LOGGING = {
  2. # ...
  3. "loggers": {
  4. "my_app": {
  5. # ...
  6. },
  7. "my_app.views": {
  8. # ...
  9. },
  10. "my_app.views.private": {
  11. # ...
  12. "propagate": False,
  13. },
  14. },
  15. }

propagate 默认为 True。在这个示例中,来自 my_app.views.private 的日志不会被父级处理,但来自 my_app.views 的日志会被处理。

配置响应式日志记录

当日志包含尽可能多的信息,而不是您不需要的信息时,日志是最有用的——需要多少取决于您正在做的事情。在调试时,您需要一定程度的信息,如果您不得不在生产环境中处理这些信息,那么这些信息将是多余的,而且毫无用处。

您可以配置日志记录,以在需要时为您提供所需的详细程度。与手动更改配置以实现此目的不同,更好的方式是根据环境自动应用配置。

例如,你可以在开发和测试环境中适当设置一个环境变量 DJANGO_LOG_LEVEL,然后在日志记录器映射中使用它,如下所示:

  1. "level": os.getenv("DJANGO_LOG_LEVEL", "WARNING")

因此,除非环境指定较低的日志级别,否则此配置将仅将严重性为 WARNING 及以上的记录转发到其处理程序。

配置中的其他选项(例如处理程序的 levelformatter 选项)可以以类似的方式进行管理。