Logging von mehreren Python-Services zu einem UDP-Server

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
top_dst
User
Beiträge: 3
Registriert: Dienstag 7. August 2007, 12:35

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.

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

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
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 :)
top_dst
User
Beiträge: 3
Registriert: Dienstag 7. August 2007, 12:35

Dienstag 7. August 2007, 16:11

Hallo,
ich habe vorläufig eine Möglichkeit gefunden.

Code: Alles auswählen

    logging.module_id = 10
    logging.root = TopModuleLogger('root')
    logging.manager = logging.Manager(logging.root)
Vieleicht nicht die schönste Lösung, aber bislang das einzige was mir dazu einfällt. :)
Antworten