前言
https://docs.djangoproject.com/zh-hans/3.1/topics/logging/
https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema
https://docs.python.org/3/library/logging.html
django 采用 python 的 logger 模块,配置方式选择字典方式
字典方式基本介绍
有一些必选的键值对 https://docs.python.org/3/library/logging.config.html#dictionary-schema-details
例如version
,formatters
等,具体看上面官方文档和下面的例子
关键对象介绍
loggers
根据消息界别接收日志,但不负责输出
LogRecord
logger
接收一条日志,就创建一个logrecord
对象
handlers
绑定在logger
,用于处理日志logrecord
对象,例如输出到哪里. 可以将多个handler
绑定到同一个logger
formatters
绑定在handler
,用来格式化日志logrecord
对象
filters
通过设定过滤条件,过滤从logger
到handler
的日志logrecord
对象。非必须
额外的
LoggerAdapter(logger, extra)
用来包装logger
,它接收一个logger
和一个字典extra
,从而将extra
添加到logrecord
之后,通过LoggerAdapter
对象接收的日志,再经过formatter
对extra.key
的编排,就实现了添加信息到原始日志的功能.
日志级别
DEBUG
:排查故障时使用的低级别系统信息INFO
:一般的系统信息WARNING
:描述系统发生了一些小问题的信息ERROR
:描述系统发生了大问题的信息CRITICAL
:描述系统发生严重问题的信息
流程
给接收的日志定级别:logger.<level>("log message")
logger
判断接收的日志级别是否符合logger
定义的级别
如果符合,logger
无差别的推送消息到多个handler
,如果不符合,则忽略;另外,如果logger.propagate
为真,则消息会复制一份到更高级别的logger
handler
判断接收的日志级别是否符合handler
定义的级别
如果符合,handler
通过formatter
排列logrecord
对象属性,并通过handler.class
将日志输出,如果不符合,则忽略;另外,如果handler
有filter
,则只会输出满足filter
的日志
例子
写入 settings.py 中
# Logging
LOGGING = {
'version': 1, # 指明版本,目前就只有一个版本
'disable_existing_loggers': False, # 表示是否禁用所有的已经存在的日志配置
# 声明两个格式化id
'formatters': { # 格式器
'verbose': { # 详细
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'standard': { # 标准
'format': '[%(asctime)s] [%(levelname)s] %(message)s'
},
},
# 定义过滤器 special,它有一个条件函数 project.logging.SpecialFilter(foo), 函数被实例化的时候,foo='bar'
# project.logging.SpecialFilter 需要自己实现, 判断 logrecord 对象,或者满足一些条件才输出日志
'filters': {
'special': {
'()': 'project.logging.SpecialFilter',
'foo': 'bar',
},
},
# handlers:用来定义具体处理日志的方式,可以定义多种,"console"就是打印到控制台方式。file是写入到文件的方式,"mail_admins"是邮件通知
# 这里的 console/file/mail_admins 仅仅是自定义的名称
'handlers': { # 处理器
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout', # 文件重定向的配置,将打印到控制台的信息都重定向出去
'formatter': 'standard' # 制定输出的格式,注意 在上面的formatters配置里面选择一个,否则会报错
},
'file_all': {
'level': 'DEBUG',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.dirname(os.path.dirname(os.path.realpath(__file__)))+'/log/all.log',
'formatter': 'standard'
'maxBytes': 1024
'when': 'midnight'
'interval': 1
'backupCount': 3
'utc': False
'encoding': 'utf-8'
},
'file_request': {
'level': 'DEBUG',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.dirname(os.path.dirname(os.path.realpath(__file__)))+'/log/request.log',
'formatter': 'standard'
'maxBytes': 1024
'when': 'midnight'
'interval': 1
'backupCount': 3
'utc': False
'encoding': 'utf-8'
},
'file_db': {
'level': 'DEBUG',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.dirname(os.path.dirname(os.path.realpath(__file__)))+'/log/db.log',
'formatter': 'standard'
'maxBytes': 1024
'when': 'midnight'
'interval': 1
'backupCount': 3
'utc': False
'encoding': 'utf-8'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
},
},
'loggers': { # log记录器,配置之后就会对应的输出日志
'django': {
'handlers': ['file_all'],
'level': 'INFO',
'propagate': False,
},
'django.request ':{
'handlers': ['file_request','mail_admins'],
'level': 'INFO',
'propagate': False,
},
'django.server ':{
'handlers': ['console'],
'level': 'INFO',
'propagate': False,
},
'django.db.backends': {
'handlers': ['file_db'],
'level':'INFO',
'propagate': False,
},
# 根记录器
'root': {
'handlers': ['console'],
'level': 'WARNING',
},
},
}
logger
https://docs.python.org/3/library/logging.html#logger-objects
从上面的例子可以看到,logger
有一个属性是propagate
,这个属性的作用是将收到的消息复制一份到更高级别的logger
关于logger
的层级意思是:通过.
分割的logger_name
上述列子中,层级高低排序是:
root
>django
>django.request
=django.server
root
>django
>``django.db.backends`
handler
https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers
在上述例子中,handler
的class
都是python
的内置类型
formatter
格式化logrecord
对象,排版logrecord
的属性
logrecord
https://docs.python.org/zh-cn/3.9/library/logging.html#logrecord-attributes
LoggerAdapter
https://docs.python.org/zh-cn/3.9/library/logging.html#loggeradapter-objects
调用
import logging, logging.config
logging.config.dictConfig(LOGGING) # django 无需此步骤,django 会自动加载
logger = logging.getLogger(__name__) # 这里的logger名称要匹配上 dictConfig 定义的 logger, 匹配遵循名称层级规则
logger.info("message")