Python 将请求记录到 django-rest-framework
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15578946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Logging requests to django-rest-framework
提问by OrPo
For debugging purposes, I would like to use Django's logging mechanism to log each and every incoming request when it "arrives" at django-rest-framework's doorstep.
出于调试目的,我想使用 Django 的日志记录机制来记录每个传入请求,当它“到达”django-rest-framework 的门口时。
Djagno offers logging of its requests (only "warning" log level and above) in the following manner (from LOGGING section in settings.py):
Djagno 以下列方式(来自 settings.py 中的 LOGGING 部分)提供其请求的日志记录(仅“警告”日志级别及更高级别):
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
I'm looking to achieve something like this (notice: log level is DEBUG):
我正在寻求实现这样的目标(注意:日志级别为调试):
'rest_framework.request': {
'handlers': ['logfile'],
'level': 'DEBUG',
'propagate': False,
},
Is there a way I can do that withoutembedding a logger in to DRF's source code?
Is there maybe some sort of "Logging Backend" option in DRF I'm not aware of?
有没有办法在不将记录器嵌入到 DRF 的源代码中的情况下做到这一点?
在我不知道的 DRF 中是否有某种“日志后端”选项?
回答by Glyn Hymanson
Override the APIView.initial()method to add logging yourself.
重写该APIView.initial()方法以自己添加日志记录。
Dispatch methods
The following methods are called directly by the view's .dispatch() method. These perform any actions that need to occur before or after calling the handler methods such as .get(), .post(), put(), patch() and .delete().
.initial(self, request, *args, **kwargs)
Performs any actions that need to occur before the handler method gets called. This method is used to enforce permissions and throttling, and perform content negotiation.
调度方式
以下方法由视图的 .dispatch() 方法直接调用。它们执行需要在调用处理程序方法之前或之后发生的任何操作,例如 .get()、.post()、put()、patch() 和 .delete()。
.initial(self, request, *args, **kwargs)
执行在调用处理程序方法之前需要发生的任何操作。此方法用于强制执行权限和限制,以及执行内容协商。
回答by thnee
I made a generic RequestLogMiddlewarethat can be hooked into any Django Viewusing decorator_from_middleware.
我制作了一个泛型RequestLogMiddleware,可以View使用decorator_from_middleware.
request_log/middleware.py
request_log/middleware.py
import socket
import time
class RequestLogMiddleware(object):
def process_request(self, request):
request.start_time = time.time()
def process_response(self, request, response):
if response['content-type'] == 'application/json':
if getattr(response, 'streaming', False):
response_body = '<<<Streaming>>>'
else:
response_body = response.content
else:
response_body = '<<<Not JSON>>>'
log_data = {
'user': request.user.pk,
'remote_address': request.META['REMOTE_ADDR'],
'server_hostname': socket.gethostname(),
'request_method': request.method,
'request_path': request.get_full_path(),
'request_body': request.body,
'response_status': response.status_code,
'response_body': response_body,
'run_time': time.time() - request.start_time,
}
# save log_data in some way
return response
request_log/mixins.py
request_log/mixins.py
from django.utils.decorators import decorator_from_middleware
from .middleware import RequestLogMiddleware
class RequestLogViewMixin(object):
"""
Adds RequestLogMiddleware to any Django View by overriding as_view.
"""
@classmethod
def as_view(cls, *args, **kwargs):
view = super(RequestLogViewMixin, cls).as_view(*args, **kwargs)
view = decorator_from_middleware(RequestLogMiddleware)(view)
return view
my_django_rest_api/views.py
my_django_rest_api/views.py
from rest_framework import generics
from ...request_log.mixins import RequestLogViewMixin
class SomeListView(
RequestLogViewMixin,
generics.ListAPIView
):
...
回答by slogan621
I found for me that the best and most flexible way was to add logging via a decorator. I simply add the decorator to each of the functions (post, get) that I want to log the request from, as opposed to it being a part of the overal view class. More control over what gets logged. These decorator take the request object passed in (arg[1]) and then logs parts of the request object to a file.
我发现最好和最灵活的方法是通过装饰器添加日志记录。我只是将装饰器添加到我想要记录请求的每个函数(post、get)中,而不是将其作为总体视图类的一部分。更好地控制记录的内容。这些装饰器接收传入的请求对象 (arg[1]),然后将请求对象的一部分记录到文件中。
See https://github.com/slogan621/tscharts/commit/39ed479b04b7077f128774d3a203a86d6f68f03efor what amounts to a template for doing this (commit shows changes to settings.py needed to thread the logging into the file logging scheme I have in place, as well as the decorator and example usage).
请参阅https://github.com/slogan621/tscharts/commit/39ed479b04b7077f128774d3a203a86d6f68f03e了解什么相当于执行此操作的模板(提交显示将日志记录到我现有的文件日志记录方案所需的 settings.py 更改,以及作为装饰器和示例用法)。
回答by Karim N Gorjux
Here my current solution to get every REQUEST/RESPONSE in the log. I created a middleware compatible with the old middleware (Django < 1.10) and the new middleware that log every request/response. This solution is the best I found so far.
这是我当前在日志中获取每个请求/响应的解决方案。我创建了一个与旧中间件(Django < 1.10)和记录每个请求/响应的新中间件兼容的中间件。这个解决方案是迄今为止我发现的最好的解决方案。
import logging
from django.utils.deprecation import MiddlewareMixin
_logger = logging.getLogger(__name__)
class LogRestMiddleware(MiddlewareMixin):
"""Middleware to log every request/response.
Is not triggered when the request/response is managed using the cache
"""
def _log_request(self, request):
"""Log the request"""
user = str(getattr(request, 'user', ''))
method = str(getattr(request, 'method', '')).upper()
request_path = str(getattr(request, 'path', ''))
query_params = str(["%s: %s" %(k,v) for k, v in request.GET.items()])
query_params = query_params if query_params else ''
_logger.debug("req: (%s) [%s] %s %s", user, method, request_path, query_params)
def _log_response(self, request, response):
"""Log the response using values from the request"""
user = str(getattr(request, 'user', ''))
method = str(getattr(request, 'method', '')).upper()
status_code = str(getattr(response, 'status_code', ''))
status_text = str(getattr(response, 'status_text', ''))
request_path = str(getattr(request, 'path', ''))
size = str(len(response.content))
_logger.debug("res: (%s) [%s] %s - %s (%s / %s)", user, method, request_path, status_code, status_text, size)
def process_response(self, request, response):
"""Method call when the middleware is used in the `MIDDLEWARE_CLASSES` option in the settings. Django < 1.10"""
self._log_request(request)
self._log_response(request, response)
return response
def __call__(self, request):
"""Method call when the middleware is used in the `MIDDLEWARE` option in the settings (Django >= 1.10)"""
self._log_request(request)
response = self.get_response(request)
self._log_response(request, response)
return response
回答by Coderji
Here is the code from @Glyn Hymanson's Answer:
这是@Glyn Hymanson 的回答中的代码:
in middleware/mixin.py
在中间件/mixin.py
class RequestLogMiddleware(object):
def initial(self, request, *args, **kwargs):
super(RequestLogMiddleware, self).initial(request, *args, **kwargs)
# store/log the request
in the View:
在视图中:
class ViewClass(RequestLogMiddleware, generics.RetrieveAPIView):
...
回答by om2c0de
In new Django 2+ better to use Middleware as a callable objectlike this, just connect it with your project in your Middlewares section of the settings.py file (also Middleware can be a function, not only a class because it's a callable object old MiddlewareMixinnow in the deprecatedmodule of Django):
在新的 Django 2+ 中,最好将中间件用作这样的可调用对象,只需将它与 settings.py 文件的中间件部分中的项目连接起来(中间件也可以是一个函数,而不仅仅是一个类,因为它是一个旧的可调用对象)MiddlewareMixin现在在Django的弃用模块中):
More info in docs:
https://docs.djangoproject.com/en/2.2/topics/http/middleware/#writing-your-own-middleware
文档中的更多信息:https:
//docs.djangoproject.com/en/2.2/topics/http/middleware/#writing-your-own-middleware
class UserActivityLogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print(request.method) # In this string we catch request object.
response = self.get_response(request)
return response
回答by paul
A few years later and Rhumbix has come out with this library, has anyone tried it?
几年后,Rhumbix 推出了这个库,有人尝试过吗?
https://github.com/Rhumbix/django-request-logging
https://github.com/Rhumbix/django-request-logging
MIDDLEWARE = (
...,
'request_logging.middleware.LoggingMiddleware',
...,
)
And configure logging in your app:
并在您的应用程序中配置日志记录:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.request': {
'handlers': ['console'],
'level': 'DEBUG', # change debug level as appropiate
'propagate': False,
},
},
}

