Ich bin oft frustriert über die Menge an Logging, die ich in meinen Code aufnehmen muss, und das führt mich dazu, mich zu fragen, ob es einen besseren Weg gibt, Dinge zu tun.
Ich weiß nicht, ob das gemacht wurde oder ob jemand eine bessere Idee hat, aber ich frage mich, ob es jemanden gibt, der einen Logger in eine Anwendung "injizieren" kann, so dass er den Thread passiv überwacht und protokolliert ruhig Prozesse, wie sie auftreten, ohne Dinge tun zu müssen:
%Vor%Was wäre toll, wenn ich meinem Logger sagen könnte:
%Vor%Es würde dann alles überwachen, was innerhalb dieser Methode passiert, einschließlich übergebener Argumente zusammen mit Methodenaufrufen und Werten, die an diese Methoden übergeben wurden, Ausnahmen, die auftreten usw.
Hat jemand in der Vergangenheit so etwas implementiert? Könnte es sogar sein implementiert werden? Ist das Einloggen nur so ein Traum?
Ich würde gerne etwas entwerfen, das das tun würde, aber ich weiß nicht einmal, wo ich anfangen würde. Natürlich will ich das Rad auch nicht neu erfinden, wenn es schon gemacht ist, wäre es toll, wenn mir jemand in die richtige Richtung zeigen könnte.
Irgendwelche Vorschläge würden dankbar empfangen ...
Bearbeiten: Ich dachte, ich würde eine Antwort geben, die nach dem Detaillierungsgrad des Protokolls fragt. Es ist häufig erforderlich, dass konfigurierbare Protokollierungsstufen bereitgestellt werden, so dass, wenn die Konfiguration eine detaillierte Protokollierung angibt, alles protokolliert wird, während, wenn eine kritische Protokollierung konfiguriert ist, nur bestimmte Informationen zusammen mit Ausnahmen protokolliert werden. Wenn die fatale Protokollierung konfiguriert ist, werden nur Informationen protokolliert, die zum Absturz der Anwendung führen. Wäre so etwas konfigurierbar oder würde AOP abhängig von der Anzahl der Protokollierungsstufen 3 oder 4 verschiedene Builds erfordern?
Ich verwende häufig vier Ebenen: Tödlich, Kritisch, Information, Detailliert
Sie können PostSharp verwenden, um sich über die Methode zu informieren. Das ist genau die Art von Dingen, bei denen AOP gut ist. Vielleicht möchten Sie mit Log4PostSharp beginnen - einem Plugin speziell für die Protokollierung.
Dies ist das klassische Beispiel der aspektorientierten Programmierung. Siehe PostSharp für eine sehr gute CLR-basierte Bibliothek.
Dies ist eines der Lehrbücher (nicht sicher, welches Lehrbuch AoP enthält, aber Sie bekommen die Idee) Beispiele für AoP - Protokollierung: wo Sie etwas vor und nach einer Methode kleben möchten.
Vielleicht möchten Sie die AoP-Route erkunden, PostSharp ist eine der beliebtesten, zusammen mit Microsoft Unity (auch IoC), Schloss.
Ein einfaches Beispiel für AoP ist, dass Sie Ihren Code vor und nach den Methoden hinzufügen, anstatt die Methodenaufrufe in die eigentlichen Methoden einzufügen. Da Sie die Frage mit C # getaggt haben, sollten Sie nur nach einer Erweiterungsmethode für die Protokollierung suchen, die bereits in diese Frage .
Ich würde einen praktischen Ansatz verfolgen: Wie viel loggen Sie eigentlich? Können Sie mit nur einer Erweiterungsmethode durchkommen, anstatt die Person, die Ihren Code liest, zu blenden. Die Protokollierung in das .NET-Framework ist bereits in Ordnung.
Zusätzlich zu den von Jon erwähnten Protokollierungsmethoden ist es wahrscheinlich auch erwähnenswert, dass es in VS eine nützliche Funktion zum Verfolgen des Programmflusses gibt. Dies ist die Möglichkeit, Breakpoints zu definieren, die einfach eine Nachricht ausgeben oder ein Makro ausführen hit (Beachten Sie, dass Sie auch variable Werte drucken können)
Klicken Sie mit der rechten Maustaste auf Ihren Haltepunkt und wählen Sie den Kontextmenüpunkt When Hit ...
Und natürlich ist eine weitere sehr nützliche Funktion das Trace-Objekt und die Trace-Liste in System.Diagnostics.
Ich habe kürzlich eine Protokollierungsbibliothek geschrieben, die die IDisposable-Schnittstelle zum Umbrechen von Regionen mit Protokollkontext verwendet. Grundsätzlich gibt es ein LogSite-Einwegobjekt, das Sie so verwenden:
%Vor%Das LogSite-Objekt verfügt über eine Reihe nützlicher Überladungen für den Konstruktor wie MethodBase, so dass Sie einfach MethodBase.GetCurrentMethod () verwenden und Reflektion verwenden können, um den tatsächlichen Namen der Methode und der Parameter zu erhalten (anstelle von fest codierten Strings). .
So funktioniert es: - Im Konstruktor schreibt es in das Protokoll mit allen Trace-Informationen, um anzuzeigen, dass es in den Block eingetreten ist. In der Dispose-Methode schreibt es einen Exit-Eintrag.
Beim Disposing überprüft es auch Marshal.GetExceptionCode () auf einen Wert ungleich Null, um festzustellen, ob der Code innerhalb der Verwendung eine Ausnahme ausgelöst oder normal beendet hat. Es gibt keine Ausnahme, daher muss dies explizit im catch-Handler protokolliert werden, aber es gibt "pass / fail" für diese Region an. Dadurch kann Ihr Protokollierungsumfang spezifischer als nur die Methode sein, da Sie viele dieser Blöcke in einer einzigen Methode verwenden können und wissen, welche die Ausnahme genau ausgelöst hat.
Da nun ein "Logger" -Objekt verfügbar ist, sieht Ihr Fang-Handler einfach so aus:
%Vor%Der Logger kennt bereits den Methodennamen, Parameterinformationen und all das und verfügt über interne Methoden zum Formatieren der Ausnahmeinformationen.
In der Architektur unter diesem High-Level-Objekt gibt es ein Konzept von "LogDisposition", das das "Pass / Fail" behandelt, das wir vorher bestimmt haben, und es gibt ein Konzept von "LogEntryType", das ein Filter ist (implementiert mit Flags enum ), die angibt, welche Art von Protokolleintrag übergeben wird (Fehler, Trace, usw.).
Die eigentliche Protokollierung ist nur ein Publisher / Listener-Muster. Der Publisher übernimmt den übergebenen Protokolleintrag und führt ähnlich wie ein Delegierter mit mehreren Ausdrücken eine Registrierung von LogListener-Instanzen (sollte am Anfang des Programms eingerichtet oder bei Bedarf dynamisch hinzugefügt werden) und übergibt den Protokolleintrag an diese Instanzen .
Die LogListener wiederum filtern heraus, um welche Art von Log-Einträgen es sich handelt. Wenn Sie also die Methodeneintritts- und -ausstiegspunkte für keine Fehlerbedingungen haben wollen, müssen sie nicht im Log erscheinen . Dies kann zur Laufzeit gesteuert werden, um dem Benutzer das Ein- und Ausschalten der detaillierten Protokollierung nach Belieben zu ermöglichen. Da der Publisher an verschiedene Loglistener schreiben kann, können Sie etwas anhängen, das in eine Datei schreibt oder in die Datenbank schreibt, oder Fehlermeldungen in der GUI anzeigt ... usw.
Es ist ein ziemlich gutes System und erfordert eine relativ kleine Menge an Code, um eine relativ reichhaltige Protokollierung zu erhalten.
Ich könnte Ihnen ein Codebeispiel geben, wenn Sie möchten ... Sie können mich über meinen (fast vollständig inaktiven) Blog kontaktieren (siehe mein Account-Profil).
Ich hoffe, das hilft.
Ich verwende die Open Source Apache log4net in allen meinen Projekten. Es ist eine sehr einfache Implementierung mit allen Arten von Erweiterungen, mit denen Sie in Datenbanken, ZIP-Dateien, Rolling Log-Dateien, RRS-Feeds, Telnet-Clients usw. loggen können. Logging ist im Prinzip so einfach wie:
%Vor%Logging-Parameter wie das Ausgabeformat und die Protokollierungsstufe, die ausgegeben werden sollen, werden alle in Echtzeit gelesen, während sich Ihre App in Runtime befindet.