Django 日志

阅读: 42910     评论:14

Django使用Python内置的logging模块实现它自己的日志系统。

Django的日志功能在django.setup()的启动过程中被一同加载了,所以大多数场景下,都可以直接使用。

如果你没有使用过logging模块,请参考Python教程中的相关章节。

直达链接《logging模块详解》,请务必学习透彻后再看本文。

在Python的logging模块中,主要包含下面四大金刚:

  • Loggers: 记录器
  • Handlers:处理器
  • Filters: 过滤器
  • Formatters: 格式化器

下文假定你已经对logging模块有一定的了解。

记录器Loggers

logger 是日志系统的入口。每个 logger 都是命名了的 bucket木桶, 消息塞入 bucket 以便进一步处理。

可以配置logger的 日志级别。日志级别定义了由该 logger 处理的消息的严重性。Python 定义了下面几种日志级别:

  • DEBUG:排查故障时使用的低级别信息
  • INFO:一般信息
  • WARNING:警告信息
  • ERROR:错误问题
  • CRITICAL:严重或致命问题
  • 每一条写入 logger 的消息都是一条日志记录。每条日志记录都本身的日志级别,代表问题的严重程度。日志记录还包含有用的元数据,来描述被记录的事件细节,例如堆栈跟踪或者错误码。

当 logger 处理一条消息时,会将自己的日志级别和消息本身的日志级别做对比。如果消息的日志级别匹配或者高于 logger 的日志级别,它就会被进一步处理。否则这条消息就会被忽略掉。

当 logger 确定了一条消息需要进一步处理之后,会把它传给 Handler

处理器Handlers

Handler 是处理 logger 传递过来的消息的引擎。它描述特定的日志行为,比如把消息输出到屏幕、文件或网络 socket。

和 logger 一样,handler 也有日志级别的概念。如果一条日志记录的级别不匹配或者低于 handler 的日志级别,对应的消息会被 handler 忽略。

一个 logger 可以有多个 handler,每一个 handler 可以有不同的日志级别。这样就可以根据消息的重要性不同,来提供不同的输出方式。例如,你可以添加一个 handler 把 ERRORCRITICAL 消息发到寻呼机,再添加另一个 handler 把所有的消息(包括 ERRORCRITICAL 消息)保存到文件里以便日后分析。

过滤器filters

在日志从 logger 传到 handler 的过程中,使用 Filter 来做额外的过滤控制。

默认情况下,只要级别匹配,任何日志消息都会被处理。不过,也可以通过添加 filter 来给日志处理的过程增加额外条件。例如,可以添加一个 filter 只允许某个特定来源的 ERROR 消息输出。

Filter 还被用来在日志输出之前对日志记录做修改。例如,可以写一个 filter,当满足一定条件时,把日志记录从 ERROR 降到 WARNING 级别。

Filter 在 logger 和 handler 中都可以添加;多个 filter 可以链接起来使用,来做多重过滤操作。

格式控制Formatters

日志记录最终是需要以文本来呈现的。Formatter 描述了记录文本的格式。一个 formatter 通常由包含 LogRecord attributes 的 Python 格式化字符串组成,也可以自定义 formatter。

一、在Django视图中使用logging

使用方法非常简单,如下例所示:

# 导入logging库
import logging

# 获取一个logger对象
logger = logging.getLogger(__name__)

def my_view(request, arg1, arg):
    ...
    if bad_mojo:
        # 记录一个错误日志
        logger.error('Something went wrong!')

每满足bad_mojo条件一次,就写入一条错误日志。

logger对象有下面几个内置方法:

  • logger.debug()
  • logger.info()
  • logger.warning()
  • logger.error()
  • logger.critical()
  • logger.log():手动输出一条指定日志级别的日志消息。(上面五种方法的基础版)
  • logger.exception():创建一个包含当前异常堆栈帧的 ERROR 级别日志消息。

二、在Django中配置logging

通常,只是像上面的例子那样简单的使用logging模块是远远不够的,我们一般都要对logging的四大金刚进行一定的配置。

例一,一个非常简单的配置文件,为root记录器配置console处理器:

import os

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'root': {
        'handlers': ['console'],
        'level': 'WARNING',
    },
}

实际上Python的logging模块提供了好几种配置方式。默认情况下,Django使用dictConfig 。也就是字典方式。

例二,将日志保存到文件中:

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,
        },
    },
}

如果你使用上面的样例,请确保Django用户对filename对应的目录和文件具有写入权限。

例三:将日志打印到控制台,通常用做开发期间的信息展示。

import os

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
        },
    },
    "root": {
        "handlers": ["console"],
        "level": "WARNING",
    },
    "loggers": {
        "django": {
            "handlers": ["console"],
            "level": os.getenv("DJANGO_LOG_LEVEL", "INFO"),
            "propagate": False,
        },
    },
}

例四:一个相当复杂的logging配置:

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,


    "formatters": {
        "verbose": {
            "format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
            "style": "{",
        },
        "simple": {
            "format": "{levelname} {message}",
            "style": "{",
        },
    },


    "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"],
        },
    },
}

上面的logging配置主要定义了这么几件事情:

  • 定义了配置文件的版本,当前版本号为1.0
  • 定义了两个formatter:simpleverbose,分别表示两种文本格式。
  • 定义了两个过滤器:specialrequire_debug_true
  • 定义了两个处理器:consolemail_admins
  • 配置了三个logger:djangodjango.requestmyproject.custom

三、Django对logging模块的扩展

Django对logging模块进行了一定的扩展,用来满足Web服务器专门的日志记录需求。

其默认配置位于django.utils.log.DEFAULT_LOGGING,如下所示:

{
    "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,
        },
    },
}

1. 记录器 Loggers

Django额外提供了几个其内建的logger。

  • django: django记录器家族的根。一般不使用这个记录器,用下面的。
  • django.request: 记录与处理请求相关的消息。5XX错误被记录为ERROR消息;4XX错误记录为WARNING消息。接收额外参数:status_coderequest
  • django.server: 记录开发服务器下处理请求相关的消息。只用于开发阶段。
  • django.template: 记录与渲染模板相关的日志。
  • django.db.backends: 与数据库交互的代码相关的消息。
  • django.utils.autoreload:记录开发服务器重载过程中的日志
  • django.dispatch:记录信号相关的日志
  • django.security.*: 记录所有与安全相关的错误。
  • django.security.csrf: 记录CSRF验证失败日志。
  • django.db.backends.schema: 记录查询导致数据库修改的日志。

2. 处理器 Handlers

Django额外提供了一个handler,AdminEmailHandler。这个处理器将它收到的每个日志信息用邮件发送给站点管理员。

3. 过滤器Filters

Django还额外提供两个过滤器。

  • CallbackFilter(callback)[source]:这个过滤器接受一个回调函数,并对每个传递给过滤器的记录调用它。如果回调函数返回False,将不会进行记录的处理。
  • RequireDebugFalse[source]: 这个过滤器只会在settings.DEBUG==False时生效。

4. 日志逻辑

  • 当 DEBUG 为 True 时:

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

  • 当 DEBUG 为 False 时:

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

  • 无论DEBUG是True还是False:

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

除了 django.server 之外,所有的日志记录器都会将日志传播给它们的父辈,直到root,也就是根django 记录器。consolemail_admins 处理程序被附加到根记录器上,以实现上述逻辑。

四、自定义配置

settings中的LOGGING_CONFIG 定义了用于配置 Django 日志记录器的可调用对象,默认情况下,它指向 Python 的 logging.config.dictConfig() 函数。

LOGGING_CONFIG 赋值为你希望的配置方案即可自定义配置。

五、禁用日志的自动配置过程

如果你根本不想配置日志记录(或者你想用自己的方法手动配置日志记录),你可以将 LOGGING_CONFIG 设置为 None。这将禁用 Django 的默认日志记录 的配置过程。

将 LOGGING_CONFIG 设置为 None 只是意味着自动配置过程被禁用,而不是日志本身被禁用。如果你禁用了配置过程,Django 仍然会进行日志调用,回到默认的日志行为。

下面是一个禁用 Django 的日志配置过程,然后手动配置日志的例子。

#settings.py

LOGGING_CONFIG = None

import logging.config

logging.config.dictConfig(...)

请注意,默认的配置过程只有在设置完全加载后才会调用 LOGGING_CONFIG。相反,在设置文件中手动配置日志记录将立即加载你的日志记录配置。因此,你的日志配置必须出现在它所依赖的任何设置之后。


 发送邮件 Django与缓存 

评论总数: 14


点击登录后方可评论

您好,在已上线的项目中碰到一个问题,在settings.py里配置好日志之后,发现有很多日志没有写入日志文件,用的是django这个logger,请问是需要自己定义一个logger才不会遗漏日志吗



django日志可以多种方式混用吗?比如我既在setting.py里写了LOGGING,又自定义了一个logger.py用logging模块来记录日志



可以混用



您好,在已上线的项目中碰到一个问题,在settings.py里配置好日志之后,发现有很多日志没有写入日志文件,用的是django这个logger,请问是需要自己定义一个logger才不会遗漏日志吗



django日志,可以把访问人的ip地址写到日志中吗? 通过配置的方式



当然可以



写的太好了,赞一个。



logging配置中添加了formatters就会报异常LookupError: No installed app with label 'admin'.是什么情况,版本2.2.0



嗷我的问题,配置写错了的话会出现这个问题



logging应该是在settings中配置,可文中并未指明。



人家博主已经标明了‘直达链接’,仔细看吧...



哈哈,如题





,一般大写的都是在settings里