Wenn Sie die Dinge gut machen möchten, müssen Sie zuerst Ihre Werkzeuge schärfen.
Viele Programmierer können vergessen, wie wichtig es ist, das Verhalten von Anwendungen aufzuzeichnen. Bei der Begegnung mit gleichzeitigen Fehler, die durch hohen Druck in Umgebungen mit mehreren Threaden verursacht werden, können Sie die Bedeutung der Aufzeichnungsprotokolle verstehen.
Einige Leute waren sehr glücklich, diesen Satz dem Code hinzuzufügen:
log.info ("Happy and Carefree Logging");
Er kann nicht einmal erkennen, wie wichtig Anwendungsprotokolle für die Wartung, Abstimmung und Fehleridentifikation sind. Ich denke, SLF4J ist die beste Protokollierungs -API, vor allem, weil sie eine großartige Möglichkeit unterstützt, ein Schema zu injizieren:
log.debug ("Found {} Datensätze Matching Filter: '{}'", Records, Filter);
Für Log4J können Sie dies nur tun:
log.debug ("gefunden" + records + "recordsMatching filter: '" + filter + "'");
Dieses Schreiben ist nicht nur wortreichere und schlechte Lesbarkeit, sondern hat auch ein String -Spleißen, der die Effizienz beeinflusst (wenn diese Ebene keine Ausgabe erfordert).
SLF4J führt die {} -Fection -Funktion vor, und da die String -Spleißung jedes Mal vermieden wird, wird die ToString -Methode nicht aufgerufen, und es müssen nicht isdebugenabled hinzugefügt werden. SLF4J ist eine Anwendung des Erscheinungsmodus, es ist nur eine Fassade. Für eine bestimmte Implementierung empfehle ich das Logback -Framework. Ich habe es bereits einmal angekündigt, anstatt der bereits vollständigen log4j. Es hat viele interessante Funktionen. Im Gegensatz zu Log4J steht es immer noch unter aktiver Entwicklung und Verbesserung.
Ein weiteres Tool, das Sie empfehlen sollten, ist Perf4J:
Perf4J ist zu System.currentTimemillis () als log4j zu System.out.println ()
Genau wie Log4j ist eine bessere Alternative zu System.out.println, Perf4J ist eher ein Ersatz für System.currentTimemillis (). Ich habe Perf4J in ein Projekt eingeführt und beobachtet, wie es unter hohen Lasten funktioniert. Administratoren und Geschäftsanwender sind beide von den wunderschönen Charts, die dieses Gerät zur Verfügung stellt, fassungslos. Wir können jederzeit Leistungsprobleme anzeigen. Perf4J sollte ein spezieller Artikel sein, über den man sprechen kann. Jetzt können Sie sich zuerst den Entwicklerführer ansehen. Es gibt auch einen Ceki Gülcü (Schöpfer von Log4J, SLF4J und Logback-Projekt), der uns eine einfache Möglichkeit bietet, Abhängigkeiten zum Commons-Logging zu entfernen.
Vergessen Sie nicht die Protokollebene
Jedes Mal, wenn Sie eine Zeile von Protokollen hinzufügen möchten, werden Sie überlegen, welche Protokollebene hier verwendet werden sollte? Ungefähr 90% der Programmierer achten diesem Thema nicht viel Aufmerksamkeit. Sie verwenden eine Ebene, um Protokolle aufzuzeichnen, normalerweise entweder Informationen oder Debuggen. Warum?
Das Protokollframework hat im Vergleich zu System zwei Hauptvorteile. Out: Klassifizierung und Ebene. Mit beiden können Sie dauerhaft oder nur bei Fehlerbehebungsfehlern selektiv Protokolle filtern.
Fehler: Ein schwerwiegender Fehler ist aufgetreten und muss sofort behandelt werden. Diese Fehlerebene ist für jedes System unerträglich. Zum Beispiel: Null -Zeiger -Ausnahme, Datenbank ist nicht verfügbar und die Anwendungsfälle von kritischen Pfaden können nicht weiter ausgeführt werden.
WARN: Der nachfolgende Prozess wird fortgesetzt, aber es sollte ernst genommen werden. Tatsächlich hoffe ich, dass es hier zwei Ebenen gibt: Eines ist das offensichtliche Problem mit der Lösung (z. B. "Die aktuellen Daten sind nicht verfügbar, Verwendung von zwischengespeicherten Daten"), und das andere ist das potenzielle Problem und die Vorschläge (z. B. "Das Programm läuft im Entwicklungsmodus" oder "Das Kennwort der Verwaltungskonsole ist nicht sicher genug".
DEBUG: Was Entwickler besorgt sind. Später werde ich darüber sprechen, was die Dinge auf dieser Ebene aufgezeichnet werden sollten.
TRACE: Detailliertere Informationen, nur in der Entwicklungsphase verwendet. Möglicherweise müssen Sie diese Informationen möglicherweise weiterhin innerhalb kurzer Zeit nach dem Start des Produkts auf diese Informationen achten. Diese Protokolldatensätze sind jedoch nur vorübergehend und sollten schließlich ausgeschaltet werden. Es ist schwierig, den Unterschied zwischen Debug und Trace zu unterscheiden, aber wenn Sie eine Protokollzeile hinzufügen und nach der Entwicklung und dem Test löschen, sollte sich das Protokoll auf der Spurenebene befinden.
Die obige Liste ist nur ein Vorschlag. Sie können nach Ihren eigenen Regeln protokollieren, aber es ist am besten, bestimmte Regeln zu haben. Meine persönliche Erfahrung ist: Filterprotokolle nicht auf Codeebene filtern, sondern die richtige Protokollebene verwenden, um die gewünschten Informationen schnell herauszufiltern, wodurch Sie viel Zeit sparen können.
Das Letzte, was zu sagen ist, ist, dass diese berüchtigte*eine bedingte Aussage ermöglichte. Einige Leute fügen dies vor jedem Protokoll hinzu:
if (log.isdebugenabled ()) log.debug ("Ort für Ihren Werbespot");Persönlich denke ich, dass Sie es vermeiden sollten, dem Code dieses chaotische Ding hinzuzufügen. Die Aufführung scheint nicht viel verbessert zu sein (insbesondere nach der Verwendung von SLF4J), was eher einer vorzeitigen Optimierung ähnelt. Finden Sie es nicht ein bisschen überflüssig? Selten wird diese explizite Beurteilungserklärung ausdrücklich benötigt, es sei denn, wir beweisen, dass das Erstellen von Protokollnachrichten selbst zu teuer ist. Andernfalls können Sie sich so viel erinnern, wie Sie sollten, und lassen Sie das Protokollframework darüber Sorgen machen.
Wissen Sie, was Sie aufnehmen?
Nehmen Sie sich jedes Mal, wenn Sie eine Zeile von Protokollen schreiben, einen Moment Zeit, um zu sehen, was Sie in der Protokolldatei drucken. Lesen Sie Ihr Protokoll und finden Sie heraus, wo sich die Ausnahme auszeichnet. Vermeiden Sie zunächst Null -Zeiger -Ausnahmen:
log.debug ("Bearbeitungsanforderung mit ID: {}", Request.getId ());
Haben Sie bestätigt, dass die Anfrage nicht null ist?
Aufnahmesammlungen sind auch eine große Grube. Wenn Sie Hibernate verwenden, um eine Sammlung von Domänenobjekten aus der Datenbank zu erhalten, schreiben Sie sie versehentlich wie folgt: log.debug ("Rückkehrer: {}", Benutzer);
SLF4J ruft nur die TOString -Methode auf, wenn diese Aussage tatsächlich gedruckt wird, natürlich ist dies cool. Wenn jedoch Speicherüberläufe, N+1 -Auswahlprobleme, Thread zu Tode, verzögerte Initialisierungsausnahme, Protokollspeicherplatz ausgeht ... all dies kann auftreten. Der beste Weg ist, nur die ID des Objekts (oder nur die Größe der Sammlung) aufzuzeichnen. Das Sammeln von IDs erfordert jedoch das Aufrufen der GetID -Methode für jedes Objekt, was in Java wirklich keine leichte Aufgabe ist. Groovy hat einen großartigen Expansionsbetreiber (Benutzer*.id). In Java können wir die Commons Beanutils Library verwenden, um zu simulieren:
log.debug ("Rückgabe von Benutzer -IDs: {}", sammeln (Benutzer, "id"));
Auf diese Weise wird wahrscheinlich die Methode des Sammelns implementiert:
Public Static Collection Collection (Sammlung Sammlung, String PropertyName) {return collectionils.collect (Sammlung, neuer BeantopropertyvaluETransformer (PropertyName));}Schließlich wird die ToString -Methode möglicherweise nicht korrekt implementiert oder verwendet.
Um sich zu protokollieren, gibt es für jede Klasse viele Möglichkeiten, ein Zunahme zu erstellen. Es ist am besten, ToStringBuilder zu verwenden, um zu generieren (jedoch nicht die Version seiner Reflexionsimplektion).
Zweitens achten Sie auf Arrays und atypische Sets. Die ToString -Implementierung von Arrays und einige alternative Sammlungen werden möglicherweise nicht die ToString -Methode eines einzelnen Elements nacheinander aufrufen. Die von JDK bereitgestellte Arrays#DeeptoString -Methode kann verwendet werden. Überprüfen Sie die auf sich selbst gedruckten Protokolle, um festzustellen, ob Informationen zur Formatausnahme vorhanden sind.
Nebenwirkungen vermeiden
Der Protokolldruck im Allgemeinen hat keinen großen Einfluss auf die Leistung des Programms. Kürzlich warf ein Freund von mir eine Ausnahme von Hibernate LazyInitializationException auf ein System, das auf einigen speziellen Plattformen ausgeführt wird. Wie Sie möglicherweise vermutet haben, werden einige Protokolldrucke, die dazu führen, dass eine verzögerte Initialisierungssammlungen geladen werden, wenn die Sitzung angeschlossen ist. In diesem Fall wird die Sammlung nicht mehr initialisiert. Wenn Sie diese Kontextinformationen nicht kennen, wie lange dauert es, bis Sie diesen Fehler entdecken.
Ein weiterer Nebeneffekt ist, dass es die Laufgeschwindigkeit des Programms beeinflusst. Eine schnelle Antwort auf diese Frage: Wenn die Protokolle zu viel gedruckt werden oder das ToString- und String -Spleißen nicht korrekt verwendet werden, wirkt sich der Protokolldruck negativ auf die Leistung aus. Wie groß kann es sein? Nun, ich habe alle 15 Minuten ein Programm neu gestartet, weil zu viele Protokolle dazu führen, dass Threads verhungern. Dies ist der Nebeneffekt! Nach meiner Erfahrung ist das Drucken hundert Megabyte in einer Stunde fast die Obergrenze.
Wenn der Geschäftsprozess aufgrund von Ausnahmen von Protokolldruckausnahmen abgebrochen wird, wird dieser Nebeneffekt natürlich großartig sein. Ich sehe oft Leute, die dies schreiben, um dies zu vermeiden:
try {log.trace ("id =" + request.getUser (). getId () + "Zugriffe" + Manager.getPage (). getUrl (). toString ())} catch (nullPointerexception e) {}Dies ist ein echtes Stück Code, aber um die Welt mehr gereinigt zu werden, schreiben Sie ihn bitte nicht so.
Klar beschreiben
Jeder Protokolldatensatz enthält Daten und Beschreibung. Schauen Sie sich dieses Beispiel an:
log.debug ("message verarbeitet"); log.debug (message.getJmsMessageId ()); log.debug ("Nachricht mit ID '{}' verarbeitet", message.getJMSmessageId ()); Welche Art von Protokoll sehen Sie, wenn Fehler bei der Fehlerbehebung in einem unbekannten System vorhanden sind? Vertrauen Sie mir, diese Beispiele sind häufig. Es gibt auch einen negativen Modus:
if (Message Instance von TextMessage)
// ...
anders
log.warn ("unbekannter Nachrichtentyp");
Ist es schwierig, diesem Warnprotokoll Nachrichtentypen, Nachrichten -IDs usw. hinzuzufügen? Ich weiß, dass ein Fehler aufgetreten ist, aber was ist das? Was sind die Kontextinformationen?
Das dritte negative Beispiel ist "Magic Log". Ein echtes Beispiel: Viele Programmierer im Team wissen, dass 3 ≥ Zahlen folgen! Die Nummer gefolgt von einer # Nummer, gefolgt von einem Pseudo-Random-Nummer-Protokoll bedeutet "Die Nachricht mit ID XYZ wurde empfangen". Niemand möchte dieses Protokoll ändern. Wenn jemand die Tastatur tippte und eine einzigartige Zeichenfolge "&&&!#" Ausgewählt hätte, würde er schnell die Informationen finden, die er wollte.
Das Ergebnis ist, dass die gesamte Protokolldatei wie eine große Zeichenfolge von zufälligen Zeichen aussieht. Einige Leute können nicht anders, als sich zu fragen, ob dies ein Perl -Programm ist.
Protokolldateien sollten lesbar, klar und selbst beschrieben sein. Verwenden Sie keine magischen Zahlen, Aufzeichnungswerte, Zahlen, IDs und ihren Kontext. Notieren Sie die verarbeiteten Daten und ihre Bedeutung. Notieren Sie, was das Programm tut. Ein gutes Protokoll sollte ein gutes Dokument des Programmcodes sein.
Habe ich erwähnt, dass ich kein Passwort drucken und persönliche Informationen habe? Ich glaube, es gibt keinen so dummen Programmierer.
Passen Sie Ihr Format an
Das Protokollformat ist ein sehr nützliches Tool, das dem Protokoll wertvolle Kontextinformationen hinzufügt. Sie sollten jedoch klar darüber nachdenken, welche Art von Informationen in Ihrem Format enthalten sind. Beispielsweise ist es bedeutungslos, Daten in Protokollen aufzuzeichnen, die in jedem Stundenzyklus geschrieben wurden, da Ihr Protokollname diese Informationen bereits enthält. Wenn Sie den Threadnamen nicht aufzeichnen, wenn zwei Threads parallel funktionieren, können Sie die Threads nicht durch die Protokolle verfolgen - die Protokolle haben sich überlagert. In einer einzel-thread-Anwendung ist es in Ordnung, dies zu tun, aber das gehört bereits der Vergangenheit an.
Aus meiner Erfahrung sollte das ideale Protokollformat (außer den Protokollinformationen selbst natürlich selbst) enthalten: Aktuelle Uhrzeit (kein Datum, Millisekunden -Präzision), Protokollebene, Threadname, einfacher Protokollname (nicht mit vollem Namen) und Nachrichten. Im Logback sieht es so aus:
<Appender name = "stdout"> <Encoder> <Muster>%d {hh: mm: ss.sss}%-5Level [%Thread] [%Logger {0}]%m%n </muster> </ccoder> </Appender>Dateinamen, Klassennamen, Zeilennummern, müssen nicht aufgeführt werden, obwohl sie nützlich zu sein scheinen. Ich habe auch leere Protokollierung im Code gesehen:
log.info (""); Da der Programmierer der Ansicht ist, dass die Zeilennummer Teil des Protokollformats ist und er weiß, dass die Benutzer authentifiziert wurde, wenn die leere Protokollnachricht in Zeile 67 der Datei angezeigt wird. Darüber hinaus wirken Namensnamen oder Zeilennummern der Unterrichtsnamennamen einen großen Einfluss auf die Leistung.
Eine fortgeschrittenere Funktion des Protokollierungsrahmens ist der zugeordnete diagnostische Kontext. MDC ist nur eine Karte, die lokal zu fädeln ist. Sie können alle Schlüsselwertpaare in diese Karte einfügen, damit alle Protokolldatensätze dieses Threads entsprechende Informationen von dieser Karte als Teil des Ausgabeformats erhalten können.
Notieren Sie die Parameter und Rückgabewerte der Methode
Wenn Sie in der Entwicklungsphase einen Fehler finden, verwenden Sie normalerweise einen Debugger, um den spezifischen Grund zu verfolgen. Nehmen wir jetzt an, Sie werden den Debugger nicht mehr verwenden. Da dieser Fehler beispielsweise vor einigen Tagen in der Umgebung des Benutzers erschien, können Sie nur einige Protokolle erhalten. Was können Sie daraus herausfinden?
Wenn Sie dem einfachen Prinzip des Druckens für jede Methode ein- und aus -Parameter folgen, benötigen Sie überhaupt keinen Debugger. Natürlich kann jede Methode auf externe Systeme, Block-, Wartezeiten usw. zugreifen, und diese sollten berücksichtigt werden. Beziehen Sie sich einfach auf das folgende Format:
public String printDocument (Dokument doc, modus modus) {log.debug ("Eingabe von printDocument (doc = {}, modus = {})", doc, modus); String id = ...; // langwieriger Druckvorgang log.debug ("printDocument (): {}", id); return id;}Da Sie die Protokolle am Anfang und am Ende der Methode protokollieren, können Sie manuell ineffiziente Codes finden und sogar Ursachen erkennen, die Deadlocks und Hunger verursachen können - Sie müssen nur sehen, ob es kein "Verlassen" nach "Eingingen" gibt. Wenn die Bedeutung Ihres Methodennamens klar ist, ist es eine angenehme Sache, das Protokoll zu löschen. In ähnlicher Weise ist die Analyse von Ausnahmen einfacher, da Sie wissen, was Sie bei jedem Schritt tun. Wenn es im Code viele Methoden zum Aufzeichnen gibt, können Sie AOP -Abschnitte verwenden, um ihn zu vervollständigen. Dies reduziert den doppelten Code, aber Sie müssen bei der Verwendung sehr vorsichtig sein. Wenn Sie nicht vorsichtig sind, kann dies zu einer großen Menge an Protokollausgabe führen.
Die am besten geeigneten Ebenen für diese Art von Protokoll sind Debug und Spur. Wenn Sie feststellen, dass eine Methode zu häufig aufgerufen wird und die Aufzeichnung ihres Protokolls die Leistung beeinflussen kann, müssen Sie nur ihre Protokollebene senken oder das Protokoll direkt löschen (oder nur eine der gesamten Methodenaufrufe?). Zu viele Protokolle sind jedoch besser als weniger. Stellen Sie sich die Protokollierung als Unit -Tests vor, Ihr Code sollte mit Protokollen behandelt werden, genau wie die Einheitstests überall sind. Kein Teil des Systems erfordert überhaupt keine Protokolle. Denken Sie daran, manchmal müssen Sie wissen, ob Ihr System ordnungsgemäß funktioniert, und Sie können nur die Protokolle anzeigen, die den Bildschirm ständig überfluten.
Externe Systeme beobachten
Dieser Vorschlag unterscheidet sich etwas von der vorherigen: Wenn Sie mit einem externen System kommunizieren, denken Sie daran, die Ausgangs- und Lesendaten Ihres Systems aufzuzeichnen. Die Systemintegration ist eine Aufgabe, und die Diagnose von Problemen zwischen zwei Anwendungen (vorstellen Sie verschiedene Unternehmen, Umgebungen, technische Teams) sind besonders schwierig. Kürzlich haben wir festgestellt, dass die Aufzeichnung vollständiger Nachrichteninhalte, einschließlich der SOAP- und HTTP -Header von Apache CXF, während der Integrations- und Testphase des Systems sehr effektiv ist.
Dies ist teuer, und wenn dies die Leistung beeinflusst, können Sie das Protokoll nur ausschalten. Aber auf diese Weise kann Ihr System sehr schnell laufen und schnell hängen, sodass Sie nichts dagegen tun können? Bei der Integration in externe Systeme können Sie nur besonders vorsichtig sein und bereit sein, etwas Overhead zu opfern. Wenn Sie das Glück haben und die Systemintegration von der ESB behandelt wird, ist es am besten, die Anfrage und Antwort im Bus aufzunehmen. Sie können auf diese Protokollkomponente des Maultiers verweisen.
Manchmal bestimmt die Menge an Daten, die mit externen Systemen ausgetauscht werden, dass es für Sie unmöglich ist, alles aufzuschreiben. Andererseits ist es am besten, alles während der Testphase und der frühen Freisetzungstadien im Protokoll im Protokoll zu halten und bereit zu sein, die Leistung zu opfern. Dies kann durch Anpassen der Protokollebene erfolgen. Schauen Sie sich die folgenden Tipps an:
Sammlung <Neger> requestIds = // ... if (log.isdebugenabled ()) log.debug ("Verarbeitungs -IDs: {}", RequestIDs); sonst log.info ("Verarbeitungs -IDS -Größe: {}", RequestIds.Size ()); Wenn dieser Logger auf der Debug -Ebene konfiguriert ist, druckt er die vollständige Sammlung von Anforderungs -IDs. Wenn es so konfiguriert ist, dass Informationen Informationen drucken, gibt es nur die Größe des Satzes aus. Sie können mich fragen, ob ich den Zustand des Issinfoenable vergessen habe. Weitere Informationen finden Sie im zweiten Vorschlag. Eine andere Sache, die hier erwähnenswert ist, ist, dass die IDs nicht null sein kann. Obwohl es normalerweise unter Debugg als Null drucken kann, ist es ein großer Nullzeiger, wenn es als Info konfiguriert wird. Erinnerst du dich an die im 4. Vorschlag erwähnten Nebenwirkungen?
Korrekte Protokollierungsausnahmen
Zunächst keine Ausnahmen protokollieren, lassen Sie das Framework oder Container dies tun. Natürlich gibt es eine Ausnahme: Wenn Sie Ausnahmen (RMI, EJB usw.) von einem Remote -Dienst werfen, werden die Ausnahmen serialisiert, um sicherzustellen, dass sie an den Kunden zurückgegeben werden können (Teil der API). Andernfalls erhält der Client einen NoclassDeffoundError oder eine andere seltsame Ausnahme anstelle einer echten Fehlermeldung.
Die Ausnahmeaufzeichnung ist eine der wichtigsten Aufgaben bei der Protokollierung, aber viele Programmierer verwenden die Protokollierung, um Ausnahmen zu bewältigen. Normalerweise geben sie nur den Standardwert zurück (normalerweise null, 0 oder leerer Zeichenfolge), und tun so, als wäre nichts passiert. Manchmal zeichnen sie zuerst die Ausnahme auf, wickeln dann die Ausnahme ein und werfen sie dann raus:
log.Error ("IO -Ausnahme", e); neue CustomException (e) werfen;Auf diese Weise werden die Stapelinformationen normalerweise zweimal gedruckt, da die Orte, an denen die Ausnahme von Mycustomexception erwischt wird, erneut gedruckt werden. Protokollieren Sie Datensätze oder wickeln Sie sie ein und werfen Sie sie aus, verwenden Sie sie nicht gleichzeitig, andernfalls sehen Ihre Protokolle verwirrend aus.
Was ist, wenn wir uns wirklich protokollieren wollen? Aus irgendeinem Grund (vermutlich nicht APIs und Dokumentation lesen?) Ist ich ungefähr die Hälfte der Protokollierung für falsch. Machen Sie einen kleinen Test, welcher der folgenden Protokollanweisungen kann Nullzeigerausnahmen korrekt drucken?
Versuchen Sie {Integer x = null; ++ x;} catch (Ausnahme e) {log.Error (e); // a log.Error (e, e); // B log.Error ("" + e); // c log.Error (e.tostring ()); // D log.Error (e.getMessage ()); // e log.Error (null, e); // f log.error ("", e); // g log.error ("{}", e); // H log.Error ("{}", e.getMessage ()); // I log.Error ("Fehler beim Lesen von Konfigurationsdateien:" + e); // j log.Error ("Fehlerlesenkonfigurationsdatei:" + e.getMessage ()); // k log.Error ("Fehlerlesenkonfigurationsdatei", e); // l}Es ist seltsam, dass nur G und L (das ist besser) Recht! A und B werden überhaupt nicht unter SLF4J zusammengestellt. Andere werfen die Stapel -Trace -Informationen weg oder drucken falsche Informationen. Zum Beispiel druckt E nichts aus, da die Null -Zeiger -Ausnahme selbst keine Ausnahmeinformationen enthält und die Stapelinformationen nicht ausgedruckt sind. Denken Sie daran, der erste Parameter ist normalerweise Textinformationen über den Fehler selbst. Schreiben Sie keine Ausnahmeinformationen darin. Nach dem Drucken des Protokolls vor den Stapelinformationen wird automatisch herausgekommen. Wenn Sie dies jedoch drucken möchten, müssen Sie natürlich die Ausnahme an den zweiten Parameter übergeben.
Protokolle sollten lesbar und leicht zu analysieren sein
Jetzt gibt es zwei Gruppen von Benutzern, die sich für Ihre Protokolle interessieren: Wir Menschen (ob Sie zustimmen oder nicht, die Codierer sind hier) und Computer (normalerweise von Systemadministratoren verfasste Shell -Skripte). Protokolle sollten für beide Benutzer zu verstehen geeignet sein. Wenn jemand das Protokoll Ihres Programms hinter sich schaut und Folgendes sieht:
Dann hast du meinen Rat definitiv nicht gefolgt. Protokolle sollten so einfach zu lesen und zu verstehen wie Code.
Wenn Ihr Programm auf der anderen Seite pro Stunde eine halbe GB Protokolle generiert, kann niemand oder ein grafischer Texteditor sie beenden. Zu dieser Zeit kamen unsere alten Typen Grep, Sed und Awk, als sie auf dem Feld kamen. Wenn möglich, ist es am besten, dass die Protokolle, die Sie aufzeichnen, sowohl dem Computer klar machen. Formatieren Sie keine Zahlen, verwenden Sie einige Formate, die regelmäßig übereinstimmen usw. Wenn dies nicht möglich ist, drucken Sie die Daten in zwei Formaten aus:
log.debug ("Anfrage ttl auf: {} ({})", neues Datum (ttl), ttl); // Anfrage TTL SET auf: Mi 28 20:14:12 CEST 2010 (1272478452437) endgültige String -Dauer = DurationForMatils. {} ms ({}) ", DurationMillis, Dauer); // Importing DAS IM: 123456789MS (1 Tag 10 Stunden 17 Minuten 36 Sekunden)Computer sehen "MS After 1970 Epoche". Ein solches Zeitformat wird es Ihnen danken, während die Leute gerne so etwas wie "1 Tag 10 Stunden 17 Minuten 36 Sekunden" sehen.
Kurz gesagt, das Journal kann auch so elegant wie ein Gedicht geschrieben werden, wenn Sie bereit sind, darüber nachzudenken.
Das obige ist eine Sammlung von Informationen zum Ausgangsformat der Java -Protokollanpassung. Interessierte Freunde können sich darauf beziehen.