Où est un exemple complet de logging.config.dictConfig?

133

J'aimerais utiliser dictConfig , mais la documentation est un peu abstraite. Où puis-je trouver un exemple concret, copiable et collable du dictionnaire utilisé avec dictConfig?

David Wolever
la source

Réponses:

201

Et ici!

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
        },
    } 
}

Usage:

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

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

Si vous voyez trop de journaux de packages tiers, assurez-vous d'exécuter cette configuration en utilisant logging.config.dictConfig(LOGGING_CONFIG) avant que les packages tiers ne soient importés.

Référence: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema

Dave
la source
11
Il existe un autre endroit pour spécifier l' rootenregistreur: au niveau supérieur du dictionnaire. Il est décrit dans la documentation , a la préférence sur le ['loggers']['']lorsque les deux sont présents, mais à mon avis, ['loggers']['']est plus logique. Voir aussi la discussion ici
Antony Hatchkins
2
Tous ces beaux extraits YAML concis dans la documentation python logging.config ne peuvent tout simplement pas être lus directement. Bummer.
JimB
N'est-ce pas spécifique à Django? Que faire si j'utilise un autre framework (Flask, Bottle, etc.) ou que je ne travaille même pas sur une application Web?
Adam Parkin
Cela ressemble à une triche avec 'disable_existing_loggers': Falseas alors vous ne configurez peut-être pas tout le tissu, mais peut-être en réutilisant quelque chose qui est déjà là. Si vous le réglez, Trueje ne semble pas obtenir de sortie.
Nick T
Salut @Dave, comment puis-je utiliser une classe personnalisée à formatpartir de formatters?
Rafa Acioly
40

La réponse acceptée est gentille! Mais que se passerait-il si l'on pouvait commencer par quelque chose de moins complexe? Le module de journalisation est une chose très puissante et la documentation est un peu écrasante, surtout pour les novices. Mais pour le début, vous n'avez pas besoin de configurer les formateurs et les gestionnaires. Vous pouvez l'ajouter lorsque vous déterminez ce que vous voulez.

Par exemple:

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
la source
C'est l'exemple le plus pertinent / utile, du moins dans mon cas. C'est la finale logging.info('Hello, log')qui a fait claquer les choses pour moi. La confusion dans la documentation est qu'avec dictConfig, nous n'avons plus besoin d'effectuer getLoggerou l'une de ces actions.
Mike Williamson
@theotheo Pouvez-vous expliquer la clé vide '': { 'level': 'INFO'...et pourquoi elle ne fonctionne pas sans elle (par exemple, lors de la modification de la valeur vide en une valeur valide telle questandard
user9074332
1
@MikeWilliamson: Il peut être utile, cependant, de continuer à appeler getLogger()si vous voulez plusieurs enregistreurs avec des noms différents. Chacun de ces enregistreurs hérite de la configuration de l'enregistreur racine.
Elias Strehle
3
@MikeWilliamson getLoggerest toujours facultatif. Lorsque vous utilisez la logging.info()méthode directement, l'enregistreur racine est utilisé, tandis qu'avec getLogger()vous pouvez avoir différents enregistreurs, avec des noms et des niveaux différents.
sox avec Monica
8

Exemple avec Stream Handler, File Handler, Rotating File Handler et 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
la source
4

J'ai trouvé la configuration par défaut de Django v1.11.15 ci-dessous, j'espère que cela aide

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,
        },
    }
}
天才 小飞 猫
la source
4
Cet exemple est bien, mais je pense que pour se démarquer au-delà de la réponse acceptée, une explication serait utile.
Mike Williamson
-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
la source