Django使用Python内置的logging模块实现它自己的日志系统。
Django的日志功能在django.setup()
的启动过程中被一同加载了,所以大多数场景下,都可以直接使用。
如果你没有使用过logging模块,请参考Python教程中的相关章节。
直达链接《logging模块详解》,请务必学习透彻后再看本文。
在Python的logging模块中,主要包含下面四大金刚:
下文假定你已经对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 把
ERROR
和CRITICAL
消息发到寻呼机,再添加另一个 handler 把所有的消息(包括ERROR
和CRITICAL
消息)保存到文件里以便日后分析。过滤器filters
在日志从 logger 传到 handler 的过程中,使用 Filter 来做额外的过滤控制。
默认情况下,只要级别匹配,任何日志消息都会被处理。不过,也可以通过添加 filter 来给日志处理的过程增加额外条件。例如,可以添加一个 filter 只允许某个特定来源的
ERROR
消息输出。Filter 还被用来在日志输出之前对日志记录做修改。例如,可以写一个 filter,当满足一定条件时,把日志记录从
ERROR
降到WARNING
级别。Filter 在 logger 和 handler 中都可以添加;多个 filter 可以链接起来使用,来做多重过滤操作。
格式控制Formatters
日志记录最终是需要以文本来呈现的。Formatter 描述了记录文本的格式。一个 formatter 通常由包含 LogRecord attributes 的 Python 格式化字符串组成,也可以自定义 formatter。
使用方法非常简单,如下例所示:
# 导入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.log()
:手动输出一条指定日志级别的日志消息。(上面五种方法的基础版)logger.exception()
:创建一个包含当前异常堆栈帧的 ERROR
级别日志消息。通常,只是像上面的例子那样简单的使用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配置主要定义了这么几件事情:
simple
和verbose
,分别表示两种文本格式。special
和require_debug_true
console
和mail_admins
django
、django.request
和myproject.custom
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, }, }, }
Django额外提供了几个其内建的logger。
django
记录器家族的根。一般不使用这个记录器,用下面的。status_code
和request
Django额外提供了一个handler,AdminEmailHandler
。这个处理器将它收到的每个日志信息用邮件发送给站点管理员。
Django还额外提供两个过滤器。
CallbackFilter(callback)[source]
:这个过滤器接受一个回调函数,并对每个传递给过滤器的记录调用它。如果回调函数返回False,将不会进行记录的处理。RequireDebugFalse[source]
: 这个过滤器只会在settings.DEBUG==False
时生效。django 记录器将 django 层次结构(django.server 除外)中的 INFO 级别或更高的消息发送到控制台。
django 记录器将 django 层次结构(django.server 除外)中带有 ERROR 或 CRITICAL 级别的消息发送到 AdminEmailHandler。
django.server 记录器向控制台发送 INFO 或更高等级的消息。
除了 django.server
之外,所有的日志记录器都会将日志传播给它们的父辈,直到root,也就是根django
记录器。console
和 mail_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
。相反,在设置文件中手动配置日志记录将立即加载你的日志记录配置。因此,你的日志配置必须出现在它所依赖的任何设置之后。
您好,在已上线的项目中碰到一个问题,在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里