OrP*_*rPo 30 python django django-rest-framework
出于调试目的,我想使用Django的日志记录机制来记录每个传入的请求,当它"到达"django-rest-framework的门口时.
Djagno以下列方式提供其请求的记录(仅"警告"日志级别及以上)(来自settings.py中的LOGGING部分):
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
Run Code Online (Sandbox Code Playgroud)
我想要实现这样的事情(注意:日志级别是DEBUG):
'rest_framework.request': {
'handlers': ['logfile'],
'level': 'DEBUG',
'propagate': False,
},
Run Code Online (Sandbox Code Playgroud)
有没有办法在不将记录器嵌入DRF的源代码的情况下做到这一点?
DRF中是否有某种"Logging Backend"选项我不知道?
thn*_*nee 26
我做了一个RequestLogMiddleware可以挂钩到任何Django View使用的泛型decorator_from_middleware.
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
from rest_framework import generics
from ...request_log.mixins import RequestLogViewMixin
class SomeListView(
RequestLogViewMixin,
generics.ListAPIView
):
...
Run Code Online (Sandbox Code Playgroud)
Gly*_*son 11
重写APIView.initial()方法以自行添加日志记录.
派遣方式
视图的.dispatch()方法直接调用以下方法.这些执行在调用处理程序方法之前或之后需要执行的任何操作,例如.get(),.postt(),put(),patch()和.delete().
.initial(self, request, *args, **kwargs)
执行在调用处理程序方法之前需要执行的任何操作.此方法用于强制执行权限和限制,以及执行内容协商.
这是我当前的解决方案,用于获取日志中的每个请求/响应。我创建了一个与旧中间件(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
Run Code Online (Sandbox Code Playgroud)
几年后,Rhumbix 推出了这个库,有人尝试过吗?
https://github.com/Rhumbix/django-request-logging
MIDDLEWARE = (
...,
'request_logging.middleware.LoggingMiddleware',
...,
)
Run Code Online (Sandbox Code Playgroud)
并在您的应用程序中配置日志记录:
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,
},
},
}
Run Code Online (Sandbox Code Playgroud)
制作了自定义中间件:
import logging
import time
logger = logging.getLogger(__name__)
class APILogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
duration = time.time() - start_time
response_ms = duration * 1000
user = str(getattr(request, 'user', ''))
method = str(getattr(request, 'method', '')).upper()
status_code = str(getattr(response, 'status_code', ''))
request_path = str(getattr(request, 'path', ''))
if status_code == '200' and response_ms > 2000:
logger.info({
"message": "*****SLOW RESPONSE****",
"path": request_path,
"response_time": str(response_ms) + " ms",
"method": method,
"user": user,
"status_code": status_code
})
return response
Run Code Online (Sandbox Code Playgroud)
这会记录所有需要 2 秒以上才能返回响应的 API。只需在 settings.py 中添加 MIDDLEWARE = ["path.to.APILogMiddleware"] 的完整路径
| 归档时间: |
|
| 查看次数: |
18044 次 |
| 最近记录: |