Log4j 2 plugins

1. Oversigt

Log4j 2 bruger plugins som Appenders og Layouts til at formatere og outputte logfiler. Disse kaldes kerne-plugins, og Log4j 2 giver mange muligheder for os at vælge imellem.

I nogle tilfælde kan vi dog også have brug for at udvide det eksisterende plugin eller endda skrive tilpassede.

I denne vejledning bruger vi Log4j 2-udvidelsesmekanismen til at implementere brugerdefinerede plugins.

2. Udvidelse af Log4j 2-plugins

Plugins i Log4j 2 er stort set opdelt i fem kategorier:

  1. Core Plugins
  2. Omformere
  3. Nøgleudbydere
  4. Opslag
  5. Skriv konvertere

Log4j 2 giver os mulighed for at implementere brugerdefinerede plugins i alle ovenstående kategorier ved hjælp af en fælles mekanisme. Desuden giver det os også mulighed for at udvide eksisterende plugins med samme tilgang.

I Log4j 1.x er den eneste måde at udvide et eksisterende plugin på at tilsidesætte dets implementeringsklasse. På den anden side gør Log4j 2 det lettere at udvide eksisterende plugins ved at kommentere en klasse med @Plugin.

I de følgende sektioner implementerer vi et brugerdefineret plugin i nogle få af disse kategorier.

3. Core Plugin

3.1. Implementering af et brugerdefineret Core Plugin

Nøgleelementer som Appenders, Layouts og Filtre er kendt som kerne-plugins i Log4j 2. Selvom der er en forskelligartet liste over sådanne plugins, er vi i nogle tilfælde muligvis nødt til at implementere et brugerdefineret core-plugin. Overvej f.eks ListAppender der kun skriver logposter i en hukommelse Liste:

@Plugin (name = "ListAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) offentlig klasse ListAppender udvider AbstractAppender {privat liste logList; beskyttet ListAppender (strengnavn, filterfilter) {super (navn, filter, null); logList = Collections.synchronizedList (ny ArrayList ()); } @PluginFactory offentlig statisk ListAppender createAppender (@PluginAttribute ("navn") Navn på streng, @PluginElement ("Filter") endelig filterfilter) {returner ny ListAppender (navn, filter); } @Override public void append (LogEvent event) {if (event.getLevel (). IsLessSpecificThan (Level.WARN)) {error ("Kan ikke logge mindre end WARN-niveau."); Vend tilbage; } logList.add (begivenhed); }}

Vi har kommenteret klassen med @Plugin det giver os mulighed for at navngive vores plugin. Parametrene er også kommenteret med @PluginAttribute. De indlejrede elementer som filter eller layout videregives som @PluginElement. Nu kan vi henvise dette plugin i konfigurationen ved hjælp af samme navn:

3.2. Plugin Builders

Eksemplet i sidste afsnit er ret simpelt og accepterer kun en enkelt parameter navn. Generelt er core-plugins som appenders meget mere komplekse og accepterer normalt flere konfigurerbare parametre.

Overvej f.eks. En appender, der skriver logger ind Kafka:

For at implementere sådanne appenders leverer Log4j 2 en implementering af plugin-builder baseret på Bygger mønster:

@Plugin (name = "Kafka2", category = Core.CATEGORY_NAME) offentlig klasse KafkaAppender udvider AbstractAppender {offentlig statisk klasse Builder implementerer org.apache.logging.log4j.core.util.Builder {@PluginBuilderAttribute ("navn") @ Nødvendig privat Strengnavn; @PluginBuilderAttribute ("ip") privat streng ipAddress; // ... yderligere egenskaber // ... getters og setters @Override public KafkaAppender build () {return new KafkaAppender (getName (), getFilter (), getLayout (), true, new KafkaBroker (ipAddress, port, topic, skillevæg)); }} privat KafkaBroker-mægler; private KafkaAppender (String name, Filter filter, Layout layout, boolean ignoreExceptions, KafkaBroker broker) {super (name, filter, layout, ignoreExceptions); denne.mægler = mægler; } @ Override public void append (LogEvent event) {connectAndSendToKafka (mægler, event); }}

Kort sagt introducerede vi en Bygger klasse og kommenterede parametrene med @PluginBuilderAttribute. På grund af dette, KafkaAppender accepterer Kafka-forbindelsesparametrene fra konfigurationen vist ovenfor.

3.3. Udvidelse af et eksisterende plugin

Vi kan også udvide et eksisterende kerneplugin i Log4j 2. Vi kan opnå dette ved at give vores plugin det samme navn som et eksisterende plugin. For eksempel, hvis vi udvider RollingFileAppender:

@Plugin (name = "RollingFile", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) offentlig klasse RollingFileAppender udvider AbstractAppender {public RollingFileAppender (strengnavn, filterfilter, layoutlayout) {super (navn, filter, layout); } @ Override public void append (LogEvent event) {}}

Især har vi nu to appenders med samme navn. I et sådant scenarie bruger Log4j 2 den appender, der først bliver opdaget. Vi vil se mere om opdagelse af plugin i et senere afsnit.

Bemærk, at Log4j 2 fraråder flere plugins med samme navn. Det er bedre at implementere et brugerdefineret plugin i stedet og bruge det i logningskonfigurationen.

4. Converter-plugin

Layoutet er et kraftfuldt plugin i Log4j 2. Det giver os mulighed for at definere outputstrukturen til vores logfiler. For eksempel kan vi bruge JsonLayout til at skrive logfiler i JSON-format.

Et andet sådant plugin er Mønsterlayout. I nogle tilfælde ønsker en applikation at offentliggøre oplysninger som tråd-id, trådnavn eller tidsstempel med hver logerklæring. Mønsterlayout plugin giver os mulighed for at integrere sådanne detaljer gennem en konverteringsmønsterstreng i konfigurationen:

Her, % d er konverteringsmønsteret. Log4j 2 konverterer dette% d mønster gennem a DatePatternConverter der forstår konverteringsmønsteret og erstatter det med den formaterede dato eller tidsstempel.

Antag nu, at et program, der kører inde i en Docker-container, ønsker at udskrive containernavnet med hver logerklæring. For at gøre dette implementerer vi en DockerPatterConverter og ændre ovenstående konfiguration for at inkludere konverteringsstrengen:

@Plugin (name = "DockerPatternConverter", category = PatternConverter.CATEGORY) @ConverterKeys ({"docker", "container"}) offentlig klasse DockerPatternConverter udvider LogEventPatternConverter {private DockerPatternConverter (String [] optioner) {super ("Docker", docker "); } offentlig statisk DockerPatternConverter newInstance (String [] optioner) {returner ny DockerPatternConverter (optioner); } @Override offentligt ugyldigt format (LogEvent-begivenhed, StringBuilder tilAppendTo) {toAppendTo.append (dockerContainer ()); } private String dockerContainer () {returner "container-1"; }}

Så vi implementerede en brugerdefineret DockerPatternConverter svarer til datomønsteret. Det erstatter konverteringsmønsteret med navnet på Docker-containeren.

Dette plugin ligner det kerneplugin, vi implementerede tidligere. Især er der kun en kommentar, der adskiller sig fra det sidste plugin. @ConverterKeys annotation accepterer konverteringsmønsteret for dette plugin.

Som et resultat konverteres dette plugin % docker eller %beholder mønsterstreng i det containernavn, hvor applikationen kører:

5. Opslags-plugin

Opslags-plugins bruges til at tilføje dynamiske værdier i Log4j 2-konfigurationsfilen. De tillader applikationer at integrere runtime-værdier til nogle egenskaber i konfigurationsfilen. Værdien tilføjes gennem en nøglebaseret opslag i forskellige kilder som et filsystem, en database osv.

Et sådant plugin er DateLookupPlugin der gør det muligt at erstatte et datomønster med den aktuelle systemdato for applikationen:

  % d% p% c {1.} [% t]% m% n 

I denne eksempelkonfigurationsfil RollingFileAppender bruger en dato opslag, hvor output vil være i MM-dd-åååå-format. Som et resultat skriver Log4j 2 logfiler til en outputfil med et dato-suffiks.

I lighed med andre plugins giver Log4j 2 mange kilder til opslag. Desuden gør det det nemt at implementere brugerdefinerede opslag, hvis der kræves en ny kilde:

@Plugin (name = "kafka", category = StrLookup.CATEGORY) public class KafkaLookup implementerer StrLookup {@Override public String lookup (String key) {return getFromKafka (key); } @Override offentlig strengopslag (LogEvent-begivenhed, strengnøgle) {return getFromKafka (nøgle); } privat String getFromKafka (String topicName) {returner "topic1-p1"; }}

KafkaLookup løser værdien ved at stille et Kafka-emne. Vi sender nu emnets navn fra konfigurationen:

  % d% p% c {1.} [% t]% m% n 

Vi erstattede dato opslag i vores tidligere eksempel med Kafka-opslag, der vil spørge emne-1.

Da Log4j 2 kun kalder standardkonstruktøren for et opslagsplugin, implementerede vi ikke @PluginFactory som vi gjorde i tidligere plugins.

6. Opdagelse af plugin

Lad os endelig forstå, hvordan Log4j 2 opdager plugins i en applikation. Som vi så i eksemplerne ovenfor, gav vi hvert plugin et unikt navn. Dette navn fungerer som en nøgle, som Log4j 2 løser til en plugin-klasse.

Der er en bestemt rækkefølge, hvor Log4j 2 udfører et opslag for at løse en plugin-klasse:

  1. Serialiseret pluginlistefil i log4j2-kerne bibliotek. Specifikt a Log4j2Plugins.dat er pakket inde i denne krukke for at angive standard Log4j 2-plugins
  2. Lignende Log4j2Plugins.dat fil fra OSGi-bundterne
  3. En komma-adskilt pakkeliste i log4j.plugin.packages systemegenskab
  4. I programmatisk Log4j 2-konfiguration kan vi ringe PluginManager.addPackages () metode til at tilføje en liste af pakkenavne
  5. En kommasepareret liste over pakker kan tilføjes i Log4j 2-konfigurationsfilen

Som en forudsætning skal annoteringsbehandling være aktiveret for at tillade Log4j 2 at løse plugin ved hjælp af navn givet i @Plugin kommentar.

Da Log4j 2 bruger navne til at slå pluginet op, bliver ovenstående rækkefølge vigtig. For eksempel, hvis vi har to plugins med samme navn, finder Log4j 2 det plugin, der først løses. Derfor, hvis vi har brug for at udvide et eksisterende plugin i Log4j 2, vi skal pakke pluginet i en separat krukke og placere det før log4j2-core.jar.

7. Konklusion

I denne artikel kiggede vi på de brede kategorier af plugins i Log4j 2. Vi diskuterede, at selvom der er en udtømmende liste over eksisterende plugins, er vi muligvis nødt til at implementere brugerdefinerede plugins til nogle brugssager.

Senere kiggede vi på den tilpassede implementering af nogle nyttige plugins. Desuden så vi, hvordan Log4j 2 giver os mulighed for at navngive disse plugins og derefter bruge dette pluginavn i konfigurationsfilen. Endelig diskuterede vi, hvordan Log4j 2 løser plugins baseret på dette navn.

Som altid er alle eksempler tilgængelige på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found