Best Practices für die Protokollierung [geschlossen]

323

Ich möchte Geschichten darüber erhalten, wie Benutzer mit der Verfolgung und Anmeldung in realen Anwendungen umgehen. Hier sind einige Fragen, die Ihnen helfen könnten, Ihre Antwort zu erklären.

Frameworks

Welche Frameworks verwenden Sie?

  • log4net
  • System.Diagnostics.Trace
  • System.Diagnostics.TraceSource
  • Anwendungsblock protokollieren
  • Andere?

Wenn Sie die Ablaufverfolgung verwenden, verwenden Sie Trace.Correlation.StartLogicalOperation?

Schreiben Sie diesen Code manuell oder verwenden Sie dazu eine aspektorientierte Programmierung? Möchten Sie ein Code-Snippet freigeben?

Bieten Sie eine Form der Granularität für Trace-Quellen an? Mit WPF TraceSources können Sie sie beispielsweise auf verschiedenen Ebenen konfigurieren:

  • System.Windows - Einstellungen für alle WPF
  • System.Windows.Animation - speziell für Animation überschreiben.

Zuhörer

Welche Protokollausgaben verwenden Sie?

  • Textdateien
  • XML-Dateien
  • Ereignisprotokoll
  • Andere?

Verwenden Sie bei der Verwendung von Dateien fortlaufende Protokolle oder nur eine einzelne Datei? Wie stellen Sie die Protokolle für Benutzer zur Verfügung?

Anzeigen

Welche Tools verwenden Sie zum Anzeigen der Protokolle?

  • Notizblock
  • Schwanz
  • Ereignisanzeige
  • Systems Center Operations Manager / Microsoft Operations Manager
  • WCF Service Trace Viewer
  • Andere?

Verwenden Sie beim Erstellen einer ASP.NET-Lösung auch ASP.NET Health Monitoring? Nehmen Sie die Trace-Ausgabe in die Health Monitor-Ereignisse auf? Was ist mit Trace.axd?

Was ist mit benutzerdefinierten Leistungsindikatoren?

Paul Stovell
quelle
3
Es wäre hilfreich, wenn Leute, die Fragen wie diese mit 300 Upvotes schließen, entweder ein Wiki-Format vorschlagen oder auf programmers.stackexchange posten könnten, oder Quora, wenn diese Art von Frage nicht erwünscht ist. Offensichtlich ist die Frage tatsächlich sehr konstruktiv, sie entspricht einfach nicht den Kriterien, die StackOverflow wünscht. programmers.stackexchange.com/questions/57064/… hat 24 Upvotes. Vielleicht fehlt StackOverflow etwas?
Niall Connaughton
Wenn diese Frage das Q & A-Format verletzt, ist etwas falsch mit dem Q & A-Format und nicht mit dieser Frage. Manchmal hängt die Entscheidung, ob eine Frage geschlossen werden soll, von den Antworten ab. Einige offene Fragen laden zur Debatte ein, andere laden Benutzer ein, wertvolle Inhalte wie diesen bereitzustellen!
Matthias Wolf
1
Diese Frage - insbesondere die Top-Antwort - wäre wahrscheinlich eine hervorragende Grundlage für einen Blog-Beitrag, wenn jemand sie als solche verwenden möchte ... Als objektive Frage passt sie nicht wirklich - sie ist explizit als Strohumfrage strukturiert - aber Es gibt einige gute Informationen unten, daher das Schloss.
Shog9

Antworten:

232

Update: Erweiterungen zu System.Diagnostics mit einigen der fehlenden Listener, die Sie möglicherweise benötigen, finden Sie unter Essential.Diagnostics auf CodePlex ( http://essentialdiagnostics.codeplex.com/ ).


Frameworks

F: Welche Frameworks verwenden Sie?

A: System.Diagnostics.TraceSource, integriert in .NET 2.0.

Es bietet leistungsstarke, flexible und leistungsstarke Protokollierung für Anwendungen. Viele Entwickler sind sich jedoch seiner Funktionen nicht bewusst und nutzen sie nicht vollständig.

Es gibt einige Bereiche, in denen zusätzliche Funktionen nützlich sind oder manchmal vorhanden sind, die jedoch nicht gut dokumentiert sind. Dies bedeutet jedoch nicht, dass das gesamte Protokollierungsframework (das erweiterbar ausgelegt ist) weggeworfen und wie einige gängige Alternativen vollständig ersetzt werden sollte (NLog, log4net, Common.Logging und sogar EntLib Logging).

Anstatt die Art und Weise zu ändern, in der Sie Ihrer Anwendung Protokollierungsanweisungen hinzufügen und das Rad neu erfinden, haben Sie das System.Diagnostics-Framework nur an den wenigen Stellen erweitert, an denen Sie es benötigen.

Mir scheint, die anderen Frameworks, sogar EntLib, leiden einfach unter dem Not Invented Here-Syndrom, und ich denke, sie haben Zeit damit verschwendet, die Grundlagen neu zu erfinden, die in System.Diagnostics bereits einwandfrei funktionieren (z. B. wie Sie Protokollanweisungen schreiben). anstatt die wenigen vorhandenen Lücken zu füllen. Kurz gesagt, verwenden Sie sie nicht - sie werden nicht benötigt.

Funktionen, die Sie möglicherweise nicht kennen:

  • Die Verwendung von TraceEvent-Überladungen, die eine Formatzeichenfolge und Argumente annehmen, kann die Leistung verbessern, da Parameter als separate Referenzen beibehalten werden, bis Filter.ShouldTrace () erfolgreich war. Dies bedeutet, dass keine teuren Aufrufe von ToString () für Parameterwerte erfolgen, bis die vom System bestätigte Nachricht tatsächlich protokolliert wird.
  • Mit dem Trace.CorrelationManager können Sie Protokollanweisungen zu derselben logischen Operation korrelieren (siehe unten).
  • VisualBasic.Logging.FileLogTraceListener eignet sich zum Schreiben in Protokolldateien und unterstützt die Dateirotation. Obwohl im VisualBasic-Namespace, kann es in einem C # -Projekt (oder einem anderen Sprachprojekt) genauso einfach verwendet werden, indem einfach die DLL eingeschlossen wird.
  • Wenn Sie EventLogTraceListener verwenden und TraceEvent mit mehreren Argumenten und einer leeren Zeichenfolge oder einer Zeichenfolge im Nullformat aufrufen, werden die Argumente direkt an EventLog.WriteEntry () übergeben, wenn Sie lokalisierte Nachrichtenressourcen verwenden.
  • Das Service Trace Viewer-Tool (von WCF) ist nützlich, um Diagramme von aktivitätskorrelierten Protokolldateien anzuzeigen (auch wenn Sie WCF nicht verwenden). Dies kann wirklich dazu beitragen, komplexe Probleme zu beheben, bei denen mehrere Threads / Aktivitäten beteiligt sind.
  • Vermeiden Sie Overhead, indem Sie alle Listener löschen (oder Default entfernen). Andernfalls übergibt Default alles an das Trace-System (und verursacht all diese ToString () - Overheads).

Bereiche, die Sie möglicherweise erweitern möchten (falls erforderlich):

  • Datenbank-Trace-Listener
  • Farbiger Konsolen-Trace-Listener
  • MSMQ / Email / WMI-Trace-Listener (falls erforderlich)
  • Implementieren Sie einen FileSystemWatcher, um Trace.Refresh für dynamische Konfigurationsänderungen aufzurufen

Sonstige Empfehlungen:

Verwenden Sie strukturierte Ereignis-IDs und führen Sie eine Referenzliste (z. B. dokumentieren Sie sie in einer Aufzählung).

Das Vorhandensein eindeutiger Ereignis-IDs für jedes (signifikante) Ereignis in Ihrem System ist sehr nützlich, um bestimmte Probleme zu korrelieren und zu finden. Es ist einfach, zu dem spezifischen Code zurückzukehren, der die Ereignis-IDs protokolliert / verwendet, und es kann einfach sein, Anleitungen für häufig auftretende Fehler bereitzustellen, z. B. Fehler 5178 bedeutet, dass Ihre Datenbankverbindungszeichenfolge falsch ist usw.

Ereignis-IDs sollten einer bestimmten Struktur folgen (ähnlich der in E-Mail und HTTP verwendeten Theorie der Antwortcodes), mit der Sie sie nach Kategorien behandeln können, ohne bestimmte Codes zu kennen.

Beispiel: Die erste Ziffer kann die allgemeine Klasse detaillieren: 1xxx kann für 'Start'-Operationen verwendet werden, 2xxx für normales Verhalten, 3xxx für Aktivitätsverfolgung, 4xxx für Warnungen, 5xxx für Fehler, 8xxx für' Stop'-Operationen, 9xxx für schwerwiegende Fehler, usw.

Die zweite Ziffer kann den Bereich detaillieren, z. B. 21xx für Datenbankinformationen (41xx für Datenbankwarnungen, 51xx für Datenbankfehler), 22xx für den Berechnungsmodus (42xx für Berechnungswarnungen usw.), 23xx für ein anderes Modul usw.

Mit zugewiesenen, strukturierten Ereignis-IDs können Sie diese auch in Filtern verwenden.

F: Wenn Sie die Ablaufverfolgung verwenden, verwenden Sie Trace.Correlation.StartLogicalOperation?

A: Trace.CorrelationManager ist sehr nützlich, um Protokollanweisungen in jeder Art von Multithread-Umgebung zu korrelieren (was heutzutage so ziemlich alles ist).

Sie müssen die ActivityId mindestens einmal für jede logische Operation festlegen, um eine Korrelation herzustellen.

Start / Stop und der LogicalOperationStack können dann für einen einfachen stapelbasierten Kontext verwendet werden. Bei komplexeren Kontexten (z. B. asynchronen Operationen) ermöglicht die Verwendung von TraceTransfer für die neue ActivityId (vor dem Ändern) die Korrelation.

Das Service Trace Viewer-Tool kann zum Anzeigen von Aktivitätsdiagrammen hilfreich sein (auch wenn Sie WCF nicht verwenden).

F: Schreiben Sie diesen Code manuell oder verwenden Sie dazu eine aspektorientierte Programmierung? Möchten Sie ein Code-Snippet freigeben?

A: Möglicherweise möchten Sie eine Bereichsklasse erstellen, z. B. LogicalOperationScope, die (a) den Kontext beim Erstellen einrichtet und (b) den Kontext beim Entsorgen zurücksetzt.

Auf diese Weise können Sie Code wie den folgenden schreiben, um Vorgänge automatisch zu verpacken:

  using( LogicalOperationScope operation = new LogicalOperationScope("Operation") )
  {
    // .. do work here
  }

Bei der Erstellung konnte der Bereich bei Bedarf zuerst ActivityId festlegen, StartLogicalOperation aufrufen und dann eine TraceEventType.Start-Nachricht protokollieren. Bei Entsorgen kann eine Stoppnachricht protokolliert und anschließend StopLogicalOperation aufgerufen werden.

F: Bieten Sie eine Form der Granularität für Trace-Quellen an? Mit WPF TraceSources können Sie sie beispielsweise auf verschiedenen Ebenen konfigurieren.

A: Ja, mehrere Trace-Quellen sind nützlich / wichtig, wenn die Systeme größer werden.

Während Sie wahrscheinlich alle Warnungen und höher oder alle Informationen und Nachrichten konsistent protokollieren möchten, wird für jedes System mit angemessener Größe das Volumen der Aktivitätsverfolgung (Start, Stopp usw.) und der ausführlichen Protokollierung einfach zu groß.

Anstatt nur einen Schalter zu haben, der alles ein- oder ausschaltet, ist es hilfreich, diese Informationen jeweils für einen Abschnitt Ihres Systems aktivieren zu können.

Auf diese Weise können Sie signifikante Probleme anhand der normalerweise protokollierten Protokollierung (alle Warnungen, Fehler usw.) lokalisieren und dann die gewünschten Abschnitte "vergrößern" und auf Aktivitätsverfolgung oder sogar Debug-Ebenen einstellen.

Die Anzahl der benötigten Ablaufverfolgungsquellen hängt von Ihrer Anwendung ab, z. B. möchten Sie möglicherweise eine Ablaufverfolgungsquelle pro Assembly oder pro Hauptabschnitt Ihrer Anwendung.

Wenn Sie eine noch feinere Steuerung benötigen, fügen Sie einzelne boolesche Schalter hinzu, um die spezifische Ablaufverfolgung mit hohem Volumen ein- und auszuschalten, z. B. Rohnachrichten-Dumps. (Oder es könnte eine separate Trace-Quelle verwendet werden, ähnlich wie bei WCF / WPF).

Möglicherweise möchten Sie auch separate Ablaufverfolgungsquellen für die Aktivitätsverfolgung im Vergleich zur allgemeinen (anderen) Protokollierung in Betracht ziehen, da dies die Konfiguration von Filtern genau nach Ihren Wünschen erleichtert.

Beachten Sie, dass Nachrichten auch dann über ActivityId korreliert werden können, wenn verschiedene Quellen verwendet werden. Verwenden Sie daher so viele, wie Sie benötigen.


Zuhörer

F: Welche Protokollausgaben verwenden Sie?

Dies kann davon abhängen, welche Art von Anwendung Sie schreiben und welche Dinge protokolliert werden. Normalerweise gehen verschiedene Dinge an verschiedenen Orten (dh mehrere Ausgänge).

Ich klassifiziere Outputs im Allgemeinen in drei Gruppen:

(1) Ereignisse - Windows-Ereignisprotokoll (und Ablaufverfolgungsdateien)

Wenn Sie beispielsweise einen Server / Dienst schreiben, empfiehlt es sich unter Windows, das Windows-Ereignisprotokoll zu verwenden (Sie haben keine Benutzeroberfläche, an die Sie Bericht erstatten können).

In diesem Fall sollten alle Ereignisse mit schwerwiegenden, Fehler-, Warn- und (Service-Level-) Informationen in das Windows-Ereignisprotokoll aufgenommen werden. Die Informationsebene sollte für diese Art von Ereignissen auf hoher Ebene reserviert sein, die Sie in das Ereignisprotokoll aufnehmen möchten, z. B. "Dienst gestartet", "Dienst gestoppt", "Mit Xyz verbunden" und möglicherweise sogar "Zeitplan initiiert". , "Benutzer angemeldet" usw.

In einigen Fällen möchten Sie möglicherweise das Schreiben in das Ereignisprotokoll zu einem integrierten Bestandteil Ihrer Anwendung machen und nicht über das Trace-System (dh das Schreiben von Ereignisprotokolleinträgen direkt). Dies bedeutet, dass es nicht versehentlich ausgeschaltet werden kann. (Beachten Sie, dass Sie immer noch dasselbe Ereignis in Ihrem Trace-System notieren möchten, damit Sie korrelieren können.)

Im Gegensatz dazu meldet eine Windows-GUI-Anwendung diese im Allgemeinen dem Benutzer (obwohl sie möglicherweise auch im Windows-Ereignisprotokoll protokolliert werden).

Ereignisse können auch verwandte Leistungsindikatoren haben (z. B. Anzahl der Fehler / Sek.), Und es kann wichtig sein, das direkte Schreiben in das Ereignisprotokoll, die Leistungsindikatoren, das Schreiben in das Ablaufverfolgungssystem und das Melden an den Benutzer so zu koordinieren, dass sie auftreten die selbe Zeit.

Wenn ein Benutzer zu einem bestimmten Zeitpunkt eine Fehlermeldung sieht, sollte es möglich sein, dieselbe Fehlermeldung im Windows-Ereignisprotokoll und dann dasselbe Ereignis mit demselben Zeitstempel im Ablaufverfolgungsprotokoll (zusammen mit anderen Ablaufverfolgungsdetails) zu finden.

(2) Aktivitäten - Anwendungsprotokolldateien oder Datenbanktabelle (und Trace-Dateien)

Dies ist die reguläre Aktivität, die ein System ausführt, z. B. Webseite, Börsenhandel, Bestellung, Berechnung usw.

Die Aktivitätsverfolgung (Start, Stopp usw.) ist hier nützlich (in der richtigen Granualität).

Außerdem wird häufig ein bestimmtes Anwendungsprotokoll verwendet (manchmal auch als Überwachungsprotokoll bezeichnet). Normalerweise ist dies eine Datenbanktabelle oder eine Anwendungsprotokolldatei und enthält strukturierte Daten (dh eine Reihe von Feldern).

Abhängig von Ihrer Anwendung kann es hier zu Unschärfen kommen. Ein gutes Beispiel könnte ein Webserver sein, der jede Anforderung in ein Webprotokoll schreibt. Ähnliche Beispiele können ein Nachrichtensystem oder ein Berechnungssystem sein, bei dem jeder Vorgang zusammen mit anwendungsspezifischen Details protokolliert wird.

Ein nicht so gutes Beispiel sind Börsengeschäfte oder ein Kundenbestellsystem. In diesen Systemen protokollieren Sie die Aktivität wahrscheinlich bereits, da sie einen wichtigen Geschäftswert haben. Das Prinzip der Korrelation mit anderen Aktionen ist jedoch weiterhin wichtig.

Neben benutzerdefinierten Anwendungsprotokollen haben Aktivitäten häufig auch zugehörige Leistungsindikatoren, z. B. die Anzahl der Transaktionen pro Sekunde.

Im Allgemeinen sollten Sie die Protokollierung von Aktivitäten über verschiedene Systeme hinweg koordinieren, dh gleichzeitig mit dem Erhöhen des Leistungsindikators und dem Protokollieren in Ihrem Trace-System in Ihr Anwendungsprotokoll schreiben. Wenn Sie alle gleichzeitig (oder direkt nacheinander im Code) ausführen, ist das Debuggen von Problemen einfacher (als wenn sie alle zu unterschiedlichen Zeiten / Orten im Code auftreten).

(3) Debug Trace - Textdatei oder möglicherweise XML oder Datenbank.

Dies sind Informationen auf ausführlicher Ebene und niedriger (z. B. benutzerdefinierte boolesche Schalter zum Ein- und Ausschalten von Rohdaten-Dumps). Dies liefert den Mut oder die Details dessen, was ein System auf Unteraktivitätsebene tut.

Dies ist die Ebene, die Sie für einzelne Abschnitte Ihrer Anwendung (daher die mehreren Quellen) ein- und ausschalten möchten. Sie möchten nicht, dass dieses Zeug das Windows-Ereignisprotokoll überfüllt. Manchmal wird eine Datenbank verwendet, aber wahrscheinlicher sind fortlaufende Protokolldateien, die nach einer bestimmten Zeit gelöscht werden.

Ein großer Unterschied zwischen diesen Informationen und einer Anwendungsprotokolldatei besteht darin, dass sie unstrukturiert sind. Während ein Anwendungsprotokoll Felder für An, Von, Betrag usw. enthalten kann, können ausführliche Debug-Traces das sein, was ein Programmierer eingibt, z. B. "Überprüfen der Werte X = {Wert}, Y = Falsch" oder zufällige Kommentare / Markierungen wie " Fertig, erneut versuchen ".

Eine wichtige Vorgehensweise besteht darin, sicherzustellen, dass Dinge, die Sie in Anwendungsprotokolldateien oder im Windows-Ereignisprotokoll ablegen, auch mit denselben Details (z. B. Zeitstempel) im Trace-System protokolliert werden. Auf diese Weise können Sie die verschiedenen Protokolle bei der Untersuchung korrelieren.

Wenn Sie planen, einen bestimmten Protokoll-Viewer zu verwenden, weil Sie eine komplexe Korrelation haben, z. B. den Service Trace Viewer, müssen Sie ein geeignetes Format verwenden, z. B. XML. Andernfalls ist eine einfache Textdatei normalerweise gut genug - auf den unteren Ebenen sind die Informationen weitgehend unstrukturiert, sodass Sie möglicherweise Speicherauszüge von Arrays, Stapelspeicherauszügen usw. finden. Vorausgesetzt, Sie können auf höheren Ebenen mit strukturierteren Protokollen korrelieren, sollten die Dinge dies tun in Ordnung sein.

F: Wenn Sie Dateien verwenden, verwenden Sie fortlaufende Protokolle oder nur eine einzelne Datei? Wie stellen Sie die Protokolle für Benutzer zur Verfügung?

A: Für Dateien möchten Sie im Allgemeinen rollierende Protokolldateien unter dem Gesichtspunkt der Verwaltbarkeit (mit System.Diagnostics verwenden Sie einfach VisualBasic.Logging.FileLogTraceListener).

Die Verfügbarkeit hängt wiederum vom System ab. Wenn Sie nur über Dateien sprechen, können Sie für einen Server / Dienst nur bei Bedarf auf fortlaufende Dateien zugreifen. (Windows-Ereignisprotokoll- oder Datenbankanwendungsprotokolle verfügen über eigene Zugriffsmechanismen.)

Wenn Sie keinen einfachen Zugriff auf das Dateisystem haben, ist die Debug-Ablaufverfolgung zu einer Datenbank möglicherweise einfacher. [dh eine Datenbank TraceListener implementieren].

Eine interessante Lösung, die ich für eine Windows-GUI-Anwendung gesehen habe, war, dass sie während der Ausführung sehr detaillierte Ablaufverfolgungsinformationen auf einem "Flugschreiber" protokollierte. Wenn Sie sie dann herunterfahren, wenn sie keine Probleme hatte, wurde die Datei einfach gelöscht.

Wenn es jedoch abstürzte oder auf ein Problem stieß, wurde die Datei nicht gelöscht. Entweder wenn es den Fehler abfängt, oder wenn es das nächste Mal ausgeführt wird, bemerkt es die Datei und kann dann Maßnahmen ergreifen, z. B. komprimieren (z. B. 7zip) und per E-Mail senden oder auf andere Weise verfügbar machen.

Viele Systeme enthalten heutzutage eine automatisierte Meldung von Fehlern an einen zentralen Server (nach Rücksprache mit Benutzern, z. B. aus Datenschutzgründen).


Anzeigen

F: Welche Tools verwenden Sie zum Anzeigen der Protokolle?

A: Wenn Sie aus verschiedenen Gründen mehrere Protokolle haben, verwenden Sie mehrere Viewer.

Notepad / vi / Notepad ++ oder ein anderer Texteditor ist die Basis für Nur-Text-Protokolle.

Wenn Sie komplexe Vorgänge haben, z. B. Aktivitäten mit Übertragungen, würden Sie natürlich ein spezielles Tool wie den Service Trace Viewer verwenden. (Aber wenn Sie es nicht brauchen, ist ein Texteditor einfacher).

Da ich im Allgemeinen allgemeine Informationen im Windows-Ereignisprotokoll protokolliere, bietet es eine schnelle Möglichkeit, sich strukturiert einen Überblick zu verschaffen (achten Sie auf die hübschen Fehler- / Warnsymbole). Sie müssen nur dann mit dem Durchsuchen von Textdateien beginnen, wenn das Protokoll nicht genügend enthält, obwohl das Protokoll Ihnen zumindest einen Ausgangspunkt bietet. (An diesem Punkt ist es hilfreich, sicherzustellen, dass Ihre Protokolle die gesamten Daten koordiniert haben.)

Im Allgemeinen stellt das Windows-Ereignisprotokoll diese wichtigen Ereignisse auch Überwachungstools wie MOM oder OpenView zur Verfügung.

Andere --

Wenn Sie sich bei einer Datenbank anmelden, kann es einfach sein, Informationen zu filtern und zu sortieren (z. B. eine bestimmte Aktivitäts-ID zu vergrößern. (Bei Textdateien können Sie Grep / PowerShell oder ähnliches verwenden, um nach der gewünschten GUID zu filtern.)

MS Excel (oder ein anderes Tabellenkalkulationsprogramm). Dies kann nützlich sein, um strukturierte oder halbstrukturierte Informationen zu analysieren, wenn Sie sie mit den richtigen Trennzeichen importieren können, sodass unterschiedliche Werte in unterschiedlichen Spalten angezeigt werden.

Wenn ich einen Dienst in Debug / Test ausführe, hoste ich ihn normalerweise der Einfachheit halber in einer Konsolenanwendung. Ich finde einen farbigen Konsolenlogger nützlich (z. B. rot für Fehler, gelb für Warnungen usw.). Sie müssen einen benutzerdefinierten Trace-Listener implementieren.

Beachten Sie, dass das Framework keinen farbigen Konsolenlogger oder Datenbanklogger enthält. Daher müssen Sie diese derzeit schreiben, wenn Sie sie benötigen (es ist nicht zu schwierig).

Es ärgert mich wirklich, dass mehrere Frameworks (log4net, EntLib usw.) Zeit damit verschwendet haben, das Rad neu zu erfinden und die grundlegende Protokollierung, Filterung und Protokollierung in Textdateien, dem Windows-Ereignisprotokoll und XML-Dateien jeweils für sich neu zu implementieren unterschiedliche Art und Weise (Protokollanweisungen sind jeweils unterschiedlich); Jeder hat dann seine eigene Version von beispielsweise einem Datenbanklogger implementiert, wenn das meiste davon bereits vorhanden war und nur ein paar weitere Trace-Listener für System.Diagnostics benötigt wurden. Sprechen Sie über eine große Verschwendung von Doppelarbeit.

F: Wenn Sie eine ASP.NET-Lösung erstellen, verwenden Sie auch ASP.NET Health Monitoring? Nehmen Sie die Trace-Ausgabe in die Health Monitor-Ereignisse auf? Was ist mit Trace.axd?

Diese Dinge können nach Bedarf ein- und ausgeschaltet werden. Ich finde Trace.axd sehr nützlich, um zu debuggen, wie ein Server auf bestimmte Dinge reagiert, aber es ist im Allgemeinen in einer stark genutzten Umgebung oder für die Langzeitverfolgung nicht nützlich.

F: Was ist mit benutzerdefinierten Leistungsindikatoren?

Für eine professionelle Anwendung, insbesondere einen Server / Dienst, erwarte ich, dass sie sowohl mit Leistungsindikatoren als auch mit Protokollierung im Windows-Ereignisprotokoll vollständig instrumentiert ist. Dies sind die Standardwerkzeuge in Windows und sollten verwendet werden.

Sie müssen sicherstellen, dass Sie Installationsprogramme für die von Ihnen verwendeten Leistungsindikatoren und Ereignisprotokolle einschließen. Diese sollten zur Installationszeit erstellt werden (bei der Installation als Administrator). Wenn Ihre Anwendung normal ausgeführt wird, sollte sie keine Administratorrechte benötigen (und daher keine fehlenden Protokolle erstellen können).

Dies ist ein guter Grund, die Entwicklung als Nicht-Administrator zu üben (haben Sie ein separates Administratorkonto, wenn Sie Dienste usw. installieren müssen). Wenn Sie in das Ereignisprotokoll schreiben, erstellt .NET beim ersten Schreiben automatisch ein fehlendes Protokoll. Wenn Sie sich als Nicht-Administrator entwickeln, werden Sie dies frühzeitig erkennen und eine böse Überraschung vermeiden, wenn ein Kunde Ihr System installiert und es dann nicht verwenden kann, weil er nicht als Administrator ausgeführt wird.

Schlauer Greif
quelle
Zu Ihrer Information: Ich bin auf ein Problem gestoßen, bei dem die Microsoft-Ablaufverfolgung einer Datei abstürzt. Wenn mehrere Prozesse (oder Threads) in dieselbe Datei schreiben und diese kollidieren, wird ein Fehler beim Sperren des exklusiven Zugriffs auf das Dateisystem für die Protokolldatei angezeigt.
Jay
1
Die System.Diagnostics-Infrastruktur ist threadsicher. Das Standardverhalten ist das Sperren des Frameworks. Sie können jedoch TraceListener.IsThreadSafe überschreiben, wenn Sie Ihre eigene Sperre bereitstellen. Siehe msdn.microsoft.com/en-us/library/… . Bei mehreren Prozessen schreiben Sie normalerweise in separate Dateien. Beachten Sie jedoch, dass der Service Trace Viewer mehrere Trace-Dateien (z. B. von mehreren Computern) laden und über ActivityId korrelieren kann.
Sly Gryphon
1
Vielleicht können Sie vorschlagen, wie Sie mit TraceEvent () Ausnahmen protokollieren?
Dmitriy Sosunov
1
Ist das nicht einer der Hauptnachteile System.Diagnostics.Trace, mit [Conditional("TRACE")]denen es dekoriert ist , was es in Produktionsumgebungen unbrauchbar macht, in denen Sie selten Code mit der TRACEFlagge kompiliert haben ?
Asbjørn Ulsberg
2
@asbjornu In der Standardkonfiguration für Release-Builds in Visual Studio ist TRACE definiert (DEBUG ist für Release-Builds deaktiviert). Wenn Sie über die Befehlszeile erstellen, müssen Sie diese jedoch aktivieren.
Sly Gryphon
40

Ich muss mich dem Chor anschließen, der log4net empfiehlt, in meinem Fall aus Sicht der Plattformflexibilität (Desktop .Net / Compact Framework, 32/64-Bit).

Das Einschließen in eine Private-Label-API ist jedoch ein wichtiges Anti-Pattern . log4net.ILoggerist das .Net-Gegenstück zur Commons-Protokollierung Wrapper- API , sodass die Kopplung für Sie bereits minimiert ist. Da es sich auch um eine Apache-Bibliothek handelt, ist dies normalerweise nicht einmal ein Problem, da Sie keine Kontrolle aufgeben: Verzweigen Sie sie, wenn Sie dies tun Muss.

Die meisten House-Wrapper-Bibliotheken, die ich gesehen habe, haben auch eine oder mehrere Litanei von Fehlern begangen:

  1. Verwendung eines globalen Singleton-Loggers (oder gleichwertig eines statischen Einstiegspunkts), der die feine Auflösung des empfohlenen Logger-pro-Klasse-Musters für keinen anderen Selektivitätsgewinn verliert .
  2. Wenn das optionale ExceptionArgument nicht verfügbar gemacht wird , führt dies zu mehreren Problemen:
    • Die Verwaltung einer Ausnahmeprotokollierungsrichtlinie wird dadurch noch schwieriger, sodass mit Ausnahmen nichts konsistent gemacht wird.
    • Selbst mit einer konsistenten Richtlinie gehen beim Formatieren der Ausnahme in eine Zeichenfolge Daten vorzeitig verloren. Ich habe einen benutzerdefinierten ILayoutDekorateur geschrieben, der einen detaillierten Drilldown für eine Ausnahme ausführt, um die Ereigniskette zu bestimmen.
  3. Wenn die Eigenschaften nichtIsLevelEnabled verfügbar gemacht werden, wird die Möglichkeit verworfen, Formatierungscode zu überspringen, wenn Bereiche oder Protokollierungsstufen deaktiviert sind.
Jeffrey Hantin
quelle
1
Ich wurde beauftragt, einen (schrecklichen) internen Wrapper um log4j in etwas weniger Schreckliches umzugestalten (es ist immer noch ziemlich schlecht, aber das ist ein Ergebnis davon, dass ich die Anforderungen, die mir an log4j gestellt wurden, in den Schatten gestellt habe). Ich habe versucht, den globalen statischen Einstiegspunkt zu beseitigen, wurde jedoch abgeschossen. Ich verstehe den Punkt wirklich nicht. In unserem Setup ist log4j so stark erweitert und verdreht, dass es wirklich nur als Ereignis-Dispatcher verwendet wird. Wir verwenden es nur, weil jemand gefragt hat: "Wie können wir log4j dafür verwenden?" Verwenden Sie entweder log4whatever direkt oder schreiben Sie einfach Ihr eigenes Framework. Die mittlere Straße ist schmerzhaft.
Adam Jaskiewicz
25
Ich bin mit Ihrer Empfehlung nicht einverstanden, log4net nicht zu verpacken. Durch das Umschließen mit einer Thin-Provider-Modell-API können Benutzer Ihrer Klassenbibliotheken ihr bevorzugtes Protokollierungsframework einbinden. YMMV natürlich, aber es als "Haupt-Anti-Muster" zu bezeichnen, ist ein bisschen dogmatisch. Auch die Tatsache, dass es Wrapper-Bibliotheken mit "einer Litanei von Fehlern" gibt, ist kein gutes Argument gegen einen gut geschriebenen Wrapper.
Joe
1
Etwas als Anti-Muster zu bezeichnen bedeutet nicht, dass es immer zu 100% eine schlechte Idee ist - nur, dass es die Tendenz erzeugt, sich in eine Ecke zu malen, wenn Sie nicht vorsichtig sind. ILog / LogManager ist selbst eine gut geschriebene Wrapper-Minibibliothek im Image der Commons-Protokollierung, die in der log4net-Assembly gebündelt ist. Es gibt jedoch keinen Grund, warum sie nicht extrahiert und in eine ordnungsgemäße Commons-Protokollierung für CLR umgewandelt werden kann.
Jeffrey Hantin
18

Ich entwickle nicht oft in asp.net, aber wenn es um Logger geht, denke ich, dass viele Best Practices universell sind. Hier sind einige meiner zufälligen Gedanken zum Protokollieren, die ich im Laufe der Jahre gelernt habe:

Frameworks

  • Verwenden Sie ein Logger-Abstraktionsframework wie slf4j (oder rollen Sie Ihr eigenes), damit Sie die Logger-Implementierung von Ihrer API entkoppeln. Ich habe eine Reihe von Logger-Frameworks kommen und gehen sehen, und Sie sind besser dran, wenn Sie ohne großen Aufwand ein neues übernehmen können.
  • Versuchen Sie, ein Framework zu finden, das eine Vielzahl von Ausgabeformaten unterstützt.
  • Versuchen Sie, ein Framework zu finden, das Plugins / benutzerdefinierte Filter unterstützt.
  • Verwenden Sie ein Framework, das von externen Dateien konfiguriert werden kann, damit Ihre Kunden / Verbraucher die Protokollausgabe einfach optimieren können, damit sie von kommerziellen Protokollverwaltungsanwendungen problemlos gelesen werden kann.
  • Stellen Sie sicher, dass Sie bei benutzerdefinierten Protokollierungsstufen nicht über Bord gehen, da Sie sonst möglicherweise nicht zu anderen Protokollierungsframeworks wechseln können.

Logger-Ausgabe

  • Vermeiden Sie Protokolle im XML / RSS-Stil für die Protokollierung, bei denen katastrophale Fehler auftreten können. Dies ist wichtig, da </xxx>Ihr Protokoll beschädigt ist, wenn der Netzschalter ausgeschaltet wird, ohne dass Ihr Logger das schließende Tag schreibt .
  • Threads protokollieren. Andernfalls kann es sehr schwierig sein, den Ablauf Ihres Programms zu verfolgen.
  • Wenn Sie Ihre Protokolle internationalisieren müssen, möchten Sie möglicherweise, dass sich ein Entwickler nur in Englisch (oder in der Sprache Ihrer Wahl) anmeldet.
  • Manchmal kann die Möglichkeit, Protokollierungsanweisungen in SQL-Abfragen einzufügen, in Debugging-Situationen lebensrettend sein. Sowie:
    - Aufruf der Klasse: com.foocorp.foopackage.FooClass: 9021
    SELECT * FROM foo;
  • Sie möchten eine Protokollierung auf Klassenebene. Normalerweise möchten Sie auch keine statischen Instanzen von Loggern - die Mikrooptimierung lohnt sich nicht.
  • Das Markieren und Kategorisieren protokollierter Ausnahmen ist manchmal nützlich, da nicht alle Ausnahmen gleich erstellt werden. Wenn Sie über einen Protokollmonitor verfügen, der Benachrichtigungen über kritische Zustände senden muss, ist es daher hilfreich, eine Teilmenge wichtiger Ausnahmen im Voraus zu kennen.
  • Duplizierungsfilter sparen Ihr Sehvermögen und Ihre Festplatte. Möchten Sie wirklich, dass dieselbe Protokollierungsanweisung 10 ^ 10000000 Mal wiederholt wird? Wäre es nicht besser, nur eine Nachricht zu erhalten wie: This is my logging statement - Repeated 100 times

Siehe auch meine Frage .

Elijah
quelle
5
Duplizierungsfilter sind eine großartige Idee
Paul Stovell
Früher war ich mir über das Problem mit defekten Tags einig, aber die meisten guten XML-Autoren verwenden ohnehin kein vollständiges XML (dh kein Root-Element), sodass sie sich protokollieren können, ohne das XML-DOM zu laden. In dem ungewöhnlichen Fall, dass ein Problem durch einen teilweise geschriebenen Eintrag auftritt, können Sie es manuell beheben
Paul Stovell
Ich beschäftige mich seit Jahren mit XML-Protokollierung. Jetzt scheint es mir übertrieben. Wenn ich einen RSS-Feed mit dem Status einer Anwendung benötigte, ist dieser meiner Meinung nach besser mit einem Dienstprogramm zur Protokollüberwachung implementiert.
Elijah
Ich stimme RSS zu. Ich denke mehr über Visualisierungstools nach, mit denen Sie den Eintrag besser verstehen können. Bei Textdateien möchten Sie im Allgemeinen einen Eintrag in einer Zeile behalten. Manchmal möchten Sie jedoch Stapelspuren oder serialisierte Objekte einschließen. Hier
bietet sich
+1 für die Erwähnung der Instrumentierung von SQL-Abfragen. Dies ist in der Tat sehr nützlich für die Korrelation von Datenbank- und Anwendungsspuren. Ich mache es manuell in meinem DAL, aber ich frage mich, welche Art von Werkzeugunterstützung gibt es für diese Technik?
Constantin
17

Ich bin nicht qualifiziert, die Protokollierung für .Net zu kommentieren, da mein Brot und Butter Java ist, aber wir haben in den letzten 8 Jahren eine Migration in unserer Protokollierung durchgeführt. Möglicherweise finden Sie eine nützliche Analogie zu Ihrer Frage.

Wir haben mit einem Singleton-Logger begonnen, der von jedem Thread in der JVM verwendet wurde, und die Protokollierungsstufe für den gesamten Prozess festgelegt. Dies führte zu großen Protokollen, wenn wir sogar einen ganz bestimmten Teil des Systems debuggen mussten. Die erste Lektion besteht also darin, Ihre Protokollierung zu segmentieren.

Unsere aktuelle Inkarnation des Loggers ermöglicht mehrere Instanzen, wobei eine als Standard definiert ist. Wir können eine beliebige Anzahl von untergeordneten Protokollierern mit unterschiedlichen Protokollierungsstufen instanziieren. Die nützlichste Facette dieser Architektur ist jedoch die Möglichkeit, Protokollierer für einzelne Pakete und Klassen zu erstellen, indem einfach die Protokollierungseigenschaften geändert werden. Die zweite Lektion besteht darin, ein flexibles System zu erstellen, mit dem das Verhalten überschrieben werden kann, ohne den Code zu ändern.

Wir verwenden die Apache Commons-Logging-Bibliothek, die um Log4J gewickelt ist.

Hoffe das hilft!

* Bearbeiten *

Nachdem ich den Beitrag von Jeffrey Hantin unten gelesen hatte, wurde mir klar, dass ich hätte notieren müssen, was unser interner Protokollierungs-Wrapper tatsächlich geworden ist. Es ist jetzt im Wesentlichen eine Fabrik und wird ausschließlich verwendet, um einen funktionierenden Logger mit der richtigen Eigenschaftendatei zu erhalten (die aus früheren Gründen nicht an die Standardposition verschoben wurde). Da Sie die Protokollierungskonfigurationsdatei jetzt in der Befehlszeile angeben können, wird sie vermutlich noch schlanker. Wenn Sie eine neue Anwendung starten, stimme ich seiner Aussage definitiv zu, dass Sie sich nicht einmal die Mühe machen sollten, den Protokollierer zu verpacken.

Steve Moyer
quelle
Danke für die Antwort. Erstellen Sie die untergeordneten Logger manuell im Code (dh sind sie fest codiert) oder durch eine Art automatisches / implizites Element?
Paul Stovell
Nein ... Wenn wir den logging.properties-Dateien für ein Paket oder eine Klasse eine Protokollierungskonfiguration hinzufügen, werden diese gemäß dieser Konfiguration protokolliert, aber alle Pakete oder Klassen, die nicht speziell konfiguriert sind, werden auf den Standardebenen protokolliert.
Steve Moyer
9

Wir verwenden Log4Net bei der Arbeit als Protokollierungsanbieter mit einem Singleton-Wrapper für die Protokollinstanz (obwohl der Singleton überprüft wird und fragt, ob er eine gute Idee ist oder nicht).

Wir haben es aus folgenden Gründen gewählt:

  • Einfache Konfiguration / Rekonfiguration in verschiedenen Umgebungen
  • Gute Anzahl vorgefertigter Appender
  • In einem der von uns verwendeten CMS war es bereits eingebaut
  • Schöne Anzahl von Protokollebenen und Konfigurationen um sie herum

Ich sollte erwähnen, dass dies aus Sicht der ASP.NET-Entwicklung geschieht

Ich kann einige Vorteile bei der Verwendung des Trace im .NET Framework erkennen, bin aber nicht vollständig davon überzeugt, hauptsächlich weil die Komponenten, mit denen ich arbeite, keine Trace-Aufrufe ausführen. Das einzige, was ich häufig benutze, ist das, System.Net.Mailwas ich sagen kann.

Wir haben also eine Bibliothek, die log4net umschließt, und in unserem Code brauchen wir nur solche Dinge:

Logger.Instance.Warn("Something to warn about");
Logger.Instance.Fatal("Something went bad!", new Exception());

try {
  var i = int.Parse("Hello World");
} catch(FormatException, ex) {
  Logger.Instance.Error(ex);
}

Innerhalb der Methoden überprüfen wir, ob die Protokollierungsstufe aktiviert ist, sodass Sie keine redundanten Aufrufe der log4net-API haben (wenn also Debug nicht aktiviert ist, werden die Debug-Anweisungen ignoriert), aber wenn ich etwas Zeit bekomme Ich werde es aktualisieren, um diese freizulegen, damit Sie die Überprüfungen selbst durchführen können. Dies verhindert, dass Bewertungen durchgeführt werden, wenn dies nicht der Fall sein sollte, z.

Logger.Instance.Debug(string.Format("Something to debug at {0}", DateTime.Now);

Dies wird:

if(Logger.DebugEnabled) Logger.Instance.Debug(string.Format("Something to debug at {0}", DateTime.Now);

(Sparen Sie ein bisschen Ausführungszeit)

Standardmäßig melden wir uns an zwei Orten an:

  1. Dateisystem der Website (in einer nicht bereitgestellten Dateierweiterung)
  2. E-Mail-Versand für Error & Fatal

Dateien werden als Rolling von jedem Tag oder 10 MB (IIRC) erstellt. Wir verwenden das EventLog nicht, da es eine höhere Sicherheit erfordern kann, als wir häufig einer Site geben möchten.

Ich finde, Notepad funktioniert gut zum Lesen von Protokollen.

Aaron Powell
quelle
Protokollierungsframeworks sind einer der wenigen Fälle, in denen der Singleton kein Missbrauch ist.
mmcdole
Dies kann der Fall sein, wenn Sie einen Kontext für Ihren Logger bereitstellen möchten. Aber es hilft, mit Parallelität umzugehen
Aaron Powell
7
Ich würde definitiv den Singleton herausreißen. Sie können sicherlich eine einzelne Instanz haben, die herumgereicht wird (vorzugsweise im IOC / DI-Container). Ich würde auch versuchen, mich in einen Abfangjäger
einzuloggen
2
Auch kein Fan der einzelnen Instanz. Ich bevorzuge es, jeder Klasse einen eindeutig benannten Logger zu geben, so dass es einfach ist, die Protokollierung pro Modul nach oben oder unten zu drehen.
Jeffrey Hantin
8

Welche Frameworks verwenden Sie?

Wir verwenden eine Mischung aus dem Protokollierungsanwendungsblock und einem benutzerdefinierten Protokollierungshelfer, der die .NET-Framework-Bits umgeht. Das LAB ist so konfiguriert, dass es ziemlich umfangreiche Protokolldateien ausgibt, einschließlich separater allgemeiner Ablaufverfolgungsdateien für die Eingabe / Beendigung von Dienstmethoden und spezifischer Fehlerdateien für unerwartete Probleme. Die Konfiguration enthält Datum / Uhrzeit, Thread, pId usw. für die Debug-Unterstützung sowie die vollständigen Ausnahmedetails und den Stapel (im Falle einer unerwarteten Ausnahme).

Der benutzerdefinierte Protokollierungshelfer verwendet die Trace.Correlation und ist besonders praktisch im Zusammenhang mit der Protokollierung in WF. Zum Beispiel haben wir eine Zustandsmaschine, die eine Reihe von sequentiellen Workflows aufruft. Bei jeder dieser Aufrufaktivitäten protokollieren wir den Start (mit StartLogicalOperation) und stoppen am Ende die logische Operation mit einem gererischen Rückgabeereignishandler.

Dies hat sich einige Male als nützlich erwiesen, wenn versucht wird, Fehler in komplexen Geschäftsabläufen zu debuggen, da wir so Dinge wie If / Else-Verzweigungsentscheidungen usw. schneller anhand der Aktivitätsausführungssequenz bestimmen können.

Welche Protokollausgaben verwenden Sie?

Wir verwenden Textdateien und XML-Dateien. Textdateien werden über den App-Block konfiguriert, aber wir haben auch XML-Ausgaben von unserem WF-Dienst. Auf diese Weise können wir die Laufzeitereignisse (Persistenz usw.) sowie allgemeine Ausnahmen für Geschäftstypen erfassen. Die Textdateien sind fortlaufende Protokolle, die nach Tag und Größe gerollt werden (ich glaube, die Gesamtgröße von 1 MB ist ein Rollover-Punkt).

Welche Tools verwenden Sie zum Anzeigen der Protokolle?

Wir verwenden Notepad und WCF Service Trace Viewer, je nachdem, welche Ausgabegruppe wir betrachten. Der WCF Service Trace Viewer ist wirklich sehr praktisch, wenn Sie Ihre Ausgabe korrekt eingerichtet haben und das Lesen der Ausgabe erheblich vereinfachen können. Das heißt, wenn ich ungefähr weiß, wo der Fehler sowieso liegt, ist es auch gut, nur eine gut kommentierte Textdatei zu lesen.

Die Protokolle werden an ein einzelnes Verzeichnis gesendet, das dann basierend auf dem Quelldienst in Unterverzeichnisse aufgeteilt wird. Das Root-Verzeichnis wird über eine Website verfügbar gemacht, deren Zugriff von einer Support-Benutzergruppe kontrolliert wird. Auf diese Weise können wir Produktionsprotokolle einsehen, ohne Anforderungen stellen und langwierige Bürokratieprozesse für Produktionsdaten durchführen zu müssen.

Steve Godbold
quelle
6

Als Autoren des Tools verwenden wir SmartInspect natürlich zum Protokollieren und Verfolgen von .NET-Anwendungen. Normalerweise verwenden wir das Named-Pipe-Protokoll für die Live-Protokollierung und (verschlüsselte) binäre Protokolldateien für Endbenutzerprotokolle. Wir verwenden die SmartInspect Console als Viewer- und Überwachungstool.

Es gibt tatsächlich einige Protokollierungsframeworks und -tools für .NET. Auf DotNetLogging.com finden Sie eine Übersicht und einen Vergleich der verschiedenen Tools .

Dennis G.
quelle
5

Die Antworten enthalten viele gute Empfehlungen.

Eine allgemeine bewährte Methode besteht darin, zu prüfen, wer das Protokoll lesen wird. In meinem Fall ist es ein Administrator am Client-Standort. Also protokolliere ich Nachrichten, die ihnen etwas geben, auf das sie reagieren können. Beispiel: "Anwendung kann nicht initialisiert werden. Dies wird normalerweise durch ... verursacht."

Matthew Sposato
quelle
1

Wir verwenden log4net in unseren Webanwendungen.

Die Möglichkeit, die Protokollierung zur Laufzeit durch Ändern der XML-Konfigurationsdatei anzupassen, ist sehr praktisch, wenn eine Anwendung zur Laufzeit fehlerhaft funktioniert und Sie weitere Informationen benötigen.

Außerdem können Sie auf bestimmte Klassen oder Attribute abzielen, unter denen Sie sich anmelden möchten. Dies ist sehr praktisch, wenn Sie eine Vorstellung davon haben, wo der Fehler auftritt. Ein klassisches Beispiel ist NHibernate, bei dem nur SQL in die Datenbank übertragen werden soll.

Bearbeiten:

Wir schreiben alle Ereignisse in eine Datenbank und das Trace-System. Das Ereignisprotokoll, das wir für Fehler oder Ausnahmen verwenden. Wir protokollieren die meisten Ereignisse in einer Datenbank, damit wir benutzerdefinierte Berichte erstellen und die Benutzer das Protokoll anzeigen lassen können, wenn sie direkt aus der Anwendung möchten.

Jeffrey Cameron
quelle
Können Sie weitere Details zu Ihrer Verwendung angeben? Melden Sie sich in einer Datei oder im Ereignisprotokoll an? Ist es eine fortlaufende Protokolldatei? Was tun Sie, um es zu sichern oder zu sichern? Ich interessiere mich für den realen Gebrauch.
Paul Stovell
1

In Bezug auf die aspektorientierte Protokollierung wurde mir PostSharp für eine andere SO-Frage empfohlen -

Aspektorientierte Protokollierung mit Unity \ T4 \ alles andere

Der in der Antwort angegebene Link ist einen Besuch wert, wenn Sie Protokollierungsframeworks evaluieren.

Unmesh Kondolikar
quelle