Logging de Requisições e Respostas HTTP no Django com Django Rest Framework

O logging é um aspecto essencial de qualquer aplicação web, pois permite que os desenvolvedores rastreiem erros e depurem problemas que surgem durante o desenvolvimento e a produção. No Django, você pode usar a estrutura de logging integrada para registrar mensagens em vários destinos, como o console, arquivos ou email. No entanto, para registrar requisições e respostas HTTP, pode ser necessário criar um logger personalizado que capture essas informações.

Neste artigo, mostraremos como criar um logger personalizado no Django usando a classe LoggingMixin, e como configurar o logger usando o arquivo de configurações do Django.

Usando a Classe LoggingMixin

A classe LoggingMixin é um mixin reutilizável que você pode adicionar às suas views do Django para registrar requisições e respostas HTTP. A classe define dois métodos: initial() e finalize_response(). O método initial() é chamado antes da view ser executada, e o método finalize_response() é chamado depois que a view retorna uma resposta.

Aqui está um exemplo de implementação da classe LoggingMixin:

import logging

class LoggingMixin:
    """
    Fornece logging completo de requisições e respostas
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.logger = logging.getLogger('django.request')

    def initial(self, request, *args, **kwargs):
        try:
            self.logger.debug({
                "request": request.data,
                "method": request.method,
                "endpoint": request.path,
                "user": request.user.username,
                "ip_address": request.META.get('REMOTE_ADDR'),
                "user_agent": request.META.get('HTTP_USER_AGENT')
            })
        except Exception:
            self.logger.exception("Erro ao registrar dados da requisição")
        super().initial(request, *args, **kwargs)

    def finalize_response(self, request, response, *args, **kwargs):
        try:
            self.logger.debug({
                "response": response.data,
                "status_code": response.status_code,
                "user": request.user.username,
                "ip_address": request.META.get('REMOTE_ADDR'),
                "user_agent": request.META.get('HTTP_USER_AGENT')
            })
        except Exception:
            self.logger.exception("Erro ao registrar dados da resposta")
        return super().finalize_response(request, response, *args, **kwargs)
eption:
            self.logger.exception("Erro ao registrar dados da requisição")
        super().initial(request, *args, **kwargs)

    def finalize_response(self, request, response, *args, **kwargs):
        try:
            self.logger.debug({
                "response": response.data,
                "status_code": response.status_code,
                "user": request.user.username,
                "ip_address": request.META.get('REMOTE_ADDR'),
                "user_agent": request.META.get('HTTP_USER_AGENT')
            })
        except Exception:
            self.logger.exception("Erro ao registrar dados da resposta")
        return super().finalize_response(request, response, *args, **kwargs)

A classe LoggingMixin registra os dados da requisição e da resposta usando o método logger.debug(), que escreve as mensagens de log no nível DEBUG do logger. As mensagens de log incluem informações como o método da requisição, endpoint, usuário, endereço IP, agente de usuário, código de status da resposta e dados da resposta.

Para usar a classe LoggingMixin nas suas views do Django, você pode simplesmente adicioná-la como um mixin à sua classe de view, como neste exemplo:

from django.http import JsonResponse
from django.views import View
from .mixins import LoggingMixin

class MyView(LoggingMixin, View):
    def get(self, request):
        return JsonResponse({'message': 'Hello, world!'})

Configurando o Logger

Por padrão, o logger definido na classe MyView escreve as mensagens de log no console. No entanto, você pode querer configurar o logger para escrever as mensagens de log em um arquivo, enviar por email ou outro destino. Para isso, você pode configurar o logger no arquivo de configurações do Django usando o dicionário LOGGING.

Aqui está um exemplo de como configurar o logger para escrever as mensagens de log em um arquivo:

# settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'logs/request.log',
            'maxBytes': 10485760,  # 10 MB
            'backupCount': 5,
            'encoding': 'utf-8',
            'formatter': 'verbose'
        },
    },
    'formatters': {
        'verbose': {
            'format': '%(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)',
        },
    },
    'loggers': {
        'django.request': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

Neste exemplo, declaramos a configuração do logger no dicionário LOGGING, que pode ser colocado no arquivo de configurações do Django. Definimos um RotatingFileHandler, que é responsável por gravar os logs em um arquivo, com detalhes como tamanho máximo do arquivo, número de backups e formato das mensagens.

Conclusão

Em conclusão, o logging é uma parte essencial de qualquer aplicação web, e registrar requisições e respostas HTTP pode ser particularmente útil para rastrear e depurar problemas que surgem durante o desenvolvimento e a produção. Criando um logger personalizado no Django usando o Django Rest Framework, você pode facilmente capturar e registrar requisições e respostas HTTP em um formato estruturado que é fácil de ler e analisar.

Usando a classe APIView no Django Rest Framework, podemos definir métodos personalizados que manipulam requisições e respostas HTTP, e configurando o logger usando o arquivo de configurações do Django, podemos controlar onde as mensagens de log são escritas e como elas são formatadas. Seguindo as melhores práticas de logging, como definir níveis de log e usar arquivos de log rotativos, podemos garantir que nossas mensagens de log sejam eficientes, seguras e fáceis de manter.