Django Setup Standardprotokollierung

94

Ich kann anscheinend nicht herausfinden, wie ein "Standard" -Logger für meine Django-Installation eingerichtet wird. Ich möchte die neue LOGGINGEinstellung von Django 1.3 in verwenden settings.py.

Ich habe mir das Beispiel des Django-Protokollierungsdokuments angesehen , aber es sieht für mich so aus, als würden sie nur Handler einrichten, die die Protokollierung für bestimmte Protokollierer durchführen. In ihrem Beispiel richten sie den Handler für die Logger mit den Namen 'django', 'django.request' und 'myproject.custom' ein.

Ich möchte lediglich einen Standard logging.handlers.RotatingFileHandlereinrichten, der standardmäßig alle Logger verarbeitet. Das heißt, wenn ich irgendwo in meinem Projekt ein neues Modul my_app_name.my_new_moduleerstelle und es mit etwas wie: gekennzeichnet ist , sollte ich in der Lage sein, dies zu tun und alle Protokolle zu den rotierenden Dateiprotokollen zu führen.

# 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.
quelle

Antworten:

153

Herausgefunden...

Sie setzen den 'catch all'-Logger, indem Sie ihn mit der leeren Zeichenfolge referenzieren : ''.

Im folgenden Setup werden beispielsweise alle Protokollereignisse gespeichert logs/mylog.log, mit Ausnahme der django.requestProtokollereignisse, in denen gespeichert wird logs/django_request.log. Weil 'propagate'eingestellt ist Falsefür meine django.requestLogger, wird das Protokoll Ereignis nie die ‚catch all‘ Logger erreichen.

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.
quelle
2
Chris, die Django-Dokumente dazu sind nicht verwirrend. Danke dafür.
5
Winzige Korrektur: Der Kommentar impliziert, dass die SQL-Protokollierung vom django.request-Logger beeinflusst wird. Um die SQL-Protokollierung umzuleiten, definieren Sie einen Protokollierer für 'django.db'. Der django.request-Logger verarbeitet 5xx- und 4xx-http-Antworten.
Rych
Dies hilft anderen Noobs wie mir: Der Logger erstellt die Protokolldateien, aber Sie müssen logs/zuerst den Ordner erstellen :-). Andernfalls wird beim Ausführen eine Fehlermeldung angezeigt ./manange.py runserver. @ Chris W. Vielen Dank für Ihre Beispiel-Protokollierungseinstellungen. Es hat mir sehr geholfen!
hobbes3
3
@arindamroychowdhury Mit der obigen Konfiguration, wenn Sie dies tun, logger = logging.getLogger('foo'); logger.warn('bar');dann wird der defaultHandler diese Protokollierung abfangen und so etwas <time> WARN: foo: barwird inlogs/mylog.log
Chris W.
8
Danke, es scheint, dass dies Root Logger bedeutet. Diese nützliche Information wurde in der Django-Dokumentation nicht gefunden.
Eino Mäkitalo
25

Wie Sie in Ihrer Antwort gesagt haben , Chris, besteht eine Option zum Definieren eines Standardloggers darin, die leere Zeichenfolge als Schlüssel zu verwenden.

Ich denke jedoch, dass der beabsichtigte Weg darin besteht, einen speziellen Logger unter dem rootSchlüssel des Logging-Konfigurationswörterbuchs zu definieren . Ich habe dies in der Python-Dokumentation gefunden :

root - Dies ist die Konfiguration für den Root-Logger. Die Verarbeitung der Konfiguration erfolgt wie bei jedem Logger, außer dass die propagateEinstellung nicht anwendbar ist.

Hier ist die Konfiguration aus Ihrer Antwort geändert, um den rootSchlüssel zu verwenden:

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

Um fair zu sein, kann ich keinen Unterschied im Verhalten zwischen den beiden Konfigurationen feststellen. Es scheint, dass das Definieren eines Loggers mit einem leeren Zeichenfolgenschlüssel den Root-Logger ändert, da logging.getLogger('')der Root-Logger zurückgegeben wird.

Der einzige Grund , warum ich es vorziehen , 'root'über ''ist , dass es zu dem Bearbeiten des Root - Logger explizit ist. Wenn Sie neugierig waren, 'root'überschreiben ''Sie , wenn Sie beide definieren, nur weil der Stammeintrag zuletzt verarbeitet wird.

Don Kirkby
quelle
Ja, das stimmt, entschuldige die Fehlkorrektur! Obwohl die Verwendung von '' anstelle von 'root' etwas logisch ist, finde ich es immer noch etwas inkonsistent, den rootEintrag in die Wurzel des Diktats zu verschieben, während der Übergang von der 2.6 fileConfig-Logik zur 2.7 dictConfig eins reibungslos verläuft.
Antony Hatchkins
2
import logging
logger = logging.getLogger(__name__)

nach dem Hinzufügen:

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

Wir können das Format ändern in:

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

oder

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

Ich habe ein kurzes Beispiel erstellt, um zu überprüfen, welche Konfiguration verwendet wird, wenn sowohl der rootSchlüssel als auch der leere ''Logger in config dict referenziert werden.

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

Druckt das folgende Ergebnis:

[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

Dies zeigt an, dass die Konfiguration unter rootSchlüssel die höchste Priorität hat. Wenn der Block entfernt wird, ist das Ergebnis:

[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

In beiden Fällen konnte ich debuggen und feststellen, dass alle drei Logger ( l1, l2und root) auf dieselbe Logger-Instanz, den Root-Logger, verwiesen haben.

Ich hoffe, das hilft anderen, die wie ich durch die zwei verschiedenen Möglichkeiten zur Konfiguration des Root-Loggers verwirrt waren.

Antwane
quelle