在项目中,我们可能需要定义不同的日志格式,有时需要定位到某一行,有的就不需要,并且根据情况要筛选不同的日志等级,例如,生产环境就不需要打印 DEBUG
级别的日志。这就涉及到需要多个日志模型。
python中定义了基本的日志组件让我们可以去组装和自定义以实现日志模型,功能包括日志信息过滤(脱敏)、筛选日志等级等等。这些组件包括:
logging.Logger
, logging.Handler
, logging.Formatter
, logging.Filter
, logging.LogRecord
, LoggerAdapter
。
logging.Logger
在 python 中获取 Logger
实例,一般是通过 logging.getLogger(name)
这个方法来获得,并且针对单个 name
,不管获得多少次,都是同一个实例。
Logger
的方法:setLevel
: 设置最低的日志输出的等级。在3.2版本之后可以接受 INFO
或是 20
这样的字符串或是整型类型信息。debug
、 info
、 warn
、 error
、warning
、 exception
、 critical
、 fatal
、log
Handler
添加与移除: addHandler
, removeHandler
LogRecord
: makeRecord
import logging
logger = logging.getLogger('test')
logger.setLevel('INFO')
logger.debug('test logger debug')
logger.info('test logger')
输出为: No handlers could be found for logger "test"
, 从结果看来,还缺少Handelr实例。
logging.Handler
实际来处理日志记录的类, 用以做一些特殊逻辑上的操作。如记录到文件、上传日志等等。
主要的方法有:
setLevel
setFormatter
format
: 格式化日志。addFilter
, removeFilter
handle
, handleError
, emit
, 最终的逻辑在 emit
中,handle
的逻辑是会加上锁,调用 emit
logging.Formatter
格式化日志记录的类, 主要方法有:
format(record)
formatTime
formatException
loggingFilter
Filter
的实例,能被用在 Handler
和 Logger
这个两个类的实例中。
该类的方法时 filter(record)
: 用来决定指定的 record
是否可以被记录, 能被记录返回True, 否则为False,并且,我们可以用来过滤一些参数信息,将敏感信息脱敏。
logging.LogRecord
用来记录一条日志中的所有信息和需要的信息。
Logger
的组合方式:使用代码,直接使用 Logger
、 Handler
等实例,进行组合:
import logging
logger = logging.getLogger('test')
logger.setLevel('INFO')
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
输出为:
2019-01-05 17:11:46,286 - test - INFO - info message
2019-01-05 17:11:46,286 - test - WARNING - warn message
2019-01-05 17:11:46,286 - test - ERROR - error message
2019-01-05 17:11:46,286 - test - CRITICAL - critical message
使用配置文件,加载配置文件, fileConfig()
配置文件信息为:
import logging
import logging.config
logging.config.fileConfig('logging.conf')
# create logger
logger = logging.getLogger('simpleExample')
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
[loggers]
keys=root,simpleExample
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
输出为:
2005-03-19 15:38:55,977 - simpleExample - DEBUG - debug message
2005-03-19 15:38:55,979 - simpleExample - INFO - info message
2005-03-19 15:38:56,054 - simpleExample - WARNING - warn message
2005-03-19 15:38:56,055 - simpleExample - ERROR - error message
2005-03-19 15:38:56,130 - simpleExample - CRITICAL - critical message
使用 dict
类型的变量进行配置, dictConfig()
.
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'filters': {
'special': {
'()': 'project.logging.SpecialFilter',
'foo': 'bar',
}
},
'handlers': {
'null': {
'level':'DEBUG',
'class':'django.utils.log.NullHandler',
},
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter': 'simple'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
}
},
'loggers': {
'django': {
'handlers':['null'],
'propagate': True,
'level':'INFO',
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'myproject.custom': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
'filters': ['special']
}
}
}
以上的配置 Logger
方案中,使用配置文件或是dict实例的方式更加合理,把配置和代码分离了,更容易扩展,应该作为实际项目中推荐的使用方式。
参考:
- https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
- https://docs.python.org/3/library/logging.html
- https://docs.python.org/3/howto/logging-cookbook.html#logging-cookbook