Django 中如何优雅的记录日志
链接:https://zhuanlan.zhihu.com/p/133864368
项目/utils/custom_middleware.py
# 项目/utils/custom_middleware.py
import json
import logging
import socket
import threading
from django.utils.deprecation import MiddlewareMixin
local = threading.local()
class RequestLogFilter(logging.Filter):
"""
日志过滤器
"""
def filter(self, record):
record.sip = getattr(local, 'sip', 'none')
record.dip = getattr(local, 'dip', 'none')
record.body = getattr(local, 'body', 'none')
record.path = getattr(local, 'path', 'none')
record.method = getattr(local, 'method', 'none')
record.username = getattr(local, 'username', 'none')
record.status_code = getattr(local, 'status_code', 'none')
record.reason_phrase = getattr(local, 'reason_phrase', 'none')
return True
class RequestLogMiddleware(MiddlewareMixin):
"""
将request的信息记录在当前的请求线程上。
"""
def __init__(self, get_response=None):
self.get_response = get_response
self.apiLogger = logging.getLogger('web.log')
def __call__(self, request):
try:
body = json.loads(request.body)
except Exception:
body = dict()
if request.method == 'GET':
body.update(dict(request.GET))
else:
body.update(dict(request.POST))
local.body = body
local.path = request.path
local.method = request.method
local.username = request.user
local.sip = request.META.get('REMOTE_ADDR', '')
local.dip = socket.gethostbyname(socket.gethostname())
response = self.get_response(request)
local.status_code = response.status_code
local.reason_phrase = response.reason_phrase
self.apiLogger.info('system-auto')
return response
配置文件 settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 自定义中间件添加在最后
'lib.log_middleware.RequestLogMiddleware'
]
LOGGING = {
# 版本
'version': 1,
# 是否禁止默认配置的记录器
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '{"time": "%(asctime)s", "level": "%(levelname)s", "method": "%(method)s", "username": "%(username)s", "sip": "%(sip)s", "dip": "%(dip)s", "path": "%(path)s", "status_code": "%(status_code)s", "reason_phrase": "%(reason_phrase)s", "func": "%(module)s.%(funcName)s:%(lineno)d", "message": "%(message)s"}',
'datefmt': '%Y-%m-%d %H:%M:%S'
}
},
# 过滤器
'filters': {
'request_info': {'()': 'lib.log_middleware.RequestLogFilter'},
},
'handlers': {
# 标准输出
'console': {
'level': 'ERROR',
'class': 'logging.StreamHandler',
'formatter': 'standard'
},
# 自定义 handlers,输出到文件
'restful_api': {
'level': 'DEBUG',
# 时间滚动切分
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(LOGS_DIR, 'web-log.log'),
'formatter': 'standard',
# 调用过滤器
'filters': ['request_info'],
# 每天凌晨切分
'when': 'MIDNIGHT',
# 保存 30 天
'backupCount': 30,
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': 'ERROR',
'propagate': False
},
'web.log': {
'handlers': ['restful_api'],
'level': 'INFO',
# 此记录器处理过的消息就不再让 django 记录器再次处理了
'propagate': False
},
}
}