Demandes de journalisation à django-rest-framework
pour le débogage, J'aimerais utiliser le mécanisme de journalisation de Django pour enregistrer chaque requête entrante quand elle" arrive " à la porte de django-rest-framework.
Djagno offre la journalisation de ses requêtes (seulement le niveau de log "warning" et au-dessus) de la manière suivante (à partir de la section LOGGING dans settings.py):
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
je cherche à obtenir quelque chose comme ceci (notez: le niveau de log est DEBUG):
'rest_framework.request': {
'handlers': ['logfile'],
'level': 'DEBUG',
'propagate': False,
},
<!-Y a-t-il un moyen que je puisse faire ça? sans intégration d'un enregistreur de la FONDATION du code source?Y a-t-il peut-être une sorte d'option "Logging Backend" dans DRF dont je ne suis pas au courant?
5 réponses
j'ai fait un générique RequestLogMiddleware
qui peut être accroché dans toute Django View
en utilisant decorator_from_middleware
.
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
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
from rest_framework import generics
from ...request_log.mixins import RequestLogViewMixin
class SomeListView(
RequestLogViewMixin,
generics.ListAPIView
):
...
Remplacer APIView.initial()
méthode pour ajouter la journalisation vous-même.
méthodes D'expédition
les méthodes suivantes sont appelées directement par les vues .méthode dispatch (). Ceux-ci exécutent toutes les actions qui doivent se produire avant ou après l'appel des méthodes de handler telles que .obtenir. ,)(post (), (), patch() et .supprimer.)(
.initial(self, request, *args, **kwargs)
Effectue toutes les actions qui doivent se produire avant que la méthode handler soit appelée. Ce la méthode est utilisée pour forcer les permissions et l'étranglement, et effectuer la négociation de contenu.
j'ai trouvé pour moi que la meilleure et la plus flexible façon était d'ajouter la journalisation via un décorateur. J'ajoute simplement le décorateur à chacune des fonctions (post, get) à partir desquelles je veux enregistrer la requête, au lieu de faire partie de la classe overal view. Plus de contrôle sur ce qui est enregistré. Ces décorateurs prennent l'objet request passé dans (arg[1]) puis logent des parties de l'objet request dans un fichier.
Voir https://github.com/slogan621/tscharts/commit/39ed479b04b7077f128774d3a203a86d6f68f03e ce qui revient à un modèle pour ce faire (s'engager montre les changements settings.py nécessaire pour faire passer la journalisation dans le fichier de journalisation système que j'ai mis en place ainsi que le décorateur et exemple d'utilisation).
voici ma solution actuelle pour obtenir chaque requête / réponse dans le journal. J'ai créé un middleware compatible avec l'ancien middleware (Django < 1.10) et le nouveau middleware journal chaque requête/réponse. Cette solution est la meilleure que j'ai trouvée jusqu'à présent.
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
dans middleware/mixin.py
class RequestLogMiddleware(object):
def initial(self, request, *args, **kwargs):
super(RequestLogMiddleware, self).initial(request, *args, **kwargs)
# store/log the request
dans la Vue:
class ViewClass(RequestLogMiddleware, generics.RetrieveAPIView):
...