Django使用Python内置的logging模块实现它自己的日志系统。
如果你没有使用过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
消息)保存到文件里以便日后分析。过滤器
在日志从 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的四大金刚进行一定的配置。
下面是一个非常简单的配置文件:
import os LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'root': { 'handlers': ['console'], 'level': 'WARNING', }, }
实际上Python的logging模块提供了好几种配置方式。默认情况下,Django使用dictConfig format。也就是字典方式。
例一,将日志保存到文件中:
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'对应目录和文件的写入权限。
例二:
下面这个示例配置,让Django将日志打印到控制台,通常用做开发期间的信息展示。
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:simple和format,分别表示两种文本格式。
定义了两个过滤器:SpecialFilter和RequireDebugTrue
Django对logging模块进行了一定的扩展,用来满足Web服务器专门的日志记录需求。
Django额外提供了几个其内建的logger。
Django额外提供了一个handler,AdminEmailHandler。这个处理器将它收到的每个日志信息用邮件发送给站点管理员。
Django还额外提供两个过滤器。
CallbackFilter(callback)[source]:这个过滤器接受一个回调函数,并对每个传递给过滤器的记录调用它。如果回调函数返回False,将不会进行记录的处理。
RequireDebugFalse[source]: 这个过滤器只会在settings.DEBUG==False时传递。
总体而言,在Django中使用logging和在普通Python程序中,区别不大。
您好,在已上线的项目中碰到一个问题,在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里