Ein erster Blick auf Logback: Erfahren Sie, wie Sie Logback-Konfigurationsdateien verstehen

Vorwort

In heutigen Anwendungen sind Protokolle zu einem sehr wichtigen Werkzeug geworden. Mithilfe der vom System gedruckten Protokolle können Sie den Betrieb des Systems überwachen und die Ursachen von Systemfehlern beheben. Von der frühesten Protokollierung bis zu den verschiedenen ausgereiften Frameworks von heute ist der Protokolldruck standardisierter und klarer geworden. Insbesondere das Aufkommen von SLF4J definiert eine gemeinsame FACADE-Schnittstelle und Funktionen für das Protokollierungsframework. Durch einfaches Einführen des SLF4J-Pakets und des Protokollpakets, das FACADE speziell in die Anwendung implementiert, kann die Anwendung der oberen Schicht nur für die SLF4J-Schnittstelle programmieren, ohne sich um das spezifische zugrunde liegende Protokoll-Framework zu kümmern, wodurch die Entkopplung der Anwendung der oberen Schicht erreicht wird und das zugrunde liegende Protokoll-Framework. Logback ist als Framework, das die allgemeinen Funktionen von SLF4J unterstützt, zu einem der beliebtesten Protokollierungs-Frameworks geworden. Lassen Sie uns heute ein wenig über einige grundlegende Funktionen und Konfigurationsdateien von Logback-Protokollen lernen. System.out.print

Mit Logback können Sie schnell loslegen

Einführung in MAVEN-Abhängigkeiten

logback besteht hauptsächlich aus drei Modulen, nämlich logback-core, logback-classic und logback-access. Unter anderem ist logback-core das Kernmodul des gesamten Logbacks, logback-classic unterstützt SLF4J FACADE und logback-access integriert Servlet Rongqi, um HTTP bereitzustellen Protokollierungsfunktion, geeignet für Webanwendungen. Die folgende Einführung basiert hauptsächlich auf logback-classic.

Die Pakete, die logback-classic einführen, sind wie folgt:

<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.3.0-alpha5</version>
</dependency>

Das oben gezogene Maven-Paket ruft automatisch logback-classic, logback-core und slf4j-api.jar basierend auf der transitiven Entfernung ab, sodass im Projekt keine zusätzlichen Abhängigkeiten von SLF4J und logback-core deklariert werden müssen.

Verwenden Sie Logback

Dalogback-classic SLF4J FACADE implementiert, muss sich die Anwendung der oberen Ebene nur mit der Aufrufsyntax von SLF4J auseinandersetzen. Der folgende Code zeigt, wie Sie das Logger-Objekt zum Drucken von Protokollen erhalten.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.util.StatusPrinter;

public class HelloWorld2 {

  public static void main(String[] args) {
    //这里的Logger和LoggerFactory均为SLF4J的类,真正调用时会使用Logback的日志能力
    //getLogger方法中传入的是Logger的名称,这个名称在后面讲解配置文件中的<logger>时会继续提到
    Logger logger = LoggerFactory.getLogger("chapters.introduction.HelloWorld2");
    
    //打印一条Debug级别的日志
    logger.debug("Hello world.");

    //获取根Logger,使用场景比较少
    Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
  }
}

Protokollebene

Jeder Logger in Logback verfügt über eine entsprechende Protokollebene. Die Protokollebene kann vom Logger selbst definiert oder vom übergeordneten Logger geerbt werden. Logback unterstützt insgesamt 5 Protokollebenen, von hoch bis niedrig: ERROR, WARN, INFO, DEBUG und TRACE. Die Protokollebene des Loggers bestimmt, welche Protokollebenen ausgegeben werden können. Es werden nur Protokolle gedruckt, deren Level größer oder gleich dem Logger-Level ist. Angenommen, die oben erhaltene Protokollebene des Loggers mit dem Namen „chapters.introduction.HelloWorld2“ ist INFO. Beim Aufruf von logger.debug(„xxx“) wird der Protokollinhalt nicht ausgegeben, da die DEBUG-Protokollebene niedriger als die INFO-Protokollebene ist Ebene.

Die Protokollebene kann uns helfen, die Granularität des Protokolldrucks zu steuern. In der Entwicklungsumgebung kann die Protokollebene beispielsweise auf DEBUG eingestellt werden, um die Fehlerbehebung zu erleichtern, während in der Produktionsumgebung die Protokollebene dadurch auf INFO gesetzt werden kann Reduzierung der Leistung, die durch unnötiges Drucken von Protokollen verursacht wird. Einfluss.

Parametrische Ausgabe

Manchmal drucken wir nicht einfach ein vollständiges Protokoll aus, sondern möchten einige laufende Parameter wie folgt in das Protokoll aufnehmen:

Logger logger = LoggerFactory.getLogger("chapters.introduction.HelloWorld2");
logger.debug("Hello World To " + username);

Das obige Protokoll druckt nicht nur einige strukturierte Anweisungen, sondern fügt auch den Namen des Benutzers zusammen, der diese Logik zur Laufzeit ausgeführt hat. Hier entsteht ein Problem, nämlich das Problem der String-Verkettung. Obwohl die JVM das Spleißen von String-Strings optimiert hat, ist der von diesem Code durchgeführte String-Splicing-Vorgang völlig unnötig, wenn die aktuelle Protokollebene INFO ist. Daher wird empfohlen, dem Code zur Optimierung eine Zeile zur Beurteilung der Protokollebene wie folgt hinzuzufügen:

//非debug级别不会执行字符串拼接操作,但是debug级别会执行两次isDebugEnabled操作,性能影响不大
if(logger.isDebugEnabled()) { 
    logger.debug("Hello World To " + username);
}

Logback empfiehlt jedoch nicht die Verwendung der Zeichenfolgenverkettung zur Ausgabe von Protokollen im System. Stattdessen wird die Verwendung von Parameterübergaben empfohlen, und Logback selbst führt die Protokollserialisierung durch. wie folgt:

//logger方法会判断是否为debug级别,再决定将entry序列化拼接如字符串
logger.debug("The entry is {}.", entry);

Diese Protokollausgabemethode muss keine zusätzliche Ebene zur Beurteilung der Protokollebene enthalten, da die Methode logger.debug die Protokollebene einmal beurteilt und dann die Transkodierungsoperation für den Protokollinhalt durchführt. Beachten Sie, dass die eingehenden Parameter die toString-Methode implementieren müssen. Andernfalls druckt das Protokoll bei der Transkodierung des Objekts nur die Speicheradresse des Objekts aus, nicht den spezifischen Inhalt des Objekts

Gesamtstruktur

Im vorherigen Artikel wurden kurz die drei in Logback enthaltenen Hauptmodule vorgestellt und erläutert, wie das Log-Framework im Code basierend auf SLF4J FACADE frei verwendet werden kann. Beginnen wir damit, zu verstehen, wie Logback aus der Perspektive der Konfigurationsdateien konfiguriert wird.
Logback unterstützt hauptsächlich XML- und Groovy-Struktur-Konfigurationsdateien. Das Folgende wird basierend auf der XML-Struktur vorgestellt.


Das obige Bild ist eine Beschreibung der Gesamtstruktur der Logback-Konfigurationsdatei auf der offiziellen Website. Die Konfigurationsdatei verwendet <configuration> als Root-Element und enthält 1 <root>-Element darunter, um die Konfigurationsinformationen des Root-Protokolls zu definieren, und es gibt 0 bis mehr < /span> verknüpft werden, wodurch dieselbe Protokollzeile an mehrere Ziele ausgegeben werden kann. mit mehreren definiert das Ausgabeziel des Protokolls , kann ein in der Anwendung abgerufen wird, und das Element entspricht dem Protokollierungstool, das über Elemente. Das Element <logger> Elemente und null bis mehr <appender><logger>LoggerFactory.getLogger()<appender><logger><appender>

Eine einfache Logback-Konfigurationsdatei lautet wie folgt:

<configuration> 
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
   <!-- encoders are  by default assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

Diese Konfigurationsdatei deklariert einen Appender mit dem Ausgabenamen STDOUT für die Konsole, deklariert die Protokollebene des Root-Loggers als Debug und gibt an, dass das Protokoll an den STDOUT-Stream ausgegeben wird.

Logback ermöglicht mehrere Konfigurationsdateien und die Reihenfolge, in der Konfigurationsdateien beim Laden gelesen werden, ist wie folgt:

  1. Suchen Sie logback-test.xml im Klassenpfad (im Allgemeinen lautet der Klassenpfad src/test/resources).
  2. Wenn die Datei nicht vorhanden ist, versucht Logback, logback.groovy zu finden
  3. Wenn die Datei nicht vorhanden ist, versucht Logback, logback.xml zu finden
  4. Wenn die Datei nicht vorhanden ist, sucht Logback unter META-INF danach[com.qos.logback.classic.spi.Configurator](http://logback.qos.ch/xref/ch/qos/logback/classic/spi/Configurator.html)接口的实现
  5. Wenn es immer noch nicht gefunden wird, wird der Standard-BasicConfigurator verwendet, wodurch das Protokoll direkt auf der Konsole gedruckt wird. Die Protokollebene ist DEBUG und das Protokollformat ist _%d{HH:mm:ss.SSS} [%thread ] %-5level % Logger{36} – %msg%n_

Syntax der Konfigurationsdatei

Nach einem kurzen Verständnis der Grundstruktur der Logback-Konfigurationsdatei werden in diesem Kapitel einige der am häufigsten verwendeten Tags im Logback und ihre jeweilige Bedeutung im Detail vorgestellt.

Konfigurations-Tag

Als Root-Tag der Konfigurationsdatei definiert „configuration“ den Modus zum Lesen der gesamten Logback-Konfiguration. Die Attribute, die im Konfigurations-Tag definiert werden können, sind wie folgt:

  1. debug: Der Standard-Debug-Wert ist false. Wenn debug auf true gesetzt ist, wird der Status des Protokollrahmens gedruckt, unabhängig davon, ob die Konfiguration erfolgreich gelesen wurde. Wenn er false ist, wird das Statusprotokoll nur gedruckt, wenn ein Fehler vorliegt Fehler beim Lesen der Konfiguration.
  2. scan: Der Standardwert ist „false“. Wenn „scan“ auf „true“ gesetzt ist, scannt Logback die Konfigurationsdatei automatisch regelmäßig. Wenn sich die Konfigurationsdatei ändert, kann Logback sie schnell identifizieren und neu konfigurieren. Das Standard-Scanintervall kann über scanPeriod überschrieben werden. Es wird empfohlen, diese Funktion nicht in der Produktionsumgebung zu aktivieren, da die Konfiguration des Protokollframeworks in der Produktionsumgebung grundsätzlich stabil ist. Nur wenn die Entwicklungsumgebung das Verhalten des Protokollierungsframeworks debuggen muss, kann diese Funktion aktiviert werden, um die Probleme beim Neustart der Anwendung aufgrund einer Änderung der Konfiguration zum Debuggen zu reduzieren.

Logger-Tag

logger ist die Grundeinheit der Protokollstream-Isolation. Jeder Logger wird an einen LoggerContext gebunden. Es besteht eine baumartige hierarchische Beziehung zwischen Loggern, d. h. Logger A kann der übergeordnete Logger von Logger B sein. Die hierarchische Beziehung zwischen ihnen wird anhand des Namens des Loggers bestimmt. Wenn der Name von Logger A com.moduleA und der Name von Logger B com.moduleA.packageA ist, kann A als übergeordneter Logger von B bezeichnet werden. Der Zweck dieser Baumstruktur besteht darin, dass B, wenn es keine eigene Protokollebene definiert, die Protokollebene von A erbt. Andere wie Appender werden ebenfalls basierend auf der Vererbungsbeziehung berechnet.

Logger verfügt nur über ein erforderliches Namensattribut. Im Allgemeinen werden die anderen mit Ausnahme mehrerer Loggernamen, die speziell definiert werden müssen, grundsätzlich in der Moduldimension definiert, wodurch sichergestellt wird, dass jede Klasse unter dem Modul in ihrer eigenen Klasse definiert ist. Wenn der Logger namentlich aufgerufen wird, kann der entsprechende Logger oben gefunden werden.

Wenn beispielsweise ein Logger mit dem Namen com.rale.service definiert ist, befindet er sich in der Klasse com.rale.service.HelloService.java und wird verwendet LoggerFactory.getLogger(HelloService.class) Obwohl der erhaltene Logger nicht in der Konfigurationsdatei deklariert ist, wird der vollständige Pfad der Klasse als Name des Loggers verwendet, und der nächstgelegene übergeordnete Logger wird entsprechend der Logger-Ebene nach oben gesucht und der Name wird schließlich zurückgegeben als < ein Logger für i=4>. com.rale.service

Der Logger verfügt außerdem über eine Bezeichnung namens Level, mit der dem Logger ein entsprechender Log-Level zugewiesen werden kann. Es werden nur Logs ausgegeben, die über diesem Level liegen. Wenn kein Ebenenwert explizit definiert ist, wird seine Protokollebene vom nächstgelegenen übergeordneten Knoten geerbt, der explizit eine Protokollebene deklariert.

Eine grundlegende Logger-Konfiguration sieht wie folgt aus:

<logger name="integration" level="INFO" additivity="false">
    <appender-ref ref="integration"/>
    <appender-ref ref="common-error"/>
</logger>

Ein Logger kann mehrere Appender-Ref-Tags enthalten, die deklarieren, dass die Protokolle des Loggers in diesen Ausgabestreams gedruckt werden. Es gibt auch eine spezielle Attributadditivität, die verwendet wird, um das Vererbungsverhalten des Appenders einzuschränken. Standardmäßig ist der Wert von aditicity „true“, d. h. der Logger druckt zusätzlich zu der aktuell explizit deklarierten Appender-Ref an alle vom übergeordneten Logger geerbten Appender. Unter der Annahme, dass <appender-ref ref="common"> beispielsweise im Stammverzeichnis deklariert ist, druckt die Integration Protokolle gleichzeitig in diesen drei Ausgabestreams. Wenn im übergeordneten Logger und im untergeordneten Logger derselbe Appender vorhanden ist, wird das Protokoll auch zweimal im Appender gedruckt. Daher kann durch die Einstellung der Additivität auf „false“ eine übermäßige Protokollausgabe reduziert werden, die durch eine unerwartete Appender-Vererbung verursacht wird.

Appender-Tag

Ein Appender entspricht einem Protokollausgabestream. Derselbe Appender kann an mehrere Logger gebunden sein, d. h. mehrere Logger können Protokolle an den Appender ausgeben. Daher implementiert die Appender-Implementierung intern die Parallelitätskontrolle, um verstümmelte Protokollzeichen zu verhindern.

Appender unterstützt viele Ausgabeterminals, einschließlich Konsole, Datei, Remote-Socket-Server, MySQL, PostgreSQL und andere Datenbanken, Remote-UNIX-Protokollprozess, JMS usw.

<appender> verfügt über zwei obligatorische Attribute: Name und Klasse (der vollständige Pfad der Appender-Klasse), einschließlich 0 bis mehr <layout class="">-Tags und 0 bis mehr <encoder class="" ;>-Tag, 0 bis mehrere <filter>-Tags. Es kann auch eine beliebige Anzahl von Mitgliedsvariablenattributwerten der Appender Bean-Klasse enthalten.

Die Layout- und Encoder-Tags werden zum Formatieren der Protokolle im Appender verwendet, und das Filter-Tag unterstützt das Filtern der Protokollinformationen aus dem Appender, um zu bestimmen, welche Protokolle gedruckt werden und welche nicht. Daher können die Protokolle in der Appender-Dimension durch definiert werden Filterstufe.

Ein typischer Appender sieht wie folgt aus:

    <appender name="common-error"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/sls-common-error.log</file>
        <encoder>
            <pattern>${LOCAL_FILE_LOG_PATTERN}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>

Hier wird ein Dateiausgabestream deklariert, und das Datei-Tag wird verwendet, um den Speicherort der Ausgabedatei zu definieren, und der Encoder wird verwendet, um das Protokolldruckformat zu definieren. Es wird hier durch Referenzieren von Variablen definiert. Variablen werden später im Eigenschafts-Tag ausführlich vorgestellt. Dann wird ein Filter gebunden und der Appender wird mithilfe dieses Filters so definiert, dass nur Protokolle gedruckt werden, deren Protokollebene größer oder gleich der ERROR-Ebene ist.

Root-Tag

Das Root-Tag muss einmal in der Konfiguration deklariert werden. Das Root-Tag definiert tatsächlich die Konfigurationsinformationen des Root-Loggers. Seine Standardprotokollebene ist Debug. Der letzte übergeordnete Logger aller Logger muss der Root-Logger sein.

Eigenschafts-Tag

Das Eigenschafts-Tag unterstützt die Deklaration von Variablen in der Konfigurationsdatei. Es gibt drei Quellen für Konfigurationsdateivariablen, nämlich JVM COMMAND, JAVA COMMAND, Classpth und die aktuelle Konfigurationsdatei. Das Format der vom JAVA-Befehl übergebenen Variablen lautet beispielsweise wie folgtjava -DUSER_HOME="/home/sebastien" MyApp2. Das <property>-Tag unterstützt die Deklaration von Mitgliedsvariablen in der Konfigurationsdatei. Es unterstützt drei Typen: KV, relativer Dateipfad und Dateien unter Classpth.

  <!--键值型声明-->
  <property name="USER_HOME" value="/home/sebastien" />

  <!--配置文件声明-->
  <property file="src/main/java/chapters/configuration/variables1.properties" />

  <!--Classpath资源-->
  <property resource="resource1.properties"/>

Um auf diese Variablen zu verweisen, wird die standardmäßige Linux-Variablenreferenzmethode verwendet. Der Wert der Variablen kann über ${Variablenname} referenziert werden. Es unterstützt auch die Deklaration von Standardwerten für diese Variablen über die Syntaxstruktur ${变量名称:-默认值}.

Ein einfaches Beispiel für die Deklaration und Verwendung einer Konfiguration lautet wie folgt:

<configuration>
  <property name="USER_HOME" value="/home/sebastien" />
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${USER_HOME}/myApp.log</file>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Tag definieren

Das Tag define wird auch zum Deklarieren von Variablen verwendet. Der Unterschied zur obigen Eigenschaft besteht jedoch darin, dass define dynamische Variablen deklariert, dh die Werte dieser Variablen können erst nach Ausführung des Programms abgerufen werden. Beispielsweise wird die Variable ${HOSTNAME}, die standardmäßig in der Konfigurationsdatei vorhanden ist, über das Tag define implementiert. Sie ruft nach der Ausführung des Programms dynamisch den Hostnamen des aktuellen Containers ab und weist ihn der Variablen HOSTNAME zu.

Eine typische Verwendung des Define-Tags ist wie folgt: Es ist erforderlich, dass die in der Define-Klasse ausgefüllte Klasse eine Implementierung der PropertyDefiner-Schnittstelle sein muss.

<configuration>

  <define name="rootLevel" class="a.class.implementing.PropertyDefiner">
    <shape>round</shape>
    <color>brown</color>
    <size>24</size>
  </define>
 
  <root level="${rootLevel}"/>
</configuration>

Logback bietet mehrere grundlegende Definer-Implementierungen, wie z. B.FileExistsPropertyDefiner, einen Definierer, der verwendet wird, um zu bestimmen, ob die im Pfad deklarierte Datei vorhanden ist. .

Tag einschließen

Das Include-Tag ermöglicht die Einführung einer in einem anderen Pfad gespeicherten Logback-Konfiguration. Ein Beispiel ist wie folgt:

<configuration>
  <include file="src/main/java/chapters/configuration/includedConfig.xml"/>

  <root level="DEBUG">
    <appender-ref ref="includedConsole" />
  </root>

</configuration>

src/main/java/chapters/configuration/includedConfig.xmlDer Inhalt der Datei ist wie folgt:

<included>
  <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>"%d - %m%n"</pattern>
    </encoder>
  </appender>
</included>

Der Inhalt der eingebundenen Datei muss im eingebundenen Tag enthalten sein und die Syntax muss der Syntax der Logback-Konfigurationsdatei entsprechen. Hier ist die Einführung eines in includeConfig.xml deklarierten Appenders.

Supongo que te gusta

Origin blog.csdn.net/risen16/article/details/127687943
Recomendado
Clasificación