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


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


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')

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': 'monitoring@domain.com',
            'toaddrs': ['dev@domain.com', 'qa@domain.com'],
            '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)

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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.