Как получить доступ к объекту запроса внутри пользовательского лог-форматера в Django?
Я настроил пользовательский форматер для регистрации моих данных в текстовый файл в формате JSON:
class CustomJsonFormatter(jsonlogger.JsonFormatter):
def add_fields(self, log_record, record, message_dict):
super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
log_record['timestamp'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')
log_record['level'] = record.levelname
log_record['location'] = record.name
Я хотел бы иметь возможность автоматического доступа к объекту запроса в этом формате, поскольку у меня есть "уникальный идентификатор запроса", который я хотел бы добавить в свои журналы. Таким образом, я буду знать, какие строки журнала относятся к какому запросу.
class CustomJsonFormatter(jsonlogger.JsonFormatter):
def add_fields(self, log_record, record, message_dict):
super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
log_record['timestamp'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')
log_record['level'] = record.levelname
log_record['location'] = record.name
log_record['request_id'] = request.uuid <--- Something like this
Есть ли способ достичь этого без необходимости вручную передавать объект запроса в каждую отдельную строку журнала?
Большое спасибо заранее
You can use middleware to attach the request to the thread context, and then access it in your formatter through threadlocals:
class RequestMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
self.process_request(request)
response = self.get_response(request)
self.process_response(request, response)
return response
def process_request(self, request):
Thread.currentThread().request = request
def process_response(self, request, response):
if hasattr(Thread.currentThread(), 'request'):
del Thread.currentThread().request
return response
Then in your formatter:
threadlocals.request.uuid
Note that this uses thread-local storage, so this will only work correctly if your Django application uses threading and not multiple processes.
Alternatively, you can pass the request explicitly as an extra parameter to the logger:
logger.info('message', extra={'request': request})
and then access that in your formatter as message_dict['request']. This will work across processes as well.