Frage

Als Fragte Jeff Atwood:„Was ist Ihre Protokollierungsphilosophie?Sollte der gesamte Code übersät sein? .logthis() Und .logthat() Anrufe?Oder fügen Sie die Protokollierung irgendwie nachträglich ein?“

War es hilfreich?

Lösung

Meine Protokollierungsphilosophie lässt sich ziemlich einfach in vier Teilen zusammenfassen:

Auditing oder Geschäftslogikprotokollierung

Protokollieren Sie die Dinge, die protokolliert werden müssen.Dies ergibt sich aus den Anwendungsanforderungen und kann die Protokollierung jeder an einer Datenbank vorgenommenen Änderung (wie in vielen Finanzanwendungen) oder die Protokollierung von Zugriffen auf Daten (wie es in der Gesundheitsbranche erforderlich sein kann, um Branchenvorschriften einzuhalten) umfassen.

Da dies Teil der Programmanforderungen ist, beziehen viele es nicht in ihre allgemeinen Diskussionen über die Protokollierung ein, es gibt jedoch Überschneidungen in diesen Bereichen, und für einige Anwendungen ist es nützlich, alle Protokollierungsaktivitäten zusammen zu betrachten.

Programmprotokollierung

Meldungen, die Entwicklern dabei helfen, die Anwendung zu testen und zu debuggen und den Datenfluss und die Programmlogik leichter zu verfolgen, um zu verstehen, wo Implementierungs-, Integrations- und andere Fehler auftreten können.

Im Allgemeinen wird diese Protokollierung nach Bedarf für Debugging-Sitzungen aktiviert und deaktiviert.

Leistungsprotokollierung

Fügen Sie nach Bedarf eine spätere Protokollierung hinzu, um Leistungsengpässe und andere Programmprobleme zu finden und zu beheben, die nicht zum Ausfall des Programms führen, aber zu einem besseren Betrieb führen.Überschneidungen mit der Programmprotokollierung bei Speicherlecks und einigen unkritischen Fehlern.

Sicherheitsprotokollierung

Protokollierung von Benutzeraktionen und Interaktionen mit externen Systemen, bei denen die Sicherheit ein Anliegen ist.Nützlich, um festzustellen, wie ein Angreifer nach einem Angriff ein System zerstört hat, kann aber auch mit einem Intrusion-Detection-System verknüpft werden, um neue oder laufende Angriffe zu erkennen.

Andere Tipps

Ich arbeite mit sicherheitskritischen Echtzeitsystemen und die Protokollierung ist oft die einzige Möglichkeit, seltene Fehler zu erkennen, die nur jeden 53. Dienstag bei Vollmond auftauchen, wenn Sie verstehen, was ich meine.Das macht einen irgendwie besessen von dem Thema, also entschuldige ich mich jetzt, wenn ich anfange, vor dem Mund zu schäumen.

Ich entwerfe Systeme, die so ziemlich alles protokollieren können, aber ich schalte nicht alles standardmäßig ein.Die Debug-Informationen werden an einen versteckten Debug-Dialog gesendet, der sie mit einem Zeitstempel versehen und in einem Listenfeld ausgibt (begrenzt auf etwa 500 Zeilen vor dem Löschen), und der Dialog ermöglicht es mir, sie zu stoppen, automatisch in einer Protokolldatei zu speichern oder dorthin umzuleiten ein angehängter Debugger wie DBWin32.Diese Umleitung ermöglicht es mir, die Debug-Ausgaben mehrerer Anwendungen sauber serialisiert zu sehen, was manchmal lebensrettend sein kann.Die Protokolldateien werden alle N Tage automatisch gelöscht.ICH gebraucht So verwenden Sie numerische Protokollierungsstufen (je höher Sie die Stufe einstellen, desto mehr erfassen Sie):

  • aus
  • Nur Fehler
  • Basic
  • detailliert
  • alles

Aber das ist zu unflexibel – während Sie sich auf einen Fehler zubewegen, ist es viel effizienter, sich beim Einloggen auf genau das zu konzentrieren, was Sie brauchen, ohne sich durch Tonnen von Müll wühlen zu müssen, und es kann sich dabei um eine bestimmte Art von Transaktion oder Vorgang handeln das verursacht den Fehler.Wenn Sie dafür alles einschalten müssen, erschweren Sie nur Ihre eigene Arbeit.Sie brauchen etwas Feinkörnigeres.

Jetzt bin ich gerade dabei, auf die Protokollierung basierend auf einem Flag-System umzusteigen.Alles, was protokolliert wird, hat eine Markierung, die angibt, um welche Art von Vorgang es sich handelt, und es gibt eine Reihe von Kontrollkästchen, mit denen ich definieren kann, was protokolliert wird.Normalerweise sieht diese Liste so aus:

#define DEBUG_ERROR          1
#define DEBUG_BASIC          2
#define DEBUG_DETAIL         4
#define DEBUG_MSG_BASIC      8
#define DEBUG_MSG_POLL       16
#define DEBUG_MSG_STATUS     32
#define DEBUG_METRICS        64
#define DEBUG_EXCEPTION      128
#define DEBUG_STATE_CHANGE   256
#define DEBUG_DB_READ        512
#define DEBUG_DB_WRITE       1024
#define DEBUG_SQL_TEXT       2048
#define DEBUG_MSG_CONTENTS   4096

Dieses Protokollierungssystem wird mit dem Release-Build ausgeliefert, ist standardmäßig aktiviert und speichert in einer Datei.Es ist zu spät, um herauszufinden, dass Sie sich hätten anmelden sollen, NACHDEM der Fehler aufgetreten ist, wenn dieser Fehler im Durchschnitt nur alle sechs Monate auftritt und Sie keine Möglichkeit haben, ihn zu reproduzieren.

Die Software wird normalerweise mit aktivierten ERROR, BASIC, STATE_CHANGE und EXCEPTION ausgeliefert, aber dies kann vor Ort über den Debug-Dialog (oder eine Registry/INI/CFG-Einstellung, in der diese Dinge gespeichert werden) geändert werden.

Oh und noch etwas: Mein Debug-System generiert eine Datei pro Tag.Ihre Anforderungen können unterschiedlich sein.Stellen Sie jedoch sicher, dass Ihr Debug-Code startet jeden Datei mit dem Datum, der Version des von Ihnen ausgeführten Codes und, wenn möglich, einer Markierung für die Kunden-ID, den Standort des Systems oder was auch immer.Sie können ein Durcheinander von Protokolldateien erhalten, die vom Außendienst eingehen, und Sie benötigen Aufzeichnungen darüber, was von wo kam und welche Version des Systems ausgeführt wurde, die tatsächlich in den Daten selbst enthalten sind, und Sie können dem Kunden nicht vertrauen /Außendiensttechniker, um Ihnen zu sagen, welche Version sie haben – sie sagen Ihnen möglicherweise nur, welche Version sie zu haben glauben.Schlimmer noch, sie melden möglicherweise die exe-Version, die sich auf der Festplatte befindet, aber die alte Version läuft noch, weil sie vergessen haben, nach dem Ersetzen neu zu starten.Lassen Sie sich von Ihrem Code selbst erzählen.

Das ist mein Hirnschmuggel...

Ich denke, immer, immer, immer die Protokollierung hinzufügen, wenn es eine Ausnahme gibt, einschließlich der Meldung und des vollständigen Stack-Trace.Darüber hinaus denke ich, dass es ziemlich subjektiv ist, ob Sie die Protokolle häufig verwenden oder nicht ...

Ich versuche oft, die Protokollierung nur an kritischen Stellen hinzuzufügen, an denen das, was ich protokolliere, nur sehr selten auftreten sollte, sonst entsteht das von ihm erwähnte Problem der Protokolle, die viel zu groß werden ...Aus diesem Grund ist es ideal, Fehlerfälle immer zu protokollieren (und es ist großartig zu sehen, wann diese Fehlerfälle tatsächlich auftreten, damit Sie das Problem genauer untersuchen können).

Andere gute Dinge zum Protokollieren sind: Wenn Sie Behauptungen haben und diese fehlschlagen, dann protokollieren Sie sie ...Diese Abfrage sollte beispielsweise weniger als 10 Ergebnisse enthalten. Wenn sie größer ist, liegt möglicherweise ein Problem vor. Protokollieren Sie sie daher.Wenn eine Protokollanweisung am Ende die Protokolle füllt, ist das natürlich wahrscheinlich ein Hinweis darauf, sie entweder auf eine Art „Debug“-Ebene zu versetzen oder die Protokollanweisung anzupassen oder zu entfernen.Wenn die Protokolle zu groß werden, werden Sie sie oft ignorieren.

Ich verfolge einen meiner Meinung nach traditionellen Ansatz.einige Protokolle, umgeben von bedingten Definitionen.Für Produktions-Builds schalte ich die Definitionen aus.

Ich entscheide mich bewusst für die Protokollierung, da dies bedeutet, dass die Protokolldaten aussagekräftig sind:

  • Abhängig vom Protokollierungsframework können Sie Informationen zur Ebene/Schweregrad/Kategorie hinzufügen, damit die Protokolldaten gefiltert werden können
  • Sie können sicherstellen, dass das richtige Maß an Informationen vorhanden ist, nicht zu viel und nicht zu wenig
  • Sie wissen beim Schreiben des Codes, welche Dinge am wichtigsten sind, und können so sicherstellen, dass diese protokolliert werden

Die Verwendung irgendeiner Form von Code-Injection, Profiling oder Tracing-Tool zum Generieren von Protokollen würde höchstwahrscheinlich zu ausführlichen, weniger nützlichen Protokollen führen, in die es schwieriger wäre, sich damit zu befassen.Sie können jedoch als Debugging-Hilfe nützlich sein.

Ich beginne damit, viele Bedingungen in meinem Code durchzusetzen (in C# mit System.Diagnostics.Assert), aber ich füge die Protokollierung nur dann hinzu, wenn ich beim Debuggen oder bei der Belastung des Systems feststelle, dass ich wirklich eine Möglichkeit brauche, zu verfolgen, was in meinem Code passiert, ohne dass ein Debugger dauerhaft angeschlossen ist.

Ansonsten nutze ich lieber die Fähigkeit von Visual Studio, Spuren als spezielle Haltepunkte in den Code einzufügen (d. h.Sie fügen einen Haltepunkt ein und klicken mit der rechten Maustaste darauf, wählen dann „Bei Treffer...“ und sagen ihm, was in diesem Fall angezeigt werden soll.Eine Neukompilierung ist nicht erforderlich und die Traces können problemlos im laufenden Betrieb aktiviert/deaktiviert werden.

Wenn Sie ein Programm schreiben, das von vielen Leuten verwendet wird, ist es am besten, über einen Mechanismus zu verfügen, mit dem Sie auswählen können, was protokolliert wird und was nicht.Ein Argument für .logthis()-Funktionen ist, dass sie in manchen Fällen ein hervorragender Ersatz für Inline-Kommentare sein können (wenn sie richtig gemacht werden).

Außerdem können Sie damit GENAU eingrenzen, wo ein Fehler auftritt.

Protokollieren Sie sie alle und lassen Sie Grep sie sortieren.

Ich stimme Adam zu, aber ich würde auch darüber nachdenken, interessante Dinge oder Dinge, die man als Erfolge nachweisen kann, als eine Art Beweis dafür zu protokollieren, dass sie geschehen.

Ich definiere verschiedene Ebenen und übergebe eine Einstellung mit der Konfiguration/Aufruf.

Wenn Sie wirklich eine Anmeldung in Ihrem System benötigen, sind Ihre Tests Mist oder zumindest unvollständig und nicht sehr gründlich.Alles in Ihrem System sollte so weit wie möglich eine Blackbox sein.Beachten Sie, dass Kernklassen wie String keine Protokollierung benötigen – der Hauptgrund dafür ist, dass sie sehr gut getestet sind und die detaillierte Leistung erbringen.Keine Überraschungen.

Ich verwende die Protokollierung, um Probleme einzugrenzen, die sich in unseren Komponententests nicht reproduzieren, ganz zu schweigen davon, dass ich die gleichen vom Benutzer bereitgestellten Schritte wiederhole:Diese seltenen Störungen, die nur auf einer sehr entfernten Hardware auftreten (und manchmal, wenn auch sehr selten, sogar durch einen Treiber- oder Bibliotheksfehler eines Drittanbieters verursacht werden, der außerhalb unserer Kontrolle liegt).

Ich stimme dem Kommentar zu, dass dies alles durch unser Testverfahren erfasst werden sollte, aber es ist schwierig, eine LOC-Codebasis mit mehr als einer Million zu finden, die leistungskritischen Code auf sehr niedrigem Niveau erfordert, um diese Anforderungen jemals zu erfüllen.Ich arbeite nicht in geschäftskritischer Software, aber ich arbeite in der Grafikbranche, wo wir oft alles tun müssen, von der Implementierung von Speicherzuweisungen bis zur Verwendung von GPU-Code für SIMD.

Selbst bei sehr modularem, lose gekoppeltem oder sogar vollständig entkoppeltem Code können die Systeminteraktionen zu sehr komplexen Ein- und Ausgaben mit unterschiedlichem Verhalten zwischen den Plattformen führen, wobei es gelegentlich zu Rogue-Edge-Fällen kommt, die sich unseren Tests entziehen.Modulare Blackboxen können sehr einfach sein, aber die Wechselwirkungen zwischen ihnen können sehr komplex werden und gelegentlich zu unerwarteten Grenzfällen führen.

Ein Beispiel für einen Fall, in dem mir die Protokollierung den Hintern gerettet hat: Einmal hatte ich diesen seltsamen Benutzer mit einem Prototyp eines Intel-Rechners, der abstürzte.Wir haben die Mindestanforderungen für Maschinen aufgelistet, die SSE 4 unterstützen sollten, aber diese spezielle Maschine erfüllte diese Mindestanforderungen und unterstützte immer noch keine Streaming-SIMD-Erweiterungen über SSE 3 hinaus, obwohl es sich um eine 16-Kern-Maschine handelt.Dies konnte schnell herausgefunden werden, indem er sich sein Protokoll ansah, das genau die Zeilennummer zeigte, in der die SSE 4-Anweisungen verwendet wurden.Keiner von uns in unserem Team konnte das Problem reproduzieren, geschweige denn ein einziger anderer Benutzer, der an der Überprüfung des Berichts beteiligt war.Idealerweise hätten wir Code für ältere SIMD-Versionen geschrieben oder zumindest einige Verzweigungen und Überprüfungen vorgenommen, um sicherzustellen, dass die Hardware die Mindestanforderungen unterstützt. Aus Gründen der Einfachheit und Wirtschaftlichkeit wollten wir jedoch eine feste Annahme treffen, die durch die Mindestanforderungen an die Hardware kommuniziert wird.Hier kann man vielleicht argumentieren, dass es unsere Mindestsystemanforderungen waren, die den „Fehler“ hatten.

Angesichts der Art und Weise, wie ich die Protokollierung hier verwende, erhalten wir in der Regel ziemlich große Protokolle.Das Ziel ist jedoch nicht die Lesbarkeit – was normalerweise wichtig ist, ist die letzte Zeile eines Protokolls, das mit einem Bericht gesendet wird, wenn der Benutzer einen Absturz erlebt, den keiner von uns im Team (geschweige denn einige andere Benutzer auf der Welt) verursacht hat. reproduzieren kann.

Ein Trick, den ich jedoch regelmäßig anwende, um übermäßiges Log-Spamming zu vermeiden, besteht darin, dass man oft davon ausgehen kann, dass ein Code, der einmal erfolgreich ausgeführt wurde, dies auch später tun wird (keine feste Garantie, aber oft eine vernünftige Annahme).Deshalb beschäftige ich oft einen log_once Eine Art Funktion für granulare Funktionen, um den Mehraufwand zu vermeiden, der durch die Kosten für die Protokollierung bei jedem Aufruf entsteht.

Ich verteile die Protokollausgaben nicht überall (ich könnte es tun, wenn ich die Zeit hätte).Normalerweise reserviere ich sie hauptsächlich für Bereiche, die am gefährlichsten erscheinen:Code, der GLSL-Shader aufruft, z.B.(GPU-Anbieter variieren hier stark in Bezug auf die Leistungsfähigkeit und sogar in der Art und Weise, wie sie den Code kompilieren), Code, der SIMD-Intrinsics verwendet, sehr Low-Level-Code, Code, der zwangsläufig auf betriebssystemspezifischem Verhalten angewiesen ist, Low-Level-Code, der Annahmen über das macht Darstellung von PODs (z. B.:Code, der 8 Bit pro Byte annimmt) – die Art von Fällen, in denen wir ebenfalls viele Behauptungen und Plausibilitätsprüfungen einstreuen und die meisten Komponententests schreiben würden.Normalerweise reicht das aus, und die Protokollierung hat mir viele Male den Hintern gerettet, wo ich sonst ein nicht reproduzierbares Problem angenommen hätte und blinde Versuche unternommen hätte, das Problem zu lösen, was viele Iterationen erforderlich gemacht hätte, um eine Lösung für den einen Benutzer auf der Welt zu finden könnte das Problem reproduzieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top