Inleiding tot Log4j2 - Appenders, lay-outs en filters

1. Overzicht

Gebeurtenissen vastleggen is een cruciaal aspect van softwareontwikkeling. Hoewel er veel frameworks beschikbaar zijn in het Java-ecosysteem, is Log4J al decennia het populairst vanwege de flexibiliteit en eenvoud die het biedt.

Log4j 2 is een nieuwe en verbeterde versie van het klassieke Log4j-framework.

In dit artikel introduceren we de meest voorkomende appenders, lay-outs en filters aan de hand van praktische voorbeelden.

In Log4J2 is een appender gewoon een bestemming voor logboekgebeurtenissen; het kan zo simpel zijn als een console en kan complex zijn zoals elk RDBMS. Lay-outs bepalen hoe de logboeken worden gepresenteerd en filters filteren de gegevens op basis van de verschillende criteria.

2. Installatie

Om de verschillende logboekcomponenten en hun configuratie te begrijpen, gaan we verschillende test use-cases opzetten, elk bestaande uit een log4J2.xml configuratiebestand en een JUnit 4 test klasse.

Twee maven-afhankelijkheden zijn gemeenschappelijk voor alle voorbeelden:

 org.apache.logging.log4j log4j-core 2.7 org.apache.logging.log4j log4j-core 2.7 testjarentest 

Naast de belangrijkste log4j-core pakket moeten we de ‘test jar 'toevoegen die bij het pakket hoort om toegang te krijgen tot een contextregel die nodig is voor het testen van ongewoon genoemde configuratiebestanden.

3. Standaardconfiguratie

ConsoleAppender is de standaardconfiguratie van de Log4J 2 kernpakket. Het logt berichten op de systeemconsole in een eenvoudig patroon:

Laten we de tags in deze eenvoudige XML-configuratie analyseren:

  • Configuratie: Het wortelelement van een Log4J 2 configuratiebestand en kenmerk toestand is het niveau van de interne Log4J-gebeurtenissen die we willen loggen
  • Appenders: Dit element bevat een of meer appenders. Hier zullen we een appender configureren die standaard naar de systeemconsole wordt uitgevoerd
  • Loggers: Dit element kan bestaan ​​uit meerdere geconfigureerde Logger elementen. Met het bijzondere Wortel tag kunt u een naamloze standaard logger configureren die alle logberichten van de applicatie zal ontvangen. Elke logger kan op een minimaal log-niveau worden ingesteld
  • Appender Ref: Dit element definieert een verwijzing naar een element uit de Appenders sectie. Daarom is het kenmerk ‘ref‘Is gekoppeld aan een appenders’naam‘Kenmerk

De bijbehorende unit-test zal op dezelfde manier eenvoudig zijn. We krijgen een Logger referentie en print twee berichten:

@Test openbare leegte gegevenLoggerWithDefaultConfig_whenLogToConsole_thanOK () gooit uitzondering {Logger logger = LogManager.getLogger (getClass ()); Uitzondering e = nieuwe RuntimeException ("Dit is maar een test!"); logger.info ("Dit is een eenvoudig bericht op INFO-niveau." + "Het zal worden verborgen."); logger.error ("Dit is een eenvoudig bericht op ERROR-niveau." + "Dit is het minimaal zichtbare niveau.", e); } 

4. ConsoleAppender Met PatternLayout

Laten we een nieuwe console-appender definiëren met een aangepast kleurenpatroon in een apart XML-bestand, en dat opnemen in onze hoofdconfiguratie:

Dit bestand gebruikt enkele patroonvariabelen die worden vervangen door Log4J 2 tijdens runtime:

  • % style {…} {colorname}: Hierdoor wordt de tekst in het eerste paar haakjes () in een bepaalde kleur (kleurnaam).
  • % highlight {…} {FATAL = kleurnaam,…}: Dit is vergelijkbaar met de 'style'-variabele. Maar voor elk stamniveau kan een andere kleur worden opgegeven.
  • %datumnotatie}: Dit wordt vervangen door de huidige datum in het opgegeven formaat. Hier gebruiken we de ‘STANDAARD'-datum / tijd-indeling, jjjj-MM-dd UU: mm: ss, SSS '.
  • % -5niveau: Drukt het niveau van het logbericht rechts uitgelijnd af.
  • %bericht: Vertegenwoordigt het onbewerkte logboekbericht

Maar er zijn veel meer variabelen en opmaak in het PatternLayout. U kunt ze verwijzen naar de officiële documentatie van Log4J 2.

Nu zullen we de gedefinieerde console-appender opnemen in onze hoofdconfiguratie:

De eenheidstest:

@Test openbare leegte gegevenLoggerWithConsoleConfig_whenLogToConsoleInColors_thanOK () gooit uitzondering {Logger logger = LogManager.getLogger ("CONSOLE_PATTERN_APPENDER_MARKER"); logger.trace ("Dit is een gekleurd bericht op TRACE-niveau."); ...} 

5. Async-bestand toevoegen met JSONLayout en BurstFilter

Soms is het handig om logboekberichten asynchroon te schrijven. Als de prestaties van applicaties bijvoorbeeld voorrang hebben op de beschikbaarheid van logboeken.

In dergelijke gevallen kunnen we een AsyncAppender.

Voor ons voorbeeld configureren we een asynchroon JSON log-bestand. Verder zullen we een burst-filter toevoegen dat de loguitvoer met een bepaalde snelheid beperkt:

   ...          ...        

Let erop dat:

  • De JSONLayout is zo geconfigureerd dat er één logboekgebeurtenis per rij wordt geschreven
  • De BurstFilter zal elk evenement met ‘INFO'-niveau en hoger laten vallen als er meer dan twee zijn, maar bij een maximum van 10 gevallen evenementen
  • De AsyncAppender is ingesteld op een buffer van 80 logboekberichten; daarna wordt de buffer doorgespoeld naar het logbestand

Laten we eens kijken naar de bijbehorende unit-test. We vullen de toegevoegde buffer in een lus, laten deze naar schijf schrijven en inspecteren het aantal regels van het logbestand:

@Test openbare leegte gegevenLoggerWithAsyncConfig_whenLogToJsonFile_thanOK () gooit uitzondering {Logger logger = LogManager.getLogger ("ASYNC_JSON_FILE_APPENDER"); laatste int count = 88; for (int i = 0; i 0 && logEventsCount <= count); }

6. RollingFile Appender en XMLLayout

Vervolgens maken we een rollend logboekbestand. Na een geconfigureerde bestandsgrootte wordt het logboekbestand gecomprimeerd en geroteerd.

Deze keer gebruiken we een XML indeling:

Let erop dat:

  • De RollingFile appender heeft een ‘filePattern'-attribuut, dat wordt gebruikt om geroteerde logboekbestanden een naam te geven en kan worden geconfigureerd met tijdelijke variabelen. In ons voorbeeld moet het een datum en een teller bevatten voor het achtervoegsel van het bestand.
  • De standaardconfiguratie van XMLLayout zal enkele logboekgebeurtenisobjecten schrijven zonder het root-element.
  • We gebruiken een op grootte gebaseerd beleid voor het roteren van onze logbestanden.

Onze eenheidstestklasse ziet eruit als die uit de vorige sectie:

@Test openbare leegte gegevenLoggerWithRollingFileConfig_whenLogToXMLFile_thanOK () genereert uitzondering {Logger logger = LogManager.getLogger ("XML_ROLLING_FILE_APPENDER"); laatste int count = 88; for (int i = 0; i <count; i ++) {logger.info ("Dit is een rollend XML-bericht # {} op INFO-niveau.", i); }}

7. Syslog Appender

Laten we zeggen dat we geregistreerde gebeurtenissen via het netwerk naar een externe machine moeten sturen. De eenvoudigste manier om dat te doen met Log4J2 zou zijn Syslog Appender:

   ...     ...        

De attributen in het Syslog label:

  • naam: definieert de naam van de appender, en moet uniek zijn. Omdat we meerdere Syslog-appenders kunnen hebben voor dezelfde applicatie en configuratie
  • formaat: het kan worden ingesteld op BSD of RFC5424, en de Syslog-records zouden dienovereenkomstig worden opgemaakt
  • host & poort: de hostnaam en poort van de externe Syslog-servermachine
  • protocol: of u TCP of UPD wilt gebruiken
  • faciliteit: naar welke Syslog-faciliteit het evenement zal worden geschreven
  • connectTimeoutMillis: wachttijd op een tot stand gebrachte verbinding, standaard ingesteld op nul
  • reconnectionDelayMillis: tijd om te wachten voordat u opnieuw probeert verbinding te maken

8. FailoverAppender

Nu kunnen er gevallen zijn waarin een appender de logboekgebeurtenissen niet verwerkt en we de gegevens niet willen verliezen. In dergelijke gevallen is het FailoverAppender is handig.

Als het Syslog appender slaagt er niet in om gebeurtenissen naar de externe machine te verzenden, in plaats van die gegevens te verliezen waarop we mogelijk terugvallen FileAppender tijdelijk.

De FailoverAppender neemt een primaire appender en het aantal secundaire appenders. In het geval dat de primaire mislukt, probeert het de logboekgebeurtenis met secundaire te verwerken totdat een slaagt of er geen secondaries zijn om te proberen:

Laten we het testen:

@Test openbare leegte gegevenLoggerWithFailoverConfig_whenLog_thanOK () genereert uitzondering {Logger logger = LogManager.getLogger ("FAIL_OVER_SYSLOG_APPENDER"); Uitzondering e = nieuwe RuntimeException ("Dit is maar een test!"); logger.trace ("Dit is een syslog-bericht op TRACE-niveau."); logger.debug ("Dit is een syslog-bericht op DEBUG-niveau."); logger.info ("Dit is een syslog-bericht op INFO-niveau. Dit is het minimaal zichtbare niveau."); logger.warn ("Dit is een syslog-bericht op WARN-niveau."); logger.error ("Dit is een syslog-bericht op ERROR-niveau.", e); logger.fatal ("Dit is een syslog-bericht op FATAL-niveau."); }

9. JDBC Appender

De JDBC-appender verzendt logboekgebeurtenissen naar een RDBMS met behulp van standaard JDBC. De verbinding kan worden verkregen met behulp van elke JNDI-gegevensbron of elke verbindingsfabriek.

De basisconfiguratie bestaat uit een Databron of ConnectionFactory, ColumnConfigs en tafel naam:

Laten we nu eens proberen:

@Test openbare leegte gegevenLoggerWithJdbcConfig_whenLogToDataSource_thanOK () genereert uitzondering {Logger logger = LogManager.getLogger ("JDBC_APPENDER"); laatste int count = 88; for (int i = 0; i <count; i ++) {logger.info ("Dit is JDBC-bericht # {} op INFO-niveau.", count); } Verbindingsverbinding = ConnectionFactory.getConnection (); ResultSet resultSet = connection.createStatement () .executeQuery ("SELECTEER AANTAL (*) ALS ROW_COUNT UIT logboeken"); int logCount = 0; if (resultSet.next ()) {logCount = resultSet.getInt ("ROW_COUNT"); } assertTrue (logCount == count); }

10. Conclusie

Dit artikel toont zeer eenvoudige voorbeelden van hoe u verschillende logboekregistratie-appenders, filters en lay-outs kunt gebruiken met Log4J2 en manieren om ze te configureren.

De voorbeelden die bij het artikel horen, zijn beschikbaar op GitHub.