Saltar al contenido

Configuración elegante de registro de Python en Django

Basta ya de investigar por todo internet porque llegaste al espacio adecuado, tenemos la respuesta que buscas pero sin complicaciones.

Solución:

Sé que esta ya es una respuesta resuelta, pero según django> = 1.3 hay una nueva configuración de registro.

Pasar de lo antiguo a lo nuevo no es automático, así que pensé en escribirlo aquí.

Y, por supuesto, consulte el documento de django para obtener más información.

Esta es la configuración básica, creada por defecto con django-admin createproject v1.3 – el kilometraje puede cambiar con las últimas versiones de django:

LOGGING = 
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': 
        'mail_admins': 
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
        
    ,
    'loggers': 
        'django.request': 
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        
    

Esta estructura se basa en el dictConfig de registro estándar de Python, que dicta los siguientes bloques:

  • formatters – el valor correspondiente será un dict en el que cada key es un id del formateador y cada valor es un dictado que describe cómo configurar la instancia del formateador correspondiente.
  • filters – el valor correspondiente será un dict en el que cada key es un ID de filtro y cada valor es un diccionario que describe cómo configurar la instancia de filtro correspondiente.
  • handlers – el valor correspondiente será un dict en el que cada key es un identificador de controlador y cada valor es un diccionario que describe cómo configurar la instancia de controlador correspondiente. Cada controlador tiene lo siguiente keys:

    • class (obligatorio). Este es el nombre completo de la clase de controlador.
    • level (Opcional). El nivel del manejador.
    • formatter (Opcional). El id del formateador para este controlador.
    • filters (Opcional). Una lista de identificadores de los filtros para este controlador.

Normalmente hago al menos esto:

  • agregar un archivo .log
  • configurar mis aplicaciones para escribir en este registro

Que se traduce en:

LOGGING = 
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': 
        'verbose': 
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        ,
        'simple': 
            'format': '%(levelname)s %(message)s'
        ,
    ,
    'filters': 
        'require_debug_false': 
            '()': 'django.utils.log.RequireDebugFalse'
        
    ,
    'handlers': 
        'null': 
            'level':'DEBUG',
            'class':'django.utils.log.NullHandler',
        ,
        'console':
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        ,
        # I always add this handler to facilitate separating loggings
        'log_file':
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(VAR_ROOT, 'logs/django.log'),
            'maxBytes': '16777216', # 16megabytes
            'formatter': 'verbose'
        ,
        'mail_admins': 
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler',
            'include_html': True,
        
    ,
    'loggers': 
        'django.request': 
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        ,
        'apps':  # I keep all my of apps under 'apps' folder, but you can also add them one by one, and this depends on how your virtualenv/paths are set
            'handlers': ['log_file'],
            'level': 'INFO',
            'propagate': True,
        ,
    ,
    # you can also shortcut 'loggers' and just configure logging for EVERYTHING at once
    'root': 
        'handlers': ['console', 'mail_admins'],
        'level': 'INFO'
    ,

editar

Vea que las excepciones de solicitud ahora siempre se registran y el ticket n. ° 16288:

Actualicé la configuración de muestra anterior para incluir explícitamente el filtro correcto para mail_admins para que, de forma predeterminada, los correos electrónicos no se envíen cuando la depuración sea Verdadero.

Deberías agregar un filtro:

'filters': 
    'require_debug_false': 
        '()': 'django.utils.log.RequireDebugFalse'
    
,

y aplicarlo al controlador mail_admins:

    'mail_admins': 
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'django.utils.log.AdminEmailHandler',
        'include_html': True,
    

De lo contrario, el django.core.handers.base.handle_uncaught_exception no pasa errores al registrador ‘django.request’ si settings.DEBUG es True.

Si no hace esto en Django 1.5, obtendrá un

DeprecationWarning: No tiene filtros definidos en el controlador de registro ‘mail_admins’: agregando depuración implícitafalse-sólo filtro

pero las cosas seguirán funcionando correctamente AMBOS en django 1.4 y django 1.5.

** fin de editar **

Ese conf está fuertemente inspirado por el ejemplo de conf en el documento de django, pero agregando la parte del archivo de registro.

A menudo también hago lo siguiente:

LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'

...
    'level': LOG_LEVEL
...

Luego, en mi código de Python, siempre agrego un NullHandler en caso de que no se defina ninguna configuración de registro. Esto evita advertencias para ningún Handler especificado. Especialmente útil para bibliotecas que no necesariamente se llaman solo en Django (ref)

import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
class NullHandler(logging.Handler): #exists in python 3.1
    def emit(self, record):
        pass
nullhandler = logger.addHandler(NullHandler())

# here you can also add some local logger should you want: to stdout with streamhandler, or to a local file...

[…]

logger.warning('etc.etc.')

¡Espero que esto ayude!

La mejor forma que he encontrado hasta ahora es inicializar la configuración de registro en settings.py, en ningún otro lugar. Puede utilizar un archivo de configuración o hacerlo mediante programación paso a paso, solo depende de sus requisitos. los key Lo que pasa es que normalmente agrego los controladores que quiero al registrador raíz, usando niveles y, a veces, registrando.Filtros para obtener los eventos que quiero en los archivos apropiados, consola, syslogs, etc.Por supuesto, también puede agregar controladores a cualquier otro registrador, pero, en mi experiencia, no suele ser necesario hacerlo.

En cada módulo, defino un registrador usando

logger = logging.getLogger(__name__)

y utilícelo para registrar eventos en el módulo (y, si quiero diferenciarlo más) use un registrador que sea hijo del registrador creado anteriormente.

Si mi aplicación se va a usar potencialmente en un sitio que no configura el inicio de sesión en settings.py, defino un NullHandler en algún lugar de la siguiente manera:

#someutils.py

class NullHandler(logging.Handler):
    def emit(self, record):
        pass

null_handler = NullHandler()

y asegurarme de que se agregue una instancia a todos los registradores creados en los módulos de mis aplicaciones que usan el registro. (Nota: NullHandler ya está en el paquete de registro para Python 3.1 y estará en Python 2.7). Entonces:

logger = logging.getLogger(__name__)
logger.addHandler(someutils.null_handler)

Esto se hace para garantizar que sus módulos funcionen bien en un sitio que no configura el inicio de sesión en settings.py, y que no reciba ningún mensaje molesto “No se pudieron encontrar controladores para el registrador XYZ” (que son advertencias sobre posibles registro mal configurado).

Hacerlo de esta manera cumple con los requisitos establecidos:

  • Puede configurar diferentes controladores de registro para diferentes eventos, como lo hace actualmente.
  • Fácil acceso a los registradores en sus módulos – uso getLogger(__name__).
  • Fácilmente aplicable a módulos de línea de comandos; también importan settings.py.

Actualizar: Tenga en cuenta que a partir de la versión 1.3, Django ahora incorpora soporte para el registro.

Inicializamos el registro en el nivel superior urls.py usando un logging.ini expediente.

La ubicación del logging.ini se proporciona en settings.py, pero eso es todo.

Luego, cada módulo

logger = logging.getLogger(__name__)

Para distinguir las instancias de prueba, desarrollo y producción, tenemos diferentes archivos logging.ini. En su mayor parte, tenemos un “registro de consola” que va a stderr solo con errores. Tenemos un “registro de la aplicación” que utiliza un archivo de registro continuo que va a un directorio de registros.

Agradecemos que desees añadir valor a nuestra información asistiendo con tu veteranía en las aclaraciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *