需求:日志根据级别不同,分别打印到不同的日志文件里。
其实这里主要使用过滤器来实现这个需求。
我们以打印一个HTTP请求的URL(request_path)、参数(request_params)、IP(request_ip)为例:
- 添加过滤器及中间件
假设包路径为:middleware.logging_middleware.LogMiddleware
class LogFilter(logging.Filter):
def filter(self, record):
record.request_path = getattr(local, 'request_path', None)
record.request_params = getattr(local, 'request_params', None)
record.request_ip = getattr(local, 'request_ip', None)
return True
class LogMiddleware(MiddlewareMixin):
def process_request(self, request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0] # 这里是真实的ip
else:
ip = request.META.get('REMOTE_ADDR') # 这里获得代理ip
local.request_path = request.path
local.request_params = json.dumps(request.POST)
local.request_ip = ip
def process_response(self, request, response):
return response
中间件LogMiddleware需要注册到配置文件settings. py,LogMiddleware类用于从request获取请求URL、参数、IP,保存到local对象,LogFilter类用于日志从local对象获取请求URL、参数、IP
- settings.py配置中间件
MIDDLEWARE = [
' middleware.logging_middleware.LogMiddleware ',
]
以上为配置中间件方法,具体配置以本地包路径为准
- settings.py配置过滤器
def debug_filter(record):
if record.levelname == 'DEBUG':
return True
return False
def info_filter(record):
if record.levelname == 'INFO':
return True
return False
def warning_filter(record):
if record.levelname == 'WARNING':
return True
return False
def error_filter(record):
if record.levelname == 'ERROR':
return True
return False
上面配置了4个过滤器,分别过滤日志四个级别,如果日志级别符合要求,则打印(返回True),否则忽略(返回False)
- settings.py日志相关配置
LOGGING = {
'version': 1,
'filters': {
'request_path': { # 此字段为第1步配置的过滤器的record对象的属性
'()': 'middleware.logging_middleware.LogFilter',
},
'request_params': {
'()': 'middleware.logging_middleware.LogFilter',
},
'request_ip': {
'()': 'middleware.logging_middleware.LogFilter',
},
'debug_filter': { # 注意这里的写法,有一个回调函数,为第3步配置的过滤器
'()': 'django.utils.log.CallbackFilter',
'callback': debug_filter,
},
'info_filter': {
'()': 'django.utils.log.CallbackFilter',
'callback': info_filter,
},
'warning_filter': {
'()': 'django.utils.log.CallbackFilter',
'callback': warning_filter,
},
'error_filter': {
'()': 'django.utils.log.CallbackFilter',
'callback': error_filter,
}
},
'formatters': {
'standard': {
'format': '%(request_path)s||%(request_params)s||%(request_ip)s'
}
},
'handlers': {
'debug': {
'level': 'DEBUG',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(BASE_DIR, 'log', 'debug.log'),
'filters': ['debug_filter', 'request_path', 'request_params', 'request_ip'],
'when': 'midnight',
'interval': 1,
'backupCount': 60,
'formatter': 'standard',
},
'info': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(BASE_DIR, 'log', 'info.log'),
'filters': ['info_filter', 'request_path', 'request_params', 'request_ip'],
'when': 'midnight',
'interval': 1,
'backupCount': 60,
'formatter': 'standard',
},
'warning': {
'level': 'WARNING',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(BASE_DIR, 'log', 'warning.log'),
'filters': ['warning_filter', 'request_path', 'request_params', 'request_ip'],
'when': 'midnight',
'interval': 1,
'backupCount': 60,
'formatter': 'standard',
},
'error': {
'level': 'ERROR',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(BASE_DIR, 'log', 'error.log'),
'filters': [' error_filter ', 'request_path', 'request_params', 'request_ip'],# 注意过滤器要写全,不要遗漏
'when': 'midnight',
'interval': 1,
'backupCount': 60,
'formatter': 'standard',
}
},
'loggers': {
'log': {
'handlers': ['error', 'warning', 'info', 'debug'],
'level': 'DEBUG',# 此次必须是DEBUG
'propagate': False
}
}
}
5、 开发人员使用日志
logging = logging.getLogger('log') # 定义日志记录器对象
logging.debug('debug') # 自定义不同级别和内容
logging.info('info')
logging.warning('warning')
logging.error('error')