需求
请求view中手动打印日志时中插入request的如下信息(每个request请求都记录可以使用中间件进行解决,但这里仅仅是在需要的地方手动打印):
#统一附加日志内容ADD_LOG = r'''{"username": request.user, "path": request.path, "request_id": request.id, "login_id": request.login_id}'''
旧的解决办法
在每次需要打印日志时,通过 loggingextra** 进行额外的打印信息添加:
每次手动添加同样的extra非常的不优雅。
新的解决方案
1、熟悉python的logging模块结构。
2、django中间件存储request信息。
class RequestLogMiddleware(MiddlewareMixin):"""将request的信息记录在当前的请求线程上"""def process_request(self, request):# 统一附加日志内容# ADD_LOG = r'''{"username": request.user, "path": request.path, "request_id": request.id, "login_id": request.login_id}'''local.path = request.pathlocal.request_id = request.idlocal.login_id = request.login_idlocal.username = request.user.username
3、logging的filters模块添加request信息。
import loggingclass RequestLogFilter(logging.Filter):"""日志过滤器,将当前请求线程的request信息保存到日志的record上下文"""def filter(self, record):record.request_id = getattr(local, 'request_id', "none")record.path = getattr(local, 'path', "none")record.login_id = getattr(local, 'login_id', "none")record.username = getattr(local, 'username', "none")record.appName = getattr(local, "appName", "none")return True
4、实现原理及代码
通过 local = threading.local()local对象local 对象上。
middleware-waiwen文件代码:
import threadingimport loggingtry:from django.utils.deprecation import MiddlewareMixin # Django 1.10.xexcept ImportError:MiddlewareMixin = object # Django 1.4.x - Django 1.9.xlocal = threading.local()class RequestLogFilter(logging.Filter):"""日志过滤器,将当前请求线程的request信息保存到日志的record上下文record带有formater需要的信息。"""def filter(self, record):record.request_id = getattr(local, 'request_id', "none")record.path = getattr(local, 'path', "none")record.login_id = getattr(local, 'login_id', "none")record.username = getattr(local, 'username', "none")return Trueclass RequestLogMiddleware(MiddlewareMixin):"""将request的信息记录在当前的请求线程上。"""def process_request(self, request):# 统一附加日志内容# ADD_LOG = r'''{"username": request.user, "path": request.path, "request_id": request.id, "login_id": request.login_id}'''local.path = request.pathlocal.request_id = request.idlocal.login_id = request.login_idlocal.username = request.user.username
settings 文件配置
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','wcloud.middleware-waiwen.RequestLogMiddleware'#使用该中间件#将当前的request信息保存到当前线程供日志打印使用]LOGGING = {# 日志相关'version': 1,'disable_existing_loggers': False,'formatters': {'standard': {'format': '{"date": "%(created)f", "level": "%(levelname)s", "funcName": "%(module)s.%(funcName)s:%(lineno)d", "msg": "%(message)s"}'}, # 日志格式'custom': {#该格式化中包含有过滤器record新增的字段'format': '{"date": "%(created)f", "level": "%(levelname)s", "funcName": "%(module)s.%(funcName)s:%(lineno)d", "request_id": "%(request_id)s","login_id": "%(login_id)s", "username": "%(username)s", "path": "%(path)s","msg": "%(message)s"}'},},'filters': {#注册该过滤器'request_info': {'()': 'wcloud.middleware-waiwen.RequestLogFilter'}},'handlers': {'log': {'level': 'DEBUG','class': 'logging.StreamHandler','formatter': 'custom',#在该过handler中使用该过滤器'filters': ['request_info'],},'console': {'level': 'DEBUG','class': 'logging.StreamHandler','formatter': 'standard',},},'loggers': {'django': {'handlers': ['console'],'level': 'ERROR','propagate': False},'django.request': {'handlers': ['console'],'level': 'ERROR','propagate': False},'django.db.backens': {'handlers': ['console'],'level': 'DEBUG','propagate': False},'log': {'handlers': ['log'],'level': 'INFO','propagate': True},}}
