Django - ведение журнала ответов на каждый запрос
У меня есть API, построенный с использованием фреймворка Django. Мне нужно регистрировать следующие данные для каждого запроса, поступающего к API.
- Метод запроса
- Путь запроса
- Объект запроса
- Код статуса ответа
- Задержка ответа (если возможно)
Я пробовал использовать сигнал request_finished
, но он не приносит с собой объект ответа. Как я могу этого добиться?
Это работа для Django Middleware: https://docs.djangoproject.com/en/4.0/topics/http/middleware/
Когда вы устанавливаете "промежуточное ПО", вы получаете возможность вмешиваться до, во время и после обработки запроса, для всех запросов.
Как описано в ссылке документации, вам нужно создать класс Middleware, а затем сослаться на него в списке MIDDLEWARE
в settings
.
Middleware на основе классов достаточно прост, но более гибок (легко хранит состояние и имеет собственные методы). Что-то вроде этого:
class LogRequestsMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start = time.perf_counter()
response = self.get_response(request)
end = time.perf_counter()
self.log(request, start, end)
return response
def log(self, request, start, end):
# log request.method, request.path_info, etc.
# log end - start for duration
В этой настройке есть и другие хуки, но они вам не понадобятся. Даже если возникнет не пойманное исключение, Django обработает его и вернет объект ответа (из get_response
) для чтения.
Имейте в виду, что это не тот же объект запроса, который вы получаете в представлении. Это экземпляр django.core.handlers.wsgi.WSGIRequest
, но те значения, которые вы ищете, должны быть там.
Для расчета latency вы можете взять значения из time.perf_counter()
как до, так и после обработки запроса в вашем методе __call__
, а разницу считать длительностью:
elapsed = time.perf_counter() # Includes time elapsed during sleep system-wide
duration = time.process_time() # Process time not including sleep