¿Dónde está un ejemplo completo de logging.config.dictConfig?

133

Me gustaría usar dictConfig , pero la documentación es un poco abstracta. ¿Dónde puedo encontrar un ejemplo concreto, copiar + pegar del diccionario utilizado dictConfig?

David Wolever
fuente

Respuestas:

201

¡Que tal aquí!

LOGGING_CONFIG = { 
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': { 
        'standard': { 
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': { 
        'default': { 
            'level': 'INFO',
            'formatter': 'standard',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',  # Default is stderr
        },
    },
    'loggers': { 
        '': {  # root logger
            'handlers': ['default'],
            'level': 'WARNING',
            'propagate': False
        },
        'my.packg': { 
            'handlers': ['default'],
            'level': 'INFO',
            'propagate': False
        },
        '__main__': {  # if __name__ == '__main__'
            'handlers': ['default'],
            'level': 'DEBUG',
            'propagate': False
        },
    } 
}

Uso:

# Run once at startup:
logging.config.dictConfig(LOGGING_CONFIG)

# Include in each module:
log = logging.getLogger(__name__)
log.debug("Logging is configured.")

En caso de que vea demasiados registros de paquetes de terceros, asegúrese de ejecutar esta configuración logging.config.dictConfig(LOGGING_CONFIG) antes de importar los paquetes de terceros.

Referencia: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema

Dave
fuente
11
Hay un lugar alternativo para especificar el rootregistrador: en el nivel superior del diccionario. Se describe en los documentos , tiene preferencia sobre ['loggers']['']cuándo ambos están presentes, pero en mi opinión, ['loggers']['']es más lógico. Vea también la discusión aquí
Antony Hatchkins
2
Todos esos fragmentos de YAML hermosos y concisos en la documentación de python logging.config simplemente no se pueden leer directamente. Gorrón.
JimB
¿No es esto específico de django? ¿Qué sucede si estoy usando un marco diferente (Frasco, Botella, etc.), o si ni siquiera estoy trabajando en una aplicación web?
Adam Parkin
Se siente como un truco, 'disable_existing_loggers': Falseya que tal vez no esté configurando todo el paño, pero tal vez reutilizando algo que ya está allí ... Si lo configura, Trueentonces no parece que obtenga ningún resultado.
Nick T
Hola @Dave, ¿cómo puedo usar una clase personalizada formatdesde formatters?
Rafa Acioly
40

¡La respuesta aceptada es buena! Pero, ¿y si uno pudiera comenzar con algo menos complejo? El módulo de registro es algo muy poderoso y la documentación es un poco abrumadora, especialmente para los novatos. Pero al principio no es necesario configurar formateadores y controladores. Puede agregarlo cuando descubra lo que quiere.

Por ejemplo:

import logging.config

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'loggers': {
        '': {
            'level': 'INFO',
        },
        'another.module': {
            'level': 'DEBUG',
        },
    }
}

logging.config.dictConfig(DEFAULT_LOGGING)

logging.info('Hello, log')
theotheo
fuente
Este es el ejemplo más relevante / útil, al menos en mi caso. Fue la final lo logging.info('Hello, log')que hizo que las cosas hicieran clic para mí. La confusión en la documentación es que con dictConfig ya no necesitamos realizar getLoggerninguna de esas acciones.
Mike Williamson
@theotheo ¿Puede explicar la clave vacía '': { 'level': 'INFO'...y por qué no funciona sin ella (por ejemplo, al cambiar el valor en blanco a un valor válido comostandard
user9074332
1
@MikeWilliamson: Sin embargo, puede ser útil llamar aún getLogger()si desea varios registradores con diferentes nombres. Cada uno de estos registradores hereda la configuración del registrador raíz.
Elias Strehle
3
@MikeWilliamson getLoggersiempre es opcional. Cuando se usa el logging.info()método directamente, se usa el registrador raíz, mientras que con getLogger()usted puede tener diferentes registradores, con diferentes nombres y niveles.
Medias con Monica
8

Ejemplo con Stream Handler, File Handler, Rotating File Handler y SMTP Handler

from logging.config import dictConfig

LOGGING_CONFIG = {
    'version': 1,
    'loggers': {
        '': {  # root logger
            'level': 'NOTSET',
            'handlers': ['debug_console_handler', 'info_rotating_file_handler', 'error_file_handler', 'critical_mail_handler'],
        },
        'my.package': { 
            'level': 'WARNING',
            'propagate': False,
            'handlers': ['info_rotating_file_handler', 'error_file_handler' ],
        },
    },
    'handlers': {
        'debug_console_handler': {
            'level': 'DEBUG',
            'formatter': 'info',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',
        },
        'info_rotating_file_handler': {
            'level': 'INFO',
            'formatter': 'info',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'info.log',
            'mode': 'a',
            'maxBytes': 1048576,
            'backupCount': 10
        },
        'error_file_handler': {
            'level': 'WARNING',
            'formatter': 'error',
            'class': 'logging.FileHandler',
            'filename': 'error.log',
            'mode': 'a',
        },
        'critical_mail_handler': {
            'level': 'CRITICAL',
            'formatter': 'error',
            'class': 'logging.handlers.SMTPHandler',
            'mailhost' : 'localhost',
            'fromaddr': '[email protected]',
            'toaddrs': ['[email protected]', '[email protected]'],
            'subject': 'Critical error with application name'
        }
    },
    'formatters': {
        'info': {
            'format': '%(asctime)s-%(levelname)s-%(name)s::%(module)s|%(lineno)s:: %(message)s'
        },
        'error': {
            'format': '%(asctime)s-%(levelname)s-%(name)s-%(process)d::%(module)s|%(lineno)s:: %(message)s'
        },
    },

}

dictConfig(LOGGING_CONFIG)
Yogesh Yadav
fuente
4

He encontrado Django v1.11.15 configuración por defecto a continuación, espero que ayude

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'formatters': {
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[%(server_time)s] %(message)s',
        }
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'django.server': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
        },
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,
        },
    }
}
天才 小飞 猫
fuente
44
Este ejemplo está bien, pero creo que para destacar más allá de la respuesta aceptada, alguna explicación ayudaría.
Mike Williamson el
-7
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import logging.handlers
from logging.config import dictConfig

logger = logging.getLogger(__name__)

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
}
def configure_logging(logfile_path):
    """
    Initialize logging defaults for Project.

    :param logfile_path: logfile used to the logfile
    :type logfile_path: string

    This function does:

    - Assign INFO and DEBUG level to logger file handler and console handler

    """
    dictConfig(DEFAULT_LOGGING)

    default_formatter = logging.Formatter(
        "[%(asctime)s] [%(levelname)s] [%(name)s] [%(funcName)s():%(lineno)s] [PID:%(process)d TID:%(thread)d] %(message)s",
        "%d/%m/%Y %H:%M:%S")

    file_handler = logging.handlers.RotatingFileHandler(logfile_path, maxBytes=10485760,backupCount=300, encoding='utf-8')
    file_handler.setLevel(logging.INFO)

    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)

    file_handler.setFormatter(default_formatter)
    console_handler.setFormatter(default_formatter)

    logging.root.setLevel(logging.DEBUG)
    logging.root.addHandler(file_handler)
    logging.root.addHandler(console_handler)



[31/10/2015 22:00:33] [DEBUG] [yourmodulename] [yourfunction_name():9] [PID:61314 TID:140735248744448] this is logger infomation from hello module
wcc526
fuente