Programmatisk konfiguration med Log4j 2

1. Introduktion

I denne vejledning ser vi på forskellige måder at programmatisk konfigurere Apache Log4j 2 på.

2. Første opsætning

For at begynde at bruge Log4j 2 behøver vi blot at inkludere log4j-core og log4j-slf4j-impl afhængigheder i vores pom.xml:

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

3. ConfigurationBuilder

Når vi har konfigureret Maven, skal vi oprette en ConfigurationBuilder, som er den klasse, der lader os konfigurere appenders, filtre, layouts, og loggere.

Log4j 2 giver flere måder at få en ConfigurationBuilder.

Lad os starte med den mest direkte måde:

ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder ();

Og for at begynde at konfigurere komponenter, ConfigurationBuilder er udstyret med en tilsvarende ny metode, ligesom newAppender eller newLayout, for hver komponent.

Nogle komponenter har forskellige undertyper, f.eks FileAppender eller ConsoleAppender, og disse omtales i API'en som plugins.

3.1. Konfiguration af appenders

Lad os fortælle det Bygger hvor skal hver loglinje sendes ved at konfigurere en appender:

AppenderComponentBuilder-konsol = builder.newAppender ("stdout", "Console"); builder.add (konsol); AppenderComponentBuilder file = builder.newAppender ("log", "File"); file.addAttribute ("filnavn", "target / logging.log"); builder.add (fil);

Mens de fleste ny metoder understøtter ikke dette, newAppender (navn, plugin) giver os mulighed for at give appenderen et navn, som senere viser sig at være vigtigt. Disse appenders, vi har ringet stdout og log, selvom vi kunne have navngivet dem noget.

Vi har også fortalt det Bygger hvilken appender plugin (eller mere simpelt, hvilken slags appender) der skal bruges. Konsol og Fil henvises til Log4j 2s appenders for henholdsvis at skrive til standard out og filsystemet.

Selvom Log4j 2 understøtter flere appenders, at konfigurere dem ved hjælp af Java kan være lidt vanskeligt siden AppenderComponentBuilder er en generisk klasse for alle appender-typer.

Dette gør det til at have metoder som addAttribute og addComponent i stedet for setFileName og addTriggeringPolicy:

AppenderComponentBuilder rollingFile = builder.newAppender ("rullende", "RollingFile"); rollingFile.addAttribute ("filnavn", "rullende.log"); rollingFile.addAttribute ("filePattern", "rullende-% d {MM-dd-åå} .log.gz"); builder.add (rollingFile); 

Og endelig, glem ikke at ringe bygherre. tilføj at tilføje det til hovedkonfigurationen!

3.2. Konfiguration af filtre

Vi kan tilføje filtre til hver af vores appenders, som bestemmer på hver loglinje, om den skal tilføjes eller ej.

Lad os bruge MarkerFilter plugin på vores konsol appender:

FilterComponentBuilder flow = builder.newFilter ("MarkerFilter", Filter.Result.ACCEPT, Filter.Result.DENY); flow.addAttribute ("markør", "FLOW"); console.add (flow);

Bemærk, at dette ny metode tillader os ikke at navngive filteret, men det beder os om at angive, hvad vi skal gøre, hvis filteret passerer eller fejler.

I dette tilfælde har vi holdt det simpelt og angivet, at hvis MarkerFilter passerer, så ACCEPTERE logline. Ellers, NÆGTE det.

Bemærk i dette tilfælde, at vi ikke tilføjer dette til Bygger men i stedet for appenders, at vi vil bruge dette filter.

3.3. Konfiguration af layout

Lad os derefter definere layoutet for hver loglinje. I dette tilfælde bruger vi Mønsterlayout plugin:

LayoutComponentBuilder standard = builder.newLayout ("PatternLayout"); standard.addAttribute ("mønster", "% d [% t]% -5niveau:% msg% n% kastbar"); console.add (standard); file.add (standard); rolling.add (standard);

Igen har vi tilføjet disse direkte til de relevante appenders i stedet for til Bygger direkte.

3.4. Konfiguration af rodloggeren

Nu hvor vi ved, hvor logfiler sendes til, vil vi konfigurere, hvilke logfiler der skal gå til hver destination.

Rødloggeren er den højeste logger, ligesom Objekt i Java. Denne logger er, hvad der vil blive brugt som standard, medmindre den tilsidesættes.

Så lad os bruge en rodlogger til at indstille standardlogningsniveauet til FEJL og standardappenderen til vores stdout appender ovenfra:

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

For at rette vores logger mod en bestemt appender giver vi den ikke en instans af bygherren. I stedet, vi henviser til det med navn at vi gav det tidligere.

3.5. Konfiguration af yderligere loggere

Child loggers kan bruges til at målrette mod specifikke pakker eller loggernavne.

Lad os tilføje en logger til com pakke i vores applikation, idet logningsniveauet indstilles til FEJLFINDE og få dem til vores log appender:

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

Bemærk, at vi kan indstille additivitet med vores loggere, hvilket angiver, om denne logger skal arve egenskaber som logningsniveau og appendertyper fra sine forfædre.

3.6. Konfiguration af andre komponenter

Ikke alle komponenter har en dedikeret ny metode til ConfigurationBuilder.

Så i så fald ringer vi newComponent.

For eksempel fordi der ikke er en TriggeringPolicyComponentBuilder, vi skal bruge newComponent til noget som at specificere vores udløsende politik for rullende filappendere:

ComponentBuilder triggeringPolicies = builder.newComponent ("Politikker") .addComponent (builder.newComponent ("CronTriggeringPolicy") .addAttribute ("tidsplan", "0 0 0 * *?")) .AddComponent (builder.newComponent ("SizeBasedTrigger) .addAttribute ("størrelse", "100M")); rolling.addComponent (triggeringPolicies);

3.7. XML-ækvivalent

ConfigurationBuilder er udstyret med en praktisk metode til at udskrive den tilsvarende XML:

builder.writeXmlConfiguration (System.out);

Kørsel af ovenstående linje udskrives:

Dette er praktisk, når vi vil dobbelttjekke vores konfiguration, eller hvis vi vil fortsætte vores konfiguration, f.eks. Til filsystemet.

3.8. Samler det hele

Nu hvor vi er fuldt konfigureret, lad os fortælle Log4j 2 at bruge vores konfiguration:

Configurator.initialize (builder.build ());

Når dette er påberåbt, fremtidige opkald til Log4j 2 bruger vores konfiguration.

Bemærk, at dette betyder, at vi skal påberåbe os Configurator.initialize inden vi ringer til LogManager.getLogger.

4. ConfigurationFactory

Nu hvor vi har set en måde at få og anvende en ConfigurationBuilder, lad os se på en mere:

offentlig klasse CustomConfigFactory udvider ConfigurationFactory {public Configuration createConfiguration (LoggerContext context, ConfigurationSource src) {ConfigurationBuilder builder = super .newConfigurationBuilder (); // ... konfigurer appenders, filtre osv. returner builder.build (); } offentlig streng [] getSupportedTypes () {returner ny streng [] {"*"}; }}

I dette tilfælde i stedet for at bruge ConfigurationBuilderFactory, vi underklasserede ConfigurationFactory, en abstrakt klasse målrettet til at skabe forekomster af Konfiguration.

Så i stedet for at ringe Configurator.initialize Som vi gjorde første gang, er vi bare nødt til at lade Log4j 2 vide om vores nye konfigurationsfabrik.

Der er tre måder at gøre dette på:

  • Statisk initialisering
  • En runtime-ejendom eller
  • Det @Plugin kommentar

4.1. Brug statisk initialisering

Log4j 2 understøtter opkald setConfigurationFactory under statisk initialisering:

statisk {ConfigurationFactory brugerdefineret = ny CustomConfigFactory (); ConfigurationFactory.setConfigurationFactory (brugerdefineret); }

Denne tilgang har samme begrænsning som for den sidste tilgang, vi så, hvilket er, at vi bliver nødt til at påberåbe sig den inden nogen opkald til LogManager.getLogger.

4.2. Brug en Runtime-ejendom

Hvis vi har adgang til Java-startkommandoen, understøtter Log4j 2 også specificering af ConfigurationFactory at bruge via en -D parameter:

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

Den største fordel ved denne tilgang er, at vi ikke behøver at bekymre os om initialiseringsrækkefølge, som vi gør med de to første tilgange.

4.3. Brug @Plugin Kommentar

Og endelig under omstændigheder, hvor vi ikke vil rode med Java-startkommandoen ved at tilføje en -D, kan vi ganske enkelt kommentere vores CustomConfigurationFactory med Log4j 2 @Plugin kommentar:

@Plugin (name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY) @Order (50) offentlig klasse CustomConfigFactory udvider ConfigurationFactory {// ... resten af ​​implementeringen}

Log4j 2 scanner klassestien for klasser, der har @Plugin kommentar og finde denne klasse i ConfigurationFactory kategori, vil bruge det.

4.4. Kombinerer med statisk konfiguration

En anden fordel ved at bruge en ConfigurationFactory udvidelse er, at vi nemt kan kombinere vores brugerdefinerede konfiguration med andre konfigurationskilder som XML:

offentlig konfiguration createConfiguration (LoggerContext context, ConfigurationSource src) {returner ny WithXmlConfiguration (context, src); } 

Det kilde parameter repræsenterer den statiske XML- eller JSON-konfigurationsfil, som Log4j 2 finder, hvis nogen.

Vi kan tage denne konfigurationsfil og sende den til vores brugerdefinerede implementering af Xml-konfiguration hvor vi kan placere den overordnede konfiguration, vi har brug for:

offentlig klasse WithXmlConfiguration udvider XmlConfiguration {@ Override beskyttet ugyldigt doConfigure () {super.doConfigure (); // parse xml document // ... tilføj vores brugerdefinerede konfiguration}}

5. Konklusion

I denne artikel så vi på, hvordan man bruger det nye ConfigurationBuilder API tilgængelig i Log4j 2.

Vi kiggede også på tilpasning ConfigurationFactory i kombination med ConfigurationBuilder til mere avancerede brugssager.

Glem ikke at tjekke mine komplette eksempler på GitHub.