Programmatische Konfiguration mit Log4j 2

Programmatische Konfiguration mit Log4j 2

1. Einführung

In diesem Tutorial werden verschiedene Möglichkeiten zur programmgesteuerten Konfiguration von Apache Log4j 2 vorgestellt.

2. Ersteinrichtung

Um Log4j 2 verwenden zu können, müssen wir lediglich die Abhängigkeitenlog4j-core undlog4j-slf4j-impl in unserepom.xml aufnehmen:


    org.apache.logging.log4j
    log4j-core
    2.11.0


    org.apache.logging.log4j
    log4j-slf4j-impl
    2.11.0

3. ConfigurationBuilder

Sobald wir Maven konfiguriert haben, müssen wirConfigurationBuilder erstellen. Dies ist die Klasse, mit der wirappenders, filters, layouts, undloggers. konfigurieren können

Log4j 2 bietet verschiedene Möglichkeiten, umConfigurationBuilder zu erhalten.

Beginnen wir mit dem direktesten Weg:

ConfigurationBuilder builder
 = ConfigurationBuilderFactory.newConfigurationBuilder();

Um mit der Konfiguration der Komponenten zu beginnen, wirdConfigurationBuilder für jede Komponente mit einer entsprechendennew-Methode wienewAppender odernewLayout ausgestattet.

Einige Komponenten haben unterschiedliche Untertypen, wieFileAppender oderConsoleAppender,, und diese werden in der API alsplugins bezeichnet.

3.1. Appender konfigurieren

Lassen Sie uns denbuilder mitteilen, wohin jede Protokollzeile gesendet werden soll, indem Sieappender konfigurieren:

AppenderComponentBuilder console
  = builder.newAppender("stdout", "Console");

builder.add(console);

AppenderComponentBuilder file
  = builder.newAppender("log", "File");
file.addAttribute("fileName", "target/logging.log");

builder.add(file);

Während die meisten Methoden vonnewdies nicht unterstützen, können wir mitnewAppender(name, plugin) dem Appender einen Namen geben, der sich später als wichtig herausstellen wird. Diese Appender haben wirstdout undlog, genannt, obwohl wir sie alles benennen konnten.

Wir haben auch denbuildermitgeteilt, welche Appenderplugin  (oder einfacher gesagt, welche Art von Appender) verwendet werden sollen. Console undFile beziehen sich auf die Appender von Log4j 2 zum Schreiben in Standard-Out bzw. in das Dateisystem.

ObwohlLog4j 2 supports several appenders,configuring them using Java can be a bit tricky since AppenderComponentBuilder is a generic class for all appender types.

Dies macht es Methoden wieaddAttribute undaddComponent anstelle vonsetFileName undaddTriggeringPolicy:

AppenderComponentBuilder rollingFile
  = builder.newAppender("rolling", "RollingFile");
rollingFile.addAttribute("fileName", "rolling.log");
rollingFile.addAttribute("filePattern", "rolling-%d{MM-dd-yy}.log.gz");
rollingFile.addComponent(triggeringPolicies);

builder.add(rollingFile);

Und schließlichdon’t forget to call builder.add to append it to the main configuration!

3.2. Filter konfigurieren

Wir können jedem unserer Appender Filter hinzufügen, die in jeder Protokollzeile entscheiden, ob er angehängt werden soll oder nicht.

Verwenden wir das PluginMarkerFilterin unserem Konsolen-Appender:

FilterComponentBuilder flow = builder.newFilter(
  "MarkerFilter",
  Filter.Result.ACCEPT,
  Filter.Result.DENY);
flow.addAttribute("marker", "FLOW");

console.add(flow);

Beachten Sie, dass diesenew-Methode es uns nicht erlaubt, den Filter zu benennen, sondern uns auffordert, anzugeben, was zu tun ist, wenn der Filter erfolgreich ist oder fehlschlägt.

In diesem Fall haben wir es einfach gehalten und festgestellt, dassMarkerFilter die Protokollzeile ist, wennMarkerFilter übergeben wird. Ansonsten sitztDENY .

Beachten Sie in diesem Fall, dass wir dies nicht anbuilder anhängen, sondern an die Appender, die diesen Filter verwenden möchten.

3.3. Layouts konfigurieren

Als Nächstes definieren wir das Layout für jede Protokollzeile. In diesem Fall verwenden wir das PluginPatternLayout:

LayoutComponentBuilder standard
  = builder.newLayout("PatternLayout");
standard.addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable");

console.add(standard);
file.add(standard);
rolling.add(standard);

Auch hier haben wir diese direkt zu den entsprechenden Appendern anstatt zu denbuilder direkt hinzugefügt.

3.4. Root Logger konfigurieren

Nachdem wir wissen, wohin die Protokolle gesendet werden, möchten wir konfigurieren, welche Protokolle an die einzelnen Ziele gesendet werden.

Der Root-Logger ist der höchste Logger, ähnlich wieObject in Java. Dieser Logger wird standardmäßig verwendet, sofern er nicht überschrieben wird.

Verwenden wir also einen Root-Logger, um die Standardprotokollierungsstufe aufERROR und den Standard-Appender auf unseren Appenderstdoutvon oben festzulegen:

RootLoggerComponentBuilder rootLogger
  = builder.newRootLogger(Level.ERROR);
rootLogger.add(builder.newAppenderRef("stdout"));

builder.add(rootLogger);

Um unseren Logger auf einen bestimmten Appender zu richten, geben wir ihm keine Instanz des Builders. Stattdessenwe refer to it by the name that we gave it earlier.

3.5. Zusätzliche Logger konfigurieren

Untergeordnete Logger können verwendet werden, um auf bestimmte Pakete oder Loggernamen abzuzielen.

Fügen wir in unserer Anwendung einen Logger für das Paketcom hinzu, setzen Sie die Protokollierungsstufe aufDEBUG und lassen Sie diese in unseren Sappenderlog gehen:

LoggerComponentBuilder logger = builder.newLogger("com", Level.DEBUG);
logger.add(builder.newAppenderRef("log"));
logger.addAttribute("additivity", false);

builder.add(logger);

Beachten Sie, dass wiradditivity mit unseren Loggern festlegen können. Dies gibt an, ob dieser Logger Eigenschaften wie Protokollierungsstufe und Appender-Typen von seinen Vorfahren erben soll.

3.6. Andere Komponenten konfigurieren

Nicht alle Komponenten haben eine dediziertenew-Methode fürConfigurationBuilder.

In diesem Fall nennen wirnewComponent.

Da beispielsweise keinTriggeringPolicyComponentBuilder vorhanden ist, müssen wirnewComponent  verwenden, um beispielsweise unsere Auslöserichtlinie für fortlaufende Dateianhänge anzugeben:

ComponentBuilder triggeringPolicies = builder.newComponent("Policies")
  .addComponent(builder.newComponent("CronTriggeringPolicy")
    .addAttribute("schedule", "0 0 0 * * ?"))
  .addComponent(builder.newComponent("SizeBasedTriggeringPolicy")
    .addAttribute("size", "100M"));

rolling.addComponent(triggeringPolicies);

3.7. Das XML-Äquivalent

ConfigurationBuilder comes, die mit einer praktischen Methode zum Ausdrucken des entsprechenden XML ausgestattet sind:

builder.writeXMLConfiguration(System.out);

Wenn Sie die obige Zeile ausführen, wird Folgendes gedruckt:



   
      
         
         
      
      
         
         
            
            
         
      
      
         
      
   
   
      
         
      
      
         
      
   

Dies ist praktisch, wenn wir unsere Konfiguration überprüfen oder unsere Konfiguration beibehalten möchten, beispielsweise im Dateisystem.

3.8. Alles zusammenfügen

Nachdem wir vollständig konfiguriert sind, weisen wir Log4j 2 an, unsere Konfiguration zu verwenden:

Configurator.initialize(builder.build());

Nachdem dies aufgerufen wurde, wirdfuture calls to Log4j 2 will use our configuration.

Beachten Sie, dass dies bedeutet, dass wirConfigurator.initialize aufrufen müssen, bevor wirLogManager.getLogger aufrufen.

4. ConfigurationFactory

Nachdem wir einen Weg gefunden haben, einConfigurationBuilderzu erhalten und anzuwenden, schauen wir uns noch einen an:

public class CustomConfigFactory
  extends ConfigurationFactory {

    public Configuration createConfiguration(
      LoggerContext context,
      ConfigurationSource src) {

        ConfigurationBuilder builder = super
          .newConfigurationBuilder();

        // ... configure appenders, filters, etc.

        return builder.build();
    }

    public String[] getSupportedTypes() {
        return new String[] { "*" };
    }
}

In diesem Fall haben wir anstelle vonConfigurationBuilderFactoryConfigurationFactory in Unterklassen unterteilt, eine abstrakte Klasse, die zum Erstellen von Instanzen vonConfiguration bestimmt ist.

AnstattConfigurator.initialize wie beim ersten Mal aufzurufen, müssen wir Log4j 2 lediglich über unsere neue Konfigurationsfactory informieren.

Es gibt drei Möglichkeiten, dies zu tun:

  • Statische Initialisierung

  • Eine Laufzeit-Eigenschaft oder

  • Die@Plugin annotation

4.1. Verwenden Sie die statische Initialisierung

Log4j 2 unterstützt das Aufrufen vonsetConfigurationFactory während der statischen Initialisierung:

static {
    ConfigurationFactory custom = new CustomConfigFactory();
    ConfigurationFactory.setConfigurationFactory(custom);
}

Dieser Ansatz hat die gleiche Einschränkung wie der letzte Ansatz, den wir gesehen haben. Wir müssen ihnbefore any calls to LogManager.getLogger. aufrufen

4.2. Verwenden Sie eine Runtime-Eigenschaft

Wenn wir Zugriff auf den Java-Startbefehl haben, unterstützt Log4j 2 auch die Angabe derConfigurationFactory to-Verwendung über einen-D-Parameter:

-Dlog4j2.configurationFactory=com.example.log4j2.CustomConfigFactory

Der Hauptvorteil dieses Ansatzes besteht darin, dass wir uns nicht wie bei den ersten beiden Ansätzen um die Initialisierungsreihenfolge kümmern müssen.

4.3. Verwenden Sie die@Plugin Annotation

Und schließlich können wir unter Umständen, in denen wir nicht mit dem Java-Startbefehl herumspielen möchten, indem wir-D hinzufügen, unsereCustomConfigurationFactory einfach mit der Log4j 2@Plugin -Sannotation versehen:

@Plugin(
  name = "CustomConfigurationFactory",
  category = ConfigurationFactory.CATEGORY)
@Order(50)
public class CustomConfigFactory
  extends ConfigurationFactory {

  // ... rest of implementation
}

Log4j 2 durchsucht den Klassenpfad nach Klassen mit der Sannotation@Plugin und verwendet ihn, wenn diese Klasse in der KategorieConfigurationFactory gefunden wird.

4.4. Kombination mit statischer Konfiguration

Ein weiterer Vorteil der Verwendung der ErweiterungConfigurationFactorybesteht darin, dass wir unsere benutzerdefinierte Konfiguration problemlos mit anderen Konfigurationsquellen wie XML kombinieren können:

public Configuration createConfiguration(
  LoggerContext context,
  ConfigurationSource src) {
    return new WithXmlConfiguration(context, src);
}

Der Parametersource repräsentiert die statische XML- oder JSON-Konfigurationsdatei, die Log4j 2 gegebenenfalls findet.

Wir können diese Konfigurationsdatei nehmen und an unsere benutzerdefinierte Implementierung vonXmlConfiguration senden, wo wir die erforderliche überschreibende Konfiguration platzieren können:

public class WithXmlConfiguration extends XmlConfiguration {

    @Override
    protected void doConfigure() {
        super.doConfigure(); // parse xml document

        // ... add our custom configuration
    }
}

5. Fazit

In diesem Artikel haben wir uns mit der Verwendung der neuenConfigurationBuilder-API befasst, die in Log4j 2 verfügbar ist.

Wir haben uns auch mit dem Anpassen derConfigurationFactory in-Kombination mitConfigurationBuilder für fortgeschrittenere Anwendungsfälle befasst.

Vergessen Sie nicht, meine vollständigen Beispieleover on GitHub zu lesen.