JavaRush /Java-Blog /Random-DE /Einloggen in Java: Was, wie, wo und womit?

Einloggen in Java: Was, wie, wo und womit?

Veröffentlicht in der Gruppe Random-DE
Hallo zusammen, JavaRush-Community! Heute sprechen wir über Java-Logging:
  1. Was ist das, warum ist das so? In welchen Fällen ist die Verwendung besser, in welchen nicht?
  2. Welche unterschiedlichen Implementierungen der Protokollierung gibt es in Java und was sollten wir mit dieser Vielfalt tun?
  3. Protokollierungsstufen. Lassen Sie uns besprechen, was ein Appender ist und wie man ihn richtig konfiguriert.
  4. Protokollierungsknoten und wie man sie richtig konfiguriert, damit alles so funktioniert, wie wir es wollen.
Dieses Material richtet sich an ein breites Publikum. logger.info(“log something”); Es wird sowohl denen klar sein, die sich gerade erst mit Java vertraut machen, als auch denen, die bereits arbeiten, es aber erst mit Let's Go! herausgefunden haben.

Warum ist eine Protokollierung erforderlich?

Schauen wir uns reale Fälle an, in denen eine Protokollierung das Problem lösen würde. Hier ist ein Beispiel aus meiner Arbeit. Es gibt Anwendungspunkte, die in andere Dienste integriert werden können. Ich verwende die Protokollierung dieser Punkte als „Alibi“ : Wenn die Integration nicht funktioniert, lässt sich leicht herausfinden, von welcher Seite das Problem stammt. Es empfiehlt sich außerdem, wichtige Informationen, die in der Datenbank gespeichert werden, zu protokollieren. Zum Beispiel das Erstellen eines Administratorbenutzers. Genau das wäre gut zu protokollieren.

Java-Protokollierungstools

Protokollierung: Was, wie, wo und womit?  - 2Zu den bekannten Lösungen für die Protokollierung in Java gehören:
  • log4j
  • JUL – java.util.logging
  • JCL – Jakarta-Commons-Protokollierung
  • Wieder anmelden
  • SLF4J – einfache Protokollierungsfassade für Java
Werfen wir einen kurzen Blick auf jeden von ihnen und nehmen im praktischen Teil des Materials die Verbindung Slf4j - log4j als Grundlage . Das mag jetzt seltsam erscheinen, aber keine Sorge: Am Ende des Artikels wird alles klar sein.

System.err.println

Zunächst gab es natürlich System.err.println (Ausgabe auf der Konsole aufzeichnen). Es wird immer noch verwendet, um während des Debuggens schnell ein Protokoll abzurufen. Über irgendwelche Einstellungen muss hier natürlich nicht gesprochen werden, also merken wir uns das einfach und machen weiter.

Log4j

Hierbei handelte es sich bereits um eine vollwertige Lösung, die aus den Bedürfnissen der Entwickler heraus entstand. Es stellte sich heraus, dass es ein wirklich interessantes Werkzeug war. Aufgrund verschiedener Umstände gelangte diese Lösung nie in das JDK, was die gesamte Community sehr verärgerte. log4j verfügte über Konfigurationsoptionen, sodass die Protokollierung in einem Paket aktiviert com.example.typeund in einem Unterpaket deaktiviert werden konnte com.example.type.generic. Dadurch war es möglich, schnell zu trennen, was protokolliert werden musste und was nicht. Hierbei ist zu beachten, dass es zwei Versionen von log4j gibt: 1.2.x und 2.x.x, die nicht miteinander kompatibel sind . log4j hat ein Konzept wie appender hinzugefügt , also ein Tool zum Aufzeichnen und Layouten von Protokollen – Protokollformatierung. Dadurch können Sie nur das aufzeichnen, was Sie benötigen und wie Sie es benötigen. Wir werden etwas später mehr über Appender sprechen.

JUL – java.util.logging

Einer der Hauptvorteile ist die Lösung – JUL ist im JDK (Java Development Kit) enthalten. Leider wurde bei der Entwicklung nicht das beliebte log4j als Grundlage genommen, sondern eine Lösung von IBM, die die Entwicklung beeinflusste. Tatsächlich gibt es im Moment JUL, aber niemand nutzt es. Aus dem „Mittelmäßig“: In JUL unterscheiden sich die Protokollierungsstufen von denen in Logback, Log4j, Slf4j, und dies verschlechtert das Verständnis zwischen ihnen. Das Erstellen eines Loggers ist mehr oder weniger ähnlich. Dazu müssen Sie Folgendes importieren:
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
Der Klassenname wird gezielt übergeben, um zu wissen, woher die Protokollierung kommt. Seit Java 8 ist die Übergabe möglich Supplier<String>. Dies hilft, eine Zeichenfolge nur dann zu zählen und zu erstellen, wenn sie wirklich benötigt wird, und nicht jedes Mal, wie es zuvor der Fall war. Erst mit der Veröffentlichung von Java 8 lösten die Entwickler wichtige Probleme, wodurch JUL wirklich nutzbar wurde. Nämlich Methoden mit Argumenten Supplier<String> msgSupplierwie unten gezeigt:
public void info(Supplier<String> msgSupplier) {
   log(Level.INFO, msgSupplier);
}

JCL – Jakarta-Commons-Protokollierung

Aufgrund der Tatsache, dass es lange Zeit keinen Industriestandard für die Protokollierung gab und es eine Zeit gab, in der viele Leute ihren eigenen benutzerdefinierten Logger erstellten, beschlossen sie, JCL zu veröffentlichen – einen gemeinsamen Wrapper, der anderen vorgezogen wurde. Warum? Wenn dem Projekt einige Abhängigkeiten hinzugefügt wurden, konnten sie einen anderen Logger als den Logger im Projekt verwenden. Aus diesem Grund wurden sie transitiv in das Projekt eingefügt, was beim Versuch, alles zusammenzusetzen, zu echten Problemen führte. Leider war die Funktionalität des Wrappers sehr dürftig und es wurden keine Ergänzungen vorgenommen. Es wäre wahrscheinlich praktisch, wenn jeder JCL für seine Arbeit verwenden würde. Aber in Wirklichkeit hat es nicht so geklappt, daher ist der Einsatz von JCL im Moment keine gute Idee.

Wieder anmelden

Wie steinig ist der Weg von Open-Source ... Logback wurde vom gleichen Entwickler wie log4j geschrieben, um einen Nachfolger dafür zu erstellen. Die Idee war die gleiche wie bei log4j. Die Unterschiede waren folgende beim Logback:
  • verbesserte Leistung;
  • native Unterstützung für slf4j hinzugefügt;
  • Die Filtermöglichkeit wurde erweitert.
Standardmäßig erfordert die Protokollierung keine Einstellungen und zeichnet alle Protokolle ab der DEBUG-Ebene auf. Wenn eine Konfiguration erforderlich ist, kann dies über die XML-Konfiguration erfolgen:
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
    <root level="info">
        <appender-ref ref="FILE" />
    </root>
</configuration>

SLF4J – einfache Protokollierungsfassade für Java

Um 2006 verließ einer der Gründerväter von log4j das Projekt und erstellte slf4j – Simple Logging Facade for Java – einen Wrapper um log4j, JUL, common-loggins und logback. Wie Sie sehen können, hat der Fortschritt den Punkt erreicht, an dem ein Wrapper über dem Wrapper erstellt wurde ... Darüber hinaus ist er in zwei Teile unterteilt: die API, die in der Anwendung verwendet wird, und die Implementierung, die als hinzugefügt wird separate Abhängigkeiten für jede Art der Protokollierung. Zum Beispiel, slf4j-log4j12.jar, slf4j-jdk14.jar. Es reicht aus, die richtige Implementierung anzuschließen, und schon funktioniert das gesamte Projekt damit. Slf4j unterstützt alle neuen Funktionen wie String-Formatierung für die Protokollierung. So ein Problem gab es schon einmal. Nehmen wir an, es gibt einen Protokolleintrag:
log.debug("User " + user + " connected from " + request.getRemoteAddr());
userAufgrund der Zeichenfolgenverkettung findet im Objekt eine implizite Konvertierung user.toString()statt, die Zeit in Anspruch nimmt und das System verlangsamt. Und alles ist in Ordnung, wenn wir die Anwendung debuggen. Probleme treten auf, wenn die Protokollierungsebene für diese Klasse INFO oder höher ist. Das heißt, dieses Protokoll sollte nicht aufgeschrieben werden und es sollte auch keine Zeichenfolgenverkettung durchgeführt werden. Theoretisch hätte dies von der Protokollierungsbibliothek selbst entschieden werden müssen. Darüber hinaus stellte sich heraus, dass dies das größte Problem der ersten Version von log4j war. Sie lieferten keine normale Lösung, sondern schlugen vor, es so zu machen:
if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
Das heißt, anstelle einer Protokollzeile wurde vorgeschlagen, 3 (!) zu schreiben. Durch die Protokollierung sollten Änderungen am Code minimiert werden, und drei Zeilen widersprachen eindeutig dem allgemeinen Ansatz. slf4j hatte keine Kompatibilitätsprobleme mit dem JDK und der API, sodass sofort eine schöne Lösung entstand:
log.debug("User {} connected from {}", user, request.getRemoteAddr());
Dabei {}bezeichnen Einfügungen von Argumenten, die in der Methode übergeben werden. Das heißt, das erste {}entspricht user, das zweite {}- request.getRemoteAddr(). Aus diesem Grund kann diese Nachricht nur dann zu einer einzigen Nachricht verkettet werden, wenn die Protokollierungsstufe die Protokollierung zulässt. Danach erfreute sich SJF4J schnell wachsender Beliebtheit und ist derzeit die beste Lösung. Daher betrachten wir die Protokollierung am Beispiel eines Bundles slf4j-log4j12.

Was muss protokolliert werden

Natürlich sollte man nicht alles protokollieren. Manchmal ist dies unnötig und sogar gefährlich. Wenn man beispielsweise die persönlichen Daten einer Person verpfändet und diese irgendwie ans Licht kommen, wird es vor allem bei westlich orientierten Projekten zu echten Problemen kommen. Aber es gibt auch etwas, das protokolliert werden muss :
  1. Beginn/Ende der Bewerbung. Wir müssen wissen, dass die Anwendung tatsächlich wie erwartet gestartet und wie erwartet beendet wurde.
  2. Sicherheitsfragen. Hier wäre es sinnvoll, Versuche zum Erraten von Passwörtern, Anmeldungen wichtiger Benutzer usw. zu protokollieren.
  3. Einige Anwendungszustände . Beispielsweise der Übergang von einem Zustand in einen anderen in einem Geschäftsprozess.
  4. Einige Informationen zum Debuggen mit einem entsprechenden Protokollierungsniveau.
  5. Einige SQL-Skripte. Es gibt reale Fälle, in denen dies erforderlich ist. Auch hier lassen sich durch geschickte Anpassung der Pegel hervorragende Ergebnisse erzielen.
  6. Ausgeführte Threads (Thread) können in Fällen protokolliert werden, in denen der korrekte Betrieb überprüft wird.

Beliebte Protokollierungsfehler

Es gibt viele Nuancen, aber hier sind ein paar häufige Fehler:
  1. Übermäßige Protokollierung. Sie sollten nicht jeden Schritt protokollieren, der theoretisch wichtig sein könnte. Es gibt eine Regel: Protokolle dürfen die Leistung nicht um mehr als 10 % belasten. Andernfalls kommt es zu Performance-Problemen.
  2. Protokollierung aller Daten in einer Datei. Dies wird das Lesen/Schreiben ab einem bestimmten Punkt sehr erschweren, ganz zu schweigen davon, dass es auf bestimmten Systemen Dateigrößenbeschränkungen gibt.
  3. Verwendung falscher Protokollierungsstufen. Jede Protokollierungsebene hat klare Grenzen und sollte respektiert werden. Wenn die Grenze unklar ist, können Sie sich auf die zu verwendende Ebene einigen.

Protokollierungsstufen

x: Sichtbar
TÖDLICH FEHLER WARNEN DIE INFO DEBUGGEN VERFOLGEN ALLE
AUS
TÖDLICH X
FEHLER X X
WARNEN X X X
DIE INFO X X X X
DEBUGGEN X X X X X
VERFOLGEN X X X X X X
ALLE X X X X X X X
Was sind Protokollierungsstufen? Um die Protokolle irgendwie einordnen zu können, war es notwendig, bestimmte Bezeichnungen und Unterscheidungen zu vergeben. Zu diesem Zweck wurden Protokollierungsstufen eingeführt. Die Stufe wird in der Anwendung eingestellt. Gehört ein Eintrag zu einer Ebene unterhalb der angegebenen, wird er nicht in das Protokoll eingetragen. Wir verfügen beispielsweise über Protokolle, die zum Debuggen der Anwendung verwendet werden. Im normalen Produktionsbetrieb (wenn die Anwendung bestimmungsgemäß verwendet wird) werden solche Protokolle nicht benötigt. Daher ist der Protokollierungsaufwand höher als beim Debuggen. Schauen wir uns die Ebenen am Beispiel von log4j an. Andere Lösungen außer JUL verwenden dieselben Ebenen. Hier sind sie in absteigender Reihenfolge:
  • AUS: Es werden keine Protokolle geschrieben, alle werden ignoriert.
  • FATAL: ein Fehler, nach dem die Anwendung nicht mehr funktionieren kann und gestoppt wird, z. B. JVM-Fehler wegen unzureichendem Speicher;
  • FEHLER: Die Fehlerquote, wenn Probleme gelöst werden müssen. Der Fehler stoppt nicht die gesamte Anwendung. Andere Abfragen funktionieren möglicherweise ordnungsgemäß.
  • WARN: Zeigt Protokolle an, die eine Warnung enthalten. Es ist eine unerwartete Aktion aufgetreten. Das System hat sich trotzdem dagegen gewehrt und die Anfrage abgeschlossen.
  • INFO: ein Protokoll, das wichtige Aktionen in der Anwendung aufzeichnet. Dies sind keine Fehler, dies sind keine Warnungen, dies sind erwartete Aktionen des Systems;
  • DEBUG: Protokolle, die zum Debuggen der Anwendung benötigt werden. Um sicherzustellen, dass das System genau das tut, was von ihm erwartet wird, oder um die Aktion des Systems zu beschreiben: „Methode1 hat begonnen zu arbeiten“;
  • TRACE: Protokolle mit niedrigerer Priorität zum Debuggen, mit der niedrigsten Protokollierungsstufe;
  • ALL: Ebene, auf der alle Protokolle des Systems aufgezeichnet werden.
Es stellt sich heraus, dass, wenn die INFO-Protokollierungsebene an einer Stelle in der Anwendung aktiviert ist, alle Ebenen protokolliert werden, angefangen bei INFO bis hin zu FATAL. Wenn die Protokollierungsstufe FATAL ist, werden nur Protokolle mit dieser Stufe aufgezeichnet.

Protokolle aufzeichnen und senden: Appender

Wir betrachten diesen Prozess am Beispiel von log4j: Er bietet zahlreiche Möglichkeiten zum Aufzeichnen/Versenden von Protokollen:
  • zum Schreiben in eine Datei - Lösung DailyRollingFileAppender ;
  • um Daten in die Anwendungskonsole zu empfangen - ConsoleAppender ;
  • um Protokolle in die Datenbank zu schreiben - JDBCAppender ;
  • zur Steuerung der Übertragung über TCP/IP - TelnetAppender ;
  • um sicherzustellen, dass die Protokollierung die Leistung nicht beeinträchtigt – AsyncAppender .
Es gibt mehrere andere Implementierungen: Die vollständige Liste finden Sie hier . Sollte der erforderliche Appender nicht verfügbar sein, ist das übrigens kein Problem. Sie können Ihren eigenen Appender schreiben, indem Sie die Appender- Schnittstelle implementieren , die nur log4j akzeptiert.

Protokollierungsknoten

Für die Demonstration verwenden wir die slf4j-Schnittstelle und die Implementierung von log4j. Das Erstellen eines Loggers ist sehr einfach: Sie müssen Folgendes in eine Klasse namens schreiben MainDemo, in der die Protokollierung durchgeführt wird:
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
Dadurch wird ein Logger für uns erstellt. Um einen Protokolleintrag vorzunehmen, können Sie viele Methoden verwenden, die angeben, auf welcher Ebene die Einträge vorgenommen werden. Zum Beispiel:
logger.trace("Method 1 started with argument={}", argument);
logger.debug("Database updated with script = {}", script);
logger.info("Application has started on port = {}", port);
logger.warn("Log4j didn't find log4j.properties. Please, provide them");
logger.error("Connection refused to host = {}", host);
Auch wenn wir die Klasse übergeben, wird am Ende der vollständige Name der Klasse mit Paketen aufgeschrieben. Dies geschieht, damit Sie die Protokollierung anschließend in Knoten aufteilen und für jeden Knoten eine Protokollierungsebene und einen Appender konfigurieren können. Zum Beispiel der Name der Klasse: com.github.romankh3.logginglecture.MainDemo- Darin wurde ein Logger erstellt. Und so kann es in Protokollierungsknoten unterteilt werden. Der Hauptknoten ist der Null- RootLogger . Dies ist der Knoten, der alle Protokolle der gesamten Anwendung empfängt. Der Rest lässt sich wie folgt darstellen: Protokollierung: Was, wie, wo und womit?  - 4Appender konfigurieren ihre Arbeit gezielt auf Logging-Knoten. Am Beispiel von log4j.properties schauen wir uns nun an, wie man sie konfiguriert.

Schritt-für-Schritt-Einrichtung von Log4j.properties

Nun richten wir Schritt für Schritt alles ein und schauen, was sich machen lässt:
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
Diese Zeile besagt, dass wir einen CONSOLE-Appender registrieren, der die org.apache.log4j.ConsoleAppender-Implementierung verwendet. Dieser Appender schreibt Daten in die Konsole. Als nächstes registrieren wir einen weiteren Appender, der in eine Datei schreibt:
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
Es ist wichtig zu beachten, dass die Appender noch konfiguriert werden müssen. Sobald wir bereits Appender registriert haben, können wir bestimmen, welche Protokollierungsstufe in den Knoten vorhanden sein wird und welche Appender verwendet werden.

log4j.rootLogger=DEBUG, KONSOLE, DATEI

  • log4j.rootLogger bedeutet, dass wir den Hauptknoten konfigurieren, der alle Protokolle enthält;
  • nach dem Gleichheitszeichen gibt das erste Wort an, auf welcher Ebene und höher die Protokolle aufgezeichnet werden (in unserem Fall ist dies DEBUG);
  • dann werden nach dem Komma alle Appender angezeigt, die verwendet werden.
Um einen bestimmten Protokollierungsknoten zu konfigurieren, müssen Sie den folgenden Eintrag verwenden:
log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
wo log4j.logger.es zum Konfigurieren eines bestimmten Knotens verwendet wird, in unserem Fall. com.github.romankh3.logginglecture. Und jetzt reden wir über das Einrichten des CONSOLE-Appenders:
# CONSOLE appender customisation
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] : %c:%L : %m%n
Hier sehen wir, dass wir die Ebene festlegen können, ab der der Appender verarbeiten soll. Reale Situation: Eine Nachricht mit der Info-Stufe wurde vom Protokollierungsknoten empfangen und an den ihr zugewiesenen Appender weitergeleitet, aber der Appender mit der Warnstufe und höher hat dieses Protokoll akzeptiert, aber nichts damit gemacht. Als Nächstes müssen Sie entscheiden, welche Vorlage in der Nachricht enthalten sein soll. Im Beispiel verwende ich PatternLayout, aber es gibt viele Lösungen. Sie werden in diesem Artikel nicht offengelegt. Ein Beispiel für die Einrichtung eines FILE-Appenders:
# File appender customisation
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=./target/logging/logging.log
log4j.appender.FILE.MaxFileSize=1MB
log4j.appender.FILE.threshold=DEBUG
log4j.appender.FILE.MaxBackupIndex=2
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[ %-5p] - %c:%L - %m%n
Hier können Sie konfigurieren, in welche Datei die Protokolle geschrieben werden, wie aus ersichtlich ist
log4j.appender.FILE.File=./target/logging/logging.log
Die Aufnahme wird in die Datei verschoben logging.log. Um Probleme mit der Dateigröße zu vermeiden, können Sie das Maximum festlegen: in diesem Fall 1 MB. MaxBackupIndex – gibt an, wie viele solcher Dateien vorhanden sein werden. Wenn mehr als diese Anzahl erstellt wird, wird die erste Datei gelöscht. Um ein reales Beispiel für die Konfiguration der Protokollierung anzusehen, können Sie das offene Repository auf GitHub aufrufen .

Konsolidieren wir das Ergebnis

Versuchen Sie, alles Beschriebene selbst zu tun:
  • Erstellen Sie Ihr eigenes Projekt ähnlich dem im obigen Beispiel.
  • Wenn Sie über Kenntnisse in der Verwendung von Maven verfügen, werden wir es verwenden. Wenn nicht, finden Sie hier einen Link zu einem Artikel, der beschreibt, wie Sie die Bibliothek verbinden.

Fassen wir es zusammen

  1. Wir haben darüber gesprochen, welche Lösungen es in Java gibt.
  2. Fast alle bekannten Protokollierungsbibliotheken wurden unter der Kontrolle einer Person geschrieben :D
  3. Wir haben gelernt, was protokolliert werden muss und was nicht.
  4. Wir haben die Protokollierungsstufen herausgefunden.
  5. Wir haben uns mit Protokollierungsknoten vertraut gemacht.
  6. Wir haben uns angesehen, was ein Appender ist und wozu er dient.
  7. Wir haben die Datei log4j.proterties Schritt für Schritt konfiguriert.

Zusätzliche Materialien

  1. JavaRush: Protokollierung. Wickeln Sie eine Kugel Stectrace ab
  2. JavaRush: Logger-Vorlesung
  3. Habr: Java-Protokollierung. Hallo Welt
  4. Habr: Java-Logging: die Geschichte eines Albtraums
  5. Youtube: Golovach-Kurse. Protokollierung. Teil 1 , Teil 2 , Teil 3 , Teil 4
  6. Log4j: Appender
  7. Log4j: Layout
Siehe auch meine anderen Artikel:
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION