Hier ist ein einfacher Python-Filter, der nur "TEST -" vor eine Protokollnachricht stellt. (Der eigentliche Filter wird nicht hilfreiche Verarbeitung später):Warum wird mein Protokollierungsfilter auf den falschen Handler angewendet?
class TimeStamp_Filter(logging.Filter):
def filter(self, record):
record.msg = "TEST - " + str(record.msg)
return True
Und hier ist die config in einer JSON-Datei und analysierte mit dictConfig()
gezogen:
{
"version": 1,
"disable_existing_loggers": false,
"filters": {
"timestamp_filter": {
"()": "TimeStamp_Filter"
}
},
"handlers": {
"file_handler": {
"class": "logging.FileHandler",
"level": "INFO",
"filename": "../log/default.log",
"mode": "a"
},
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"filters": ["timestamp_filter"],
"stream": "ext://sys.stdout"
}
},
"root": {
"level": "DEBUG",
"handlers": ["console", "file_handler"]
}
}
Der Filter selbst scheint zu funktionieren - wenn Ich erstelle einen Logger und logger.info("Hello, world!")
laufen, bekomme ich die Ausgabe TEST - Hello, world!
auf dem Bildschirm.
Aber ich auch bekomme diese Ausgabe (einschließlich der "TEST") in meiner default.log
Datei. Ich hatte gedacht, dass, indem ich die timestamp_filter
nur an die console
Handler anbrachte, würde ich diese TEST-Ausgabe nur auf dem Bildschirm bekommen.
Warum wird auch an den Handler file_handler
gesendet und endet in meiner Protokolldatei?
Masnum, danke für die Erklärung. Ich habe meine Idee auf dem Python Cookbook (https://docs.python.org/3/howto/logging-cookbook.html#using-filters-to-impart-contextual-information) basiert, wo sie vorschlagen, einen Filter zu verwenden, um zu injizieren zusätzliche Informationen in die Nachricht, wie IP-Daten. In meinem Fall erfordern die Daten, die injiziert werden müssen, eine gewisse Geschäftslogik. Ist es möglich, Python-Code zu einem Formatierer hinzuzufügen? Die einzigen Beispiele, die ich gesehen habe, beinhalten das Ändern der Ausgabezeichenfolge unter Verwendung vordefinierter Variablen wie '% (asctime) s''% (processName) ', usw. - nichts, was einen Block von Code betrifft. –
Ja, Sie können die Geschäftslogik auch in Formatierer einfügen. Aber denken Sie daran, das Hauptdatensatzobjekt nicht zu ändern. Das würde ähnliche Probleme verursachen. – masnun
Masnun, nochmals vielen Dank für Ihre Hilfe. Könnten Sie mir ein Beispiel dafür geben, wie diese Geschäftslogik in einen Formatierer einfließen kann? Ich weiß, wie man es mit einem Formatierungsstring mit vordefinierten Variablen setzt (zB 'formatter = logging.Formatter ('TEST -% (asctime) s -% (name) s -% (levelname) s -% (message) s') ') Aber ich gestehe, dass ich nicht verstehe, wie man den ganzen Formatierer in eine Funktion oder Klasse bringt, um komplexere Logik anzuwenden. (um nur ein Beispiel zu geben, das Wort "TEST" nur zu drucken, wenn der "socket.hostname()" einen bestimmten Wert hat). –