python日志动态收集
项目进行时遇到了一个问题,需要将生成的日志按照项目类别输出到不同的目录下,具体解决方案如下:
1.日志的格式选择标准字典,default的级别设置为DEBUG,warn为WARN,error为ERROR。写文件的handler类为’class’: ‘logging.handlers.RotatingFileHandler’。
2.写一个继承logging.logger的类,实例化时输入需要创建的目录名称即可。
class MyLogger(logging.Logger):
_is_initialize = False
def __new__(cls, app_name):
if not cls._is_initialize:
base_dir = os.path.dirname(os.path.abspath(__file__))
base_log_dir = os.path.join(base_dir, "../logs/{}".format(app_name))
LOGGING = {
'version': 1, # 保留的参数,默认是1
'disable_existing_loggers': False, # 是否禁用已经存在的logger实例
# 日志输出格式的定义
'formatters': {
'standard': { # 标准的日志格式化
'format': '%(levelname)s %(asctime)s %(module)s %(message)s'
},
'error': { # 错误日志输出格式
'format': '%(levelname)s %(asctime)s %(pathname)s %(module)s %(message)s'
},
'simple': {
'format': '%(levelname)s %(asctime)s %(message)s'
},
'collect': {
'format': '%(message)s'
}
},
# 过滤器
'filters': {
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
}, # 针对 DEBUG = True 的情况
},
# 处理器:需要处理什么级别的日志及如何处理
'handlers': {
# 将日志打印到终端
'console': {
'level': 'DEBUG', # 日志级别
'class': 'logging.StreamHandler', # 使用什么类去处理日志流
'formatter': 'simple' # 指定上面定义过的一种日志输出格式
},
# 默认日志处理器
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(base_log_dir, "default.log"), # 日志文件路径
'maxBytes': 1024 * 1024 * 100, # 日志大小 100M
'backupCount': 5, # 日志文件备份的数量
'formatter': 'standard', # 日志输出格式
'encoding': 'utf-8',
},
# 日志处理级别warn
'warn': {
'level': 'WARN',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(base_log_dir, "warn.log"), # 日志文件路径
'maxBytes': 1024 * 1024 * 100, # 日志大小 100M
'backupCount': 5, # 日志文件备份的数量
'formatter': 'standard', # 日志格式
'encoding': 'utf-8',
},
# 日志级别error
'error': {
'level': 'ERROR',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
'filename': os.path.join(base_log_dir, "error.log"), # 日志文件路径
'maxBytes': 1024 * 1024 * 100, # 日志大小 100M
'backupCount': 5,
'formatter': 'error', # 日志格式
'encoding': 'utf-8',
},
'request_handler': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(base_log_dir, "request.log"),
'maxBytes': 1024 * 1024 * 5,
'backupCount': 5,
'formatter': 'standard',
},
'scripts_handler': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(base_log_dir, "script.log"),
'maxBytes': 1024 * 1024 * 5,
'backupCount': 5,
'formatter': 'standard',
}
},
'loggers': {
# 默认的logger应用如下配置
'default': {
'handlers': ['default', 'warn', 'error'],
'level': 'DEBUG',
'propagate': True, # 如果有父级的logger示例,表示不要向上传递日志流
},
'collect': {
'handlers': ['console', 'default', 'warn', 'error'],
'level': 'INFO',
},
'django': {
'handlers': ['console'],
'level': 'INFO',
'propagate': False
},
'django.request': {
'handlers': ['request_handler'],
'level': 'INFO',
'propagate': False,
},
'scripts': {
'handlers': ['scripts_handler'],
'level': 'INFO',
'propagate': False
},
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
},
},
}
if not os.path.exists(base_log_dir):
os.makedirs(base_log_dir)
logging.config.dictConfig(LOGGING )
cls._is_initialize = True
return logging.getLogger('collect')
4.选择__new__方法而不是__init__方法:
如果选择__init__初始化的方式,每调用一次就初始化一次,会浪费一些资源,积少成多将会造成大量浪费。
5.如果文件不存在则创建,否则不创建:
if not os.path.exists(base_log_dir):
os.makedirs(base_log_dir)
6.加载logging的字典:
logging.config.dictConfig(LOGGING )
cls._is_initialize = True
7.使用方式:
需要用的地方加入下面代码:
import logging
logger = logging.getLogger(‘django’)
def test():
logger.info('info occured ')
logger.error(‘error occured’)
logger.warning(‘warning occured’)