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?

27
demandé sur mlissner 2013-03-23 00:02:30

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
):
    ...
24
répondu thnee 2015-04-14 11:36:16

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.

9
répondu Glyn Jackson 2015-05-19 17:41:25

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).

0
répondu slogan621 2018-06-02 21:38:43

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
0
répondu Karim N Gorjux 2018-07-27 01:57:10

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):
     ...
0
répondu Coderji 2018-09-18 13:21:33