Journalisation par défaut de Django Setup

94

Je n'arrive pas à comprendre comment configurer un enregistreur "par défaut" pour mon installation Django. Je voudrais utiliser le nouveau LOGGINGparamètre de Django 1.3 dans settings.py.

J'ai regardé l'exemple du Django Logging Doc , mais il me semble qu'ils ne configurent que des gestionnaires qui feront la journalisation pour des enregistreurs particuliers. Dans le cas de leur exemple, ils installent un gestionnaire pour les enregistreurs nommés «django», «django.request» et «myproject.custom».

Tout ce que je veux faire est de configurer une valeur par défaut logging.handlers.RotatingFileHandlerqui gérera tous les enregistreurs par défaut. c'est-à-dire que si je crée un nouveau module quelque part dans mon projet et qu'il est indiqué par quelque chose comme:, my_app_name.my_new_moduleje devrais pouvoir le faire et avoir tous les journaux dans les journaux de fichiers en rotation.

# 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.
la source

Réponses:

153

Deviner...

Vous définissez l'enregistreur « fourre - tout » en faisant référence avec la chaîne vide ''.

À titre d'exemple, dans la configuration suivante, j'ai enregistré tous les événements de journal dans logs/mylog.log, à l'exception des django.requestévénements de journal qui seront enregistrés dans logs/django_request.log. Comme il 'propagate'est défini sur Falsepour mon django.requestenregistreur, l'événement du journal n'atteindra jamais le journal «catch all».

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.
la source
2
Chris, la documentation Django à ce sujet ne prête pas à confusion. Merci pour cela.
5
Petite correction: le commentaire implique que la journalisation SQL serait affectée par le logger django.request. Pour rediriger la journalisation SQL, vous définiriez un enregistreur pour «django.db». L'enregistreur django.request gère les réponses http 5xx et 4xx.
rych le
Cela aide d'autres noobs comme moi: l'enregistreur créera les fichiers journaux, mais vous devez d'abord créer le logs/dossier :-). Sinon, vous obtiendrez une erreur lorsque vous exécuterez ./manange.py runserver. @Chris W. Merci pour vos exemples de paramètres de journalisation. Cela m'a beaucoup aidé!
hobbes3
3
@arindamroychowdhury Avec la configuration ci-dessus, si vous le faites, logger = logging.getLogger('foo'); logger.warn('bar');le defaultgestionnaire attrapera cette journalisation et quelque chose comme cela <time> WARN: foo: barse terminera danslogs/mylog.log
Chris W.
8
Merci, il semble que cela '' signifie root logger. Cette information utile n'a pas été trouvée dans la documentation de Django.
Eino Mäkitalo
25

Comme vous l'avez dit dans votre réponse , Chris, une option pour définir un enregistreur par défaut est d'utiliser la chaîne vide comme clé.

Cependant, je pense que la manière prévue est de définir un enregistreur spécial sous la rootclé du dictionnaire de configuration de journalisation. J'ai trouvé ceci dans la documentation Python :

root - ce sera la configuration de l'enregistreur racine. Le traitement de la configuration sera comme pour n'importe quel enregistreur, sauf que le propagateparamètre ne sera pas applicable.

Voici la configuration de votre réponse modifiée pour utiliser la rootclé:

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

Pour être honnête, je ne vois aucune différence de comportement entre les deux configurations. Il semble que la définition d'un enregistreur avec une clé de chaîne vide modifiera l'enregistreur racine, car logging.getLogger('')retournera l'enregistreur racine.

La seule raison pour laquelle je préfère 'root'plus ''est qu'il est explicite sur la modification de l'enregistreur racine. Au cas où vous étiez curieux, 'root'remplace ''si vous définissez les deux, simplement parce que l'entrée racine est traitée en dernier.

Don Kirkby
la source
Oui, c'est vrai, désolé pour une erreur de correction! Bien que l'utilisation de '' au lieu de 'root' soit quelque peu logique, je trouve toujours un peu incohérent de leur part de déplacer l' rootentrée dans la racine du dict dans le processus de transition par ailleurs en douceur de la logique 2.6 fileConfig vers 2.7 dictConfig one.
Antony Hatchkins
2
import logging
logger = logging.getLogger(__name__)

après ajouter:

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

nous pouvons changer de format pour:

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

ou

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

J'ai fait un échantillon rapide pour vérifier quelle configuration est utilisée lorsque la rootclé et l' ''enregistreur vide sont référencés dans config dict.

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 le résultat suivant:

[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

indiquant que la configuration sous rootclé a la priorité la plus élevée. Si le bloc est supprimé, le résultat est:

[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

Dans les deux cas, j'ai pu déboguer et de déterminer que les trois enregistreurs ( l1, l2et root) fait référence la même instance de l' enregistreur, l'enregistreur racine.

J'espère que cela aidera d'autres personnes qui, comme moi, ont été déroutées par les 2 façons différentes de configurer l'enregistreur racine.

Antwane
la source