Bewährte Methoden für die Protokollierung und Ablaufverfolgung in .NET

53

Ich habe viel über Nachverfolgung und Protokollierung gelesen und versucht, eine goldene Regel für Best Practices in dieser Angelegenheit zu finden, aber es gibt keine. Die Leute sagen, dass gute Programmierer gutes Tracing produzieren, aber sagen Sie es so und es muss aus Erfahrung kommen.

Ich habe auch ähnliche Fragen hier und im Internet gelesen und sie sind nicht wirklich dasselbe, was ich stelle, oder ich habe keine befriedigende Antwort, vielleicht weil die Fragen ein paar Details haben.

Leute sagen also, dass die Ablaufverfolgung die Erfahrung des Debuggens der Anwendung in Fällen replizieren sollte, in denen Sie keinen Debugger anhängen können. Es sollte genügend Kontext bieten, damit Sie sehen können, welcher Pfad an jedem Kontrollpunkt in der Anwendung genommen wird.

Im Detail können Sie sogar zwischen Ablaufverfolgung und Ereignisprotokollierung unterscheiden, da "die Ereignisprotokollierung sich von der Ablaufverfolgung dadurch unterscheidet, dass sie die Hauptzustände erfasst und nicht den detaillierten Kontrollfluss".

Angenommen, ich möchte die Ablaufverfolgung und Protokollierung nur mit den Standard-.NET-Klassen durchführen, die sich im System.DiagnosticsNamespace befinden. Ich stellte fest, dass die TraceSource-Klasse für den Job besser ist als die statische Trace-Klasse, da ich zwischen den Trace-Ebenen unterscheiden und die TraceSource-Klasse verwenden möchte, die ich in einem Parameter übergeben kann, der den Ereignistyp informiert, während ich die Trace-Klasse verwende, die ich verwenden muss Trace.WriteLineIfund dann Dinge wie SourceSwitch.TraceInformationund überprüfen SourceSwitch.TraceErrors, und es hat nicht einmal Eigenschaften wie TraceVerboseoder TraceStart.

Würden Sie in Anbetracht dessen eine gute Vorgehensweise in Betracht ziehen, um Folgendes zu tun:

  • Verfolgen Sie ein "Start" -Ereignis, wenn Sie eine Methode starten, die eine einzelne logische Operation oder eine Pipeline darstellen soll, sowie eine Zeichenfolgendarstellung der an die Methode übergebenen Parameterwerte.
  • Verfolgen Sie ein "Information" -Ereignis, wenn Sie ein Element in die Datenbank einfügen.
  • Verfolgen Sie ein "Information" -Ereignis, wenn Sie in einer wichtigen if / else-Anweisung den einen oder anderen Pfad verwenden.
  • Verfolgen Sie einen "Kritischen" oder "Fehler" in einem Catch-Block, je nachdem, ob es sich um einen behebbaren Fehler handelt.
  • Verfolgen Sie ein "Stop" -Ereignis, wenn die Ausführung der Methode abgeschlossen ist.

Außerdem klären Sie bitte, wann Sie die Ereignistypen "Ausführlich" und "Warnung" am besten nachverfolgen können. Wenn Sie Codebeispiele mit netter Ablaufverfolgung / Protokollierung haben und bereit sind, sie weiterzugeben, wäre dies exzellent.

Hinweis: Ich habe hier einige gute Informationen gefunden, aber immer noch nicht das, wonach ich suche: http://msdn.microsoft.com/en-us/magazine/ff714589.aspx

Levidad
quelle
Vielleicht ist auch die bevorzugte Art der Protokollierung in Net Deployed to Azure bei Stackoverflow hilfreich.
k3b
Gibt es eine vollständige Quellcode-Beispielanwendung, die gute Muster für die Protokollierung verwendet?
Kiquenet
Ehrlich ... Wenn ich mit .NET arbeiten würde, würde ich wahrscheinlich einfach etwas wie New Relic installieren und es als erledigt bezeichnen. (Vielleicht keine gute Option zu dem Zeitpunkt, als dies veröffentlicht wurde)
Svidgen

Antworten:

17

Die Wichtigkeit von Trace-Typen muss nicht aufgrund der Position des Trace im Code ausgewählt werden, sondern weil die verfolgte Nachricht mehr oder weniger wichtig ist. Beispiel:

Verfolgen Sie ein "Start" -Ereignis, wenn Sie eine Methode starten, die eine einzelne logische Operation oder eine Pipeline darstellen soll, sowie eine Zeichenfolgendarstellung der an die Methode übergebenen Parameterwerte.

Verwenden Sie den Starttyp, wenn Sie eine logische Operation starten. Dies bedeutet nicht, dass sich der Starttrace am Anfang einer Methode befinden muss, und auch nicht, dass eine Methode einen Starttrace haben muss.

In den meisten Fällen beginnt eine logische Operation tatsächlich am Anfang des Verfahrens. Andernfalls sollten Sie sich fragen, ob der Code korrekt überarbeitet wurde.

Die Verfolgung von Parametern kann ebenfalls eine schlechte Idee sein . Sie müssen sich überlegen, was Sie von Fall zu Fall nachvollziehen müssen. Zum Beispiel ist es wirklich schlecht, Parameter einer Methode zu verfolgen void Authenticate(string userName, string plainPassword).

Verfolgen Sie ein "Information" -Ereignis, wenn Sie ein Element in die Datenbank einfügen.

Es hängt davon ab, ob. Einige Artikel müssen zurückverfolgt werden, aber nicht jeder Artikel.

  • Stellen Sie sich beispielsweise vor, Sie fügen tatsächlich ein Protokollelement in Ihre Datenbank ein. Würden Sie Protokolle verfolgen? Und dann Spuren protokollieren? Und dann die Protokollierung der Ablaufverfolgung verfolgen?
  • Ein weiteres Beispiel: Sie fügen vertrauliche Daten ein. Dies erfordert eine Prüfung. Warum wurde die Einfügung nachverfolgt, seitdem Sie sie geprüft haben?

Verfolgen Sie ein "Information" -Ereignis, wenn Sie in einer wichtigen if / else-Anweisung den einen oder anderen Pfad verwenden.

Auch hier kommt es darauf an.

Verfolgen Sie einen "Kritischen" oder "Fehler" in einem Fangblock, abhängig vom Wetter. Dies ist ein behebbarer Fehler.

Die Aktion, die nach einem nicht behebbaren Fehler ausgeführt wird, kann mehr als nur eine Ablaufverfolgung sein. Beispielsweise möchten Sie serverseitig die Ausnahme zur weiteren Analyse in der Datenbank speichern. Außerdem sind einige Ausnahmen weniger wichtig als andere und erfordern keine Ablaufverfolgung.

Verfolgen Sie ein "Stop" -Ereignis, wenn die Ausführung der Methode abgeschlossen ist.

Siehe den ersten Punkt.

Bitte klären Sie, wann Sie die Ereignistypen Verbose und Warning am besten nachverfolgen können.

Ausführlich:

Mit Verbose können Sie nachverfolgen, was Sie nachverfolgen müssen, wenn etwas wirklich schief geht. Dies bedeutet, dass Sie in den meisten Fällen die Ablaufverfolgung ausführlicher Nachrichten deaktivieren. Manchmal müssen Sie jedoch einige Teile Ihres Codes debuggen, um zu verstehen, warum in einem Edge-Fall etwas fehlschlägt.

Normalerweise haben Sie viele ausführliche Nachrichten, mit denen Sie den Anwendungsfluss wirklich gut verstehen können. Dies bedeutet auch, dass diese Nachrichten die meiste Zeit deaktiviert werden müssen, weil:

  • Andernfalls wächst das Protokoll sehr schnell.
  • Sie brauchen sie die meiste Zeit nicht,
  • Sie können vertrauliche Daten über den Anwendungsfluss enthalten.

Stellen Sie sich Verbose als ein Tool vor, das Sie verwenden müssen, wenn Sie keinen Zugriff auf den Debugger haben.

Warnung:

Warnungstyp-Trace wird verwendet, wenn etwas Falsches und Wichtiges passiert, ist aber nicht zu kritisch, um als Fehler behandelt zu werden. Beispielsweise kann ein niedriger RAM-Speicher eine Warnung ausgeben, es gibt jedoch keinen Grund, einen Fehler aufzuspüren, da Ihre Anwendung fortgesetzt werden kann, auch wenn sie langsamer als gewöhnlich sein wird.

Beispiele:

  • Beispiel 1: Die Anwendung konnte die vom Benutzer angeforderte Datei nicht öffnen. Die Datei ist vorhanden und wird nicht verwendet. Die Berechtigungen sind korrekt festgelegt, das Öffnen einer Datei wird jedoch blockiert. In diesem Fall werden Sie einen Fehler verfolgen , da Ihre Anwendung diesen Fall nicht verwalten kann und weiterhin wie vom Benutzer erwartet arbeitet (dh die Datei tatsächlich liest).

  • Beispiel 2: Nach Prüfung des Fehlers im ersten Beispiel stellen Sie fest, dass der Fehler durch die Tatsache verursacht wird, dass der Dateipfad länger als 259 Zeichen ist. Sie überarbeiten also Ihren Code, um ihn abzufangen PathTooLongException. Wenn der Benutzer das nächste Mal versucht, dieselbe Datei zu öffnen, wird in der neuen Version der Anwendung eine Meldung angezeigt, die darauf hinweist, dass die Datei zu lang ist und in einen anderen Ordner verschoben werden muss, um den vollständigen Pfad zu verkürzen, damit diese Datei geöffnet werden kann Diese Anwendung. Sie verfolgen auch eine Nachricht .

  • Beispiel 3: Ihre Anwendung hat zwanzig Sekunden damit verbracht, eine kleine Datei zu öffnen und zu analysieren, während die meisten Dateien zehn bis einhundert Millisekunden benötigen, um sie zu öffnen und zu analysieren. Sie verfolgen eine Warnung mit relevanten Informationen: den Typ der Festplatte, auf der sich die Datei befindet, das Dateisystem, die Größe der Datei, die genaue Zeit, die Zeit, die der Computer eingeschaltet war usw. Wenn der Benutzer sich beschwert, dauert es zwanzig Sekunden, um die Datei zu öffnen, nehmen Sie den Trace, um herauszufinden, was passiert. Sie stellen beispielsweise fest, dass das Laden der Dateien von einer Netzwerkfreigabe so lange dauert, wenn der Computer gerade gestartet wurde. Sie erklären dem Benutzer, dass die Verzögerung auf das Netzwerk zurückzuführen ist und nicht mit Ihrer Anwendung zusammenhängt.

  • Beispiel 4: Die geöffnete Datei wird falsch angezeigt. Sie aktivieren die ausführliche Ablaufverfolgung, bei der Sie Schritt für Schritt sehen, wie die Daten aus der Datei geladen und dann analysiert werden.

Arseni Mourzenko
quelle
Ein Muster, das wir dort verwenden, wo ich arbeite, ist das Protokollieren von "KnownErrors" als Warnungen und "UnknownErrors" als Fehler. Abhängig von Ihrer Infrastruktur und dem Umgang mit Warnungen ist dies möglicherweise nicht angemessen, funktioniert aber für uns.
Andrew Piliser
5
 > say I want to do my tracing and logging using only the standard .NET classes

System.Diagnostics ist großartig, weil Sie konfigurieren können, wo welche Trace-Informationen wohin gehen sollen (Datei, Ereignisprotokoll, Datenbank, ....)

Leider, wenn Sie verwenden möchten System.DiagnosticsSie im Voraus wissen müssen ( zur Designzeit ), die Spurenströme möglich sein sollte , folgen. (Im Beispielartikel sind dies Transfer, Resume, Suspend, ...). Diese können als Deaktiviert, Debuglevel oder Fehlerlevel konfiguriert werden.

Ich ziehe ein Logging - System haben , wo ich zur Laufzeit entscheiden kann , classlevel / namespacelevel , wie detailliert sollte die Protokollierung sein. Zum Beispiel alle Debug und höher von MyNamespace.Business.*aber nicht MyNamespace.Business.Calculations.

Wenn Sie log4net (oder Common.logging) verwenden, erhält jede Klasse einen eigenen Logger, sodass Sie leicht entscheiden können, welche Klassen auf welcher Ebene protokolliert werden.

Da sich Datenbankoperationen in einer separaten Klasse befinden, ist keine separate Regel mehr erforderlich

Trace an "Information" event when inserting an item into the database.

Stattdessen bevorzuge ich diese Richtlinien:

  • Tracelevel sollte den grundlegenden Workflow anzeigen
  • Debuglevel sollte detaillierte Daten und die Verarbeitung innerhalb des Workflows anzeigen, einschließlich Entscheidungen im Programmablauf mit Gründen (Erstellen eines neuen Elements, da das Element in der Datenbank nicht vorhanden war).
  • Ordner zum Starten / Beenden von Diensten und ein Eintrag für jede gestartete Workflow- / GUI-Aktion
k3b
quelle
Ich verstehe, das sind gute Infos, danke! Aber wie ich in meiner ursprünglichen Frage gefragt habe, würden Sie bitte die Verwendung der Ereignistypen "Verbose" und "Warning" erläutern? Außerdem bitte ich andere Leute, ihren Standpunkt einzubringen, da dieses Thema eine eingehendere Untersuchung verdient, als ich es im Internet gesehen habe.
Levidad
4

Sie können das Story-Framework ausprobieren. Es bietet einen einzigartigen Ansatz für die Protokollierung, da alle Protokolle im Kontext "geschrieben" werden (und andere relevante Informationen hinzugefügt werden). Wenn Sie es später lesen müssen, erhalten Sie alles, was Sie benötigen.

Es werden automatisch die Konzepte "Start" und "Stopp" als Anfang und Ende einer Story hinzugefügt.

Und mit einem regelbasierten System können Sie steuern, was mit jeder Story (Kontext) basierend auf den darin enthaltenen Informationen geschehen soll, z. B. alle Storys drucken, die einen Fehler aufweisen oder vom Benutzer "admin" stammen.

Auch mehr Informationen zu diesem Blogeintrag

Amit Apple
quelle
1
Aktualisierte Antwort mit weiteren Informationen
Amit Apple