Logging von mehreren Python-Services zu einem UDP-Server
Verfasst: Dienstag 7. August 2007, 13:32
Hallo,
ich müsste die Log-Meldungen die von verschiedenen Win32-Services via logging geschrieben werden an einen UDP-Server senden. Dazu habe ich an die entsprechenden Logger-Objekte in den Diensten einen LogHandler gebunden, der mir diese Meldungen an den Server schickt. Dabei habe ich diesen Handler soweit abgeändert, dass nicht das gepickelte Record-Objekt sondern ein klarer String ("LoggerName;LogMeldung") via UDP verschickt wird, da der UDP-Server das pickleing nicht unterstützt.
Was jetzt ein Problem darstellt ist, dass ich nicht weiß welche Meldung zu welchem Service gehört. Ich habe mir dann ein paar Gedanken gemacht und habe folgendes versucht:
Ich habe eine neue Logger-Klasse abgeleitet welche in der Methode makeRecord an das Record-Objekt ein Attribut "modul_id" anhängt, welches dann durch den abgeleiteten DatagramHandler an die zu versendende Meldung vorne anhängt ("modul_id;LoggerName;LogMeldung").
Mit logging.setLoggerClass habe ich dann diese neue Logger-Klasse als Standard für neue Logger-Objekte gesetzt. Das Problem was ich dann noch habe ist der Root-Logger. Der existiert nämlich schon bevor ich die neue Klasse als Standard setzen kann und hat somit nicht die Möglichkeit das Record-Objekt dementsprechend anzupassen...
Das bedeutet, ich kann auf Server-Seite nicht unterscheiden, ob die Meldungen des Root-Loggers vom einen oder vom anderen Service kommen.
Gibt es eine Möglichkeit den Klassentyp des Root-Loggers zu bestimmen?
Oder hat vieleicht jemand so was in der Art schon mal gemacht?
Die Modul-ID in den Namen des Log-Objekts zu packen scheidet aus, da ich in den Bibliotheken der Services einige wichtige Log-Einträge habe, welche die Modul-ID dann klarerweise nicht wissen können.
Das ganze sollte so gestaltet sein, dass der Rest per logging.info("Meldung") funktioniert.
Schon mal vielen Dank im Voraus
ich müsste die Log-Meldungen die von verschiedenen Win32-Services via logging geschrieben werden an einen UDP-Server senden. Dazu habe ich an die entsprechenden Logger-Objekte in den Diensten einen LogHandler gebunden, der mir diese Meldungen an den Server schickt. Dabei habe ich diesen Handler soweit abgeändert, dass nicht das gepickelte Record-Objekt sondern ein klarer String ("LoggerName;LogMeldung") via UDP verschickt wird, da der UDP-Server das pickleing nicht unterstützt.
Code: Alles auswählen
class TopFlatDatagramHandler(logging.handlers.DatagramHandler):
"""
Abänderung des DatagramHandlers um statt dem Record-Objekt einen klaren String
zu versenden.
"""
def makePickle(self, record):
"""
Formatiert den Log-Text so, dass der LoggerName gefolgt von ';' und dem Text
über UDP versendet wird. Besitzt das Logger-Objekt ein Attribut "module_id",
wird dieses am String vorne angestellt und mit ';' vom Rest getrennt:
10;MeinLogger;LogText
"""
if record.__dict__.has_key('module_id'):
s = str(record.module_id)+';'+record.name +';'+ self.format(record)
else:
s = record.name +';'+ self.format(record)
return s
Ich habe eine neue Logger-Klasse abgeleitet welche in der Methode makeRecord an das Record-Objekt ein Attribut "modul_id" anhängt, welches dann durch den abgeleiteten DatagramHandler an die zu versendende Meldung vorne anhängt ("modul_id;LoggerName;LogMeldung").
Code: Alles auswählen
class TopModuleLogger(logging.Logger):
"""
Abänderung der Logger Klasse um im LogRecord ein weiteres Attribut "module_id" hinzuzufügen.
"""
def __init__(self, name, level=NOTSET):
logging.Logger.__init__(self, name, level)
if logging.__dict__.has_key('module_id'):
self.module_id = logging.module_id
def makeRecord(self, name, lvl, fn, lno, msg, args, exc_info, func, extra):
rv = logging.Logger.makeRecord(self, name, lvl, fn, lno, msg, args, exc_info, func, extra)
if self.__dict__.has_key('module_id'):
rv.module_id = self.module_id
return rv
Das bedeutet, ich kann auf Server-Seite nicht unterscheiden, ob die Meldungen des Root-Loggers vom einen oder vom anderen Service kommen.
Gibt es eine Möglichkeit den Klassentyp des Root-Loggers zu bestimmen?
Oder hat vieleicht jemand so was in der Art schon mal gemacht?
Die Modul-ID in den Namen des Log-Objekts zu packen scheidet aus, da ich in den Bibliotheken der Services einige wichtige Log-Einträge habe, welche die Modul-ID dann klarerweise nicht wissen können.
Das ganze sollte so gestaltet sein, dass der Rest per logging.info("Meldung") funktioniert.
Schon mal vielen Dank im Voraus
