Python logging em Django
Que o módulo logging e o framework Django são excelentes ferramentas pra qualquer trabalho todos sabem, mas como fazer para integrar os dois?
Eu sempre achei um saco o fato do Django não ter um módulo builtin/contrib que permitisse que ao fazer um simples logging.error('PAN!') a mensagem, a data, o nível, the universe and everything, fossem gravados no banco de dados. Pra resolver esse simples problema, nada como uma simples solução.

A Solução
Para começar crie um aplicativo em sua aplicação chamado "log", nunca crie a aplicação com nome de "logging", a não ser que você queira problemas com imports não funcionando:
python manage.py startapp log
Em seguida crie o seguinte model:
# -*- encoding: utf-8 -*- from django.db import models from django.contrib import admin import logging class Log(models.Model): level = models.IntegerField(db_index=True) file = models.CharField(max_length=512, db_index=True) lineno = models.IntegerField() date = models.DateTimeField(db_index=True) message = models.TextField() def _get_level_name(self): return logging.getLevelName(self.level) levelName = property(fget=_get_level_name) def _get_message_summary(self): if len(self.message) > 100: return '%s...'%(self.message[:100]) else: return self.message messageSummary = property(fget=_get_message_summary) def _get_file_summary(self): if len(self.file) > 30: return '...%s'%(self.file[-30:]) return self.file fileSummary = property(fget=_get_file_summary) class LogAdmin(admin.ModelAdmin): date_hierarchy = 'date' list_display = ('level', 'levelName', 'date','messageSummary', 'fileSummary', 'lineno') list_filter = ('level',) search_fields = ('message', 'file') admin.site.register(Log, LogAdmin)
Em seguida crie o arquivo "handler.py" dentro do aplicativo "log" com o seguinte conteúdo:
# -*- encoding: utf-8 -*- import logging import datetime from SEUPROJETO.log.models import Log class DjangoHandler(logging.Handler): '''Executa a manipulação do log e insere no banco de dados''' def emit(self, record): log = Log() log.level = record.levelno log.file = record.pathname log.lineno = record.lineno log.message = record.msg # TODO: Utiizar o record.created log.date = datetime.datetime.now() log.save()
Com isso você já tem tudo que precisa pra logar direto pro banco de dados, só falta uma coisa: Configurar o projeto para o logging usar nosso handler.
Pra fazer isso, edite o arquivo __init__.py (e você achando que esse arquivo era inutil
e adicione o seguinte conteúdo ao arquivo:
import logging from SEUPROJETO.log.handler import DjangoHandler django_handler = DjangoHandler() logging.root.addHandler(django_handler)
E pronto, é só correr pro abraço, todo e qualquer log que você executar vai ser armazenado no banco de dados.

Yes! Tudo que faltava pra terminar meu projeto!
... e antes que você venha me reclamar que a p0rr@ do log não ta aparecendo em lugar nenhum, verifique se você está usando o logging.debug com a configuração padrão do módulo logging (que só exibe mensagens de nível mais alto).
Em tempo: Eu sei que é extremamente simples criar um módulo/pacote com tudo isso, mas não seria tão didatico simplesmente falar "baixe aqui, copie ali e import lá".
Se você tiver interesse, sugira a implantação deste módulo ao django.contrib

