Configuración de Django Registro predeterminado

94

Parece que no puedo entender cómo configurar un registrador "predeterminado" para mi instalación de Django. Me gustaría usar la nueva LOGGINGconfiguración de Django 1.3 en settings.py.

He visto el ejemplo de Django Logging Doc , pero me parece que solo configuran controladores que harán registros para registradores particulares. En el caso de su ejemplo, configuraron un controlador para los registradores llamados 'django', 'django.request' y 'myproject.custom'.

Todo lo que quiero hacer es configurar un valor predeterminado logging.handlers.RotatingFileHandlerque manejará todos los registradores de forma predeterminada. es decir, si hago un nuevo módulo en algún lugar de mi proyecto y se indica con algo como:, my_app_name.my_new_moduledebería poder hacer esto y hacer que todos los registros vayan a los registros de archivos rotativos.

# In file './my_app_name/my_new_module.py'
import logging
logger = logging.getLogger('my_app_name.my_new_module')
logger.debug('Hello logs!') # <-- This should get logged to my RotatingFileHandler that I setup in `settings.py`!
Chris W.
fuente

Respuestas:

153

Lo averigué...

Se establece el registrador de 'coger todos' refiriéndose a ella con la cadena vacía: ''.

Como ejemplo, en la siguiente configuración, tengo todos los eventos de registro que se guardan en logs/mylog.log, con la excepción de los django.requesteventos de registro en los que se guardarán logs/django_request.log. Debido a que 'propagate'está configurado Falsepara mi django.requestregistrador, el evento de registro nunca llegará al registrador 'capturar todo'.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'loggers': {
        '': {
            'handlers': ['default'],
            'level': 'DEBUG',
            'propagate': True
        },
        'django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}
Chris W.
fuente
2
Chris, los documentos de Django sobre esto no son confusos. Gracias por esto.
5
Pequeña corrección: el comentario implica que el registro de sql se vería afectado por el registrador django.request. Para redirigir el registro de SQL, debe definir un registrador para 'django.db'. El registrador django.request maneja respuestas http 5xx y 4xx.
rych
En esto ayuda a otros novatos como yo: el registrador creará los archivos de registro, pero logs/primero debes crear la carpeta :-). De lo contrario, obtendrá un error cuando ejecute ./manange.py runserver. @Chris W. Gracias por su ejemplo de configuración de registro. ¡Me ayudo mucho!
hobbes3
3
@arindamroychowdhury Con la configuración anterior, si lo hace logger = logging.getLogger('foo'); logger.warn('bar');, el defaultcontrolador detectará ese registro y algo así <time> WARN: foo: barterminará enlogs/mylog.log
Chris W.
8
Gracias, parece que esto '' significa registrador de raíz. Esta información útil no se encontró en la documentación de Django.
Eino Mäkitalo
25

Como dijiste en tu respuesta , Chris, una opción para definir un registrador predeterminado es usar la cadena vacía como clave.

Sin embargo, creo que la forma prevista es definir un registrador especial bajo la rootclave del diccionario de configuración de registro. Encontré esto en la documentación de Python :

root : esta será la configuración del registrador raíz. El procesamiento de la configuración será como para cualquier registrador, excepto que la propagateconfiguración no será aplicable.

Aquí está la configuración de su respuesta cambiada para usar la rootclave:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'root': {
        'handlers': ['default'],
        'level': 'DEBUG'
    },
    'loggers': {
        'django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}

Para ser justos, no veo ninguna diferencia de comportamiento entre las dos configuraciones. Parece que definir un registrador con una clave de cadena vacía modificará el registrador raíz, porque logging.getLogger('')devolverá el registrador raíz.

La única razón por la que prefiero 'root'más ''es que es explícito acerca de cómo modificar el registrador raíz. En caso de que tenga curiosidad, 'root'anula ''si define ambos, solo porque la entrada raíz se procesa en último lugar.

Don Kirkby
fuente
Sí, es cierto, ¡perdón por la corrección incorrecta! Si bien usar '' en lugar de 'root' es algo lógico, todavía me parece un poco inconsistente mover la rootentrada a la raíz del dict en el proceso de transición sin problemas de la lógica 2.6 fileConfig a 2.7 dictConfig one.
Antony Hatchkins
2
import logging
logger = logging.getLogger(__name__)

Tras añadir:

logging.basicConfig(
    level = logging.DEBUG,
    format = '%(name)s %(levelname)s %(message)s',
)

podemos cambiar el formato a:

format = '"%(levelname)s:%(name)s:%(message)s"  ',

o

format = '%(name)s %(asctime)s %(levelname)s %(message)s',
Sérgio
fuente
0

Hice una muestra rápida para verificar qué configuración se usa cuando se hace referencia tanto a la rootclave como al ''registrador vacío en el dictado de configuración.

import logging.config

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'fmt1': {
            'format': '[FMT1] %(asctime)-15s %(message)s',
        },
        'fmt2': {
            'format': '[FMT2] %(asctime)-15s %(message)s',
        }
    },
    'handlers': {
        'console1': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt1',
        },
        'console2': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt2',
        },
    },
    # First config for root logger: console1 -> fmt1
    'root': {
        'handlers': ['console1'],
        'level': 'DEBUG',
        'propagate': True,
    },
    'loggers': {
        # Second config for root logger: console2 -> fmt2
        '': {
            'handlers': ['console2'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

logging.config.dictConfig(LOGGING)

l1 = logging.getLogger()
l2 = logging.getLogger('')
root = logging.root

l1.info("l1")
l2.info("l2")
root.info("root logger")

Imprime el siguiente resultado:

[FMT1] 2018-12-18 17:24:47,691 l1
[FMT1] 2018-12-18 17:24:47,691 l2
[FMT1] 2018-12-18 17:24:47,691 root logger

lo que indica que la configuración bajo rootclave tiene la máxima prioridad. Si se elimina el bloque, el resultado es:

[FMT2] 2018-12-18 17:25:43,757 l1
[FMT2] 2018-12-18 17:25:43,757 l2
[FMT2] 2018-12-18 17:25:43,757 root logger

En ambos casos, pude depurar y determinar que los tres registradores ( l1, l2y root) hacían referencia a la misma instancia de registrador, el registrador raíz.

Espero que ayude a otros que, como yo, estaban confundidos por las 2 formas diferentes de configurar el registrador raíz.

Antwane
fuente