Articles

hur Log4J2 fungerar: 10 sätt att få ut det mesta

Log4j2 är den uppdaterade versionen av det populära och inflytelserika log4j-biblioteket, som används i stor utsträckning i hela Java-ekosystemet i så många år. Version 2.x behåller alla loggningsfunktioner hos sin föregångare och bygger på den grunden med några betydande förbättringar, särskilt när det gäller prestanda.

och naturligtvis, med tanke på hur instrumental loggning är för alla applikationer, både för revision och felsökning, är det ganska viktigt att välja ett solidt loggbibliotek.

i följande avsnitt ska vi ta en titt på varför log4j2-biblioteket är ett utmärkt val för det beslutet och hur vi kan använda det i en applikation.

grundläggande Log4j2-konfiguration

för att börja använda log4j2 i ditt projekt behöver du bara lägga till log4j-kärnberoendet. Om du använder Maven kan du lägga till följande beroende till din pom.xml-fil:

och om du arbetar med Gradle måste du lägga till beroendet i byggnaden.gradle file:

dependencies { compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.8.2'}

ur lådan kommer log4j2 automatiskt att ge en enkel konfiguration, om du inte uttryckligen definierar en själv. Standardkonfigurationen loggar till konsolen på en nivå av felnivå eller högre.

för att börja logga meddelanden med den här grundläggande konfigurationen behöver du bara skaffa en Loggerinstans med LogManager-klassen:

private static Logger logger = LogManager.getLogger(MyService.class);

då kan du använda logger-objektet med metoder som motsvarar den loggnivå du vill ha:

logger.error("This is an error message");

anpassa Log4j2-konfigurationen

en anpassad log4j2-konfiguration kan skapas antingen programmatiskt eller genom en konfigurationsfil.

biblioteket stöder konfigurationsfiler skrivna i XML, JSON, YAML, liksom .egenskaper format. Här kommer vi att använda XML för att diskutera alla exempel främst.

först kan du åsidosätta standardkonfigurationen genom att helt enkelt skapa en log4j2.xml-fil på classpath:

låt oss titta närmare på taggarna som används i den här enkla konfigurationen:

  • konfiguration: rotelementet i en log4j2-konfigurationsfil; statusattributet representerar den nivå där interna log4j-händelser ska loggas
  • Appenders: detta element innehåller en lista med appenders; i vårt exempel definieras en appender som motsvarar systemkonsolen
  • Loggers: detta element innehåller en lista med Loggerinstanser. Rotelementet är en standardlogger som matar ut alla meddelanden

det är viktigt att förstå att Rotloggen är obligatorisk i varje konfiguration. Som diskuterats, om du inte tillhandahåller en, konfigureras den automatiskt som standard med en Konsoltillägg och FELLOGGSNIVÅN.

konfigurera Appenders

i log4j2-arkitekturen är en appender i princip ansvarig för att skicka loggmeddelanden till en viss utgångsdestination.

Här är några av de mest användbara typerna av tillägg som biblioteket tillhandahåller:

  • ConsoleAppender – loggar meddelanden till systemkonsolen
  • FileAppender – skriver loggmeddelanden till en fil
  • RollingFileAppender – skriver meddelandena till en rullande loggfil
  • JDBCAppender – använder en relationsdatabas för loggar
  • AsyncAppender – innehåller en lista över andra appenders och bestämmer loggarna för dessa som ska skrivas i en separat tråd

för att bättre förstå hur appenders fungerar, låt oss titta på några konfigurationsexempel.

RollingFileAppender

att logga in allt i en enda fil är naturligtvis inte idealiskt. Det är vanligtvis mycket bättre att rulla över den aktiva loggfilen regelbundet – vilket är exakt vad RollingFileAppender gör.

Du kommer också att kunna gå utöver grunderna med denna typ av appender och konfigurera både en anpassad utlösningspolicy och rollover-strategi.

utlösningsprincipen avgör när loggfilen rullas, vilket betyder att en ny fil skapas, medan rollover-strategin bestämmer hur filen rullas.

som ett snabbt exempel, låt oss konfigurera en appender som skapar en ny loggfil baserad på 3 principer:

  • OnStartupTriggeringPolicy – en ny loggfil skapas varje gång JVM startar
  • TimeBasedTriggeringPolicy – loggfilen rullas baserat på ett datum/tid mönster
  • SizeBasedTriggeringPolicy – filen rullas när den når en viss storlek

konfigurationen kommer att använda defaultrolloverstrategy:

Du kan se hur flexibel den här konfigurationsstilen är och hur du kan ställa in den exakta semantiken i din loggningsstrategi – till minsta detalj.

JDBCAppender

som namnet antyder använder denna appender JDBC för att skriva loggar till en relationsdatabas.

för den här konfigurationen måste du definiera en ConnectionSource, som kan vara antingen en JNDI-datakälla eller en anpassad ConnectionFactory. Loggen använder ConnectionSource för att få JDBC-anslutningar, varför det är viktigt att använda en anslutningspool för bättre prestanda.

för att konfigurera tillägget i XML-konfigurationsfilen kan du använda JDBC-taggen:

som du kan se är JNDI-datakällan helt enkelt specificerad med jndiname-attributet för DataSource-taggen. Tillsammans med ConnectionSource kan du definiera tabellen och kolumnerna som ska användas för att lagra loggdata.

FailoverAppender

slutligen, låt oss ta en titt på FailoverAppender; detta definierar en primär appender och en lista över säkerhetskopior som kommer att kliva in för att hantera loggningen om den primära misslyckas.

Du kan till exempel konfigurera en primär JDBCAppender, med en sekundär RollingFile-och Konsoltillägg om en databasanslutning inte kan upprättas:

i en produktionsmiljö är det alltid bra att ha en failover-strategi för din loggningsmekanism.

konfigurera layouter

medan appenders ansvarar för att skicka loggmeddelanden till en destination används layouterna av appenders för att definiera hur ett loggmeddelande ska formateras.

här är en kort beskrivning av några av de vanligaste layouterna som log4j2 erbjuder:

  • PatternLayout – konfigurerar meddelanden enligt ett Strängmönster
  • JsonLayout – definierar ett JSON – format för loggmeddelanden
  • CsvLayout-kan användas för att skapa meddelanden i ett CSV-format

PatternLayout

den första typen av layout vi ska titta på är PatternLayout. Det här är en ganska flexibel lösning som ger dig mycket kontroll över loggmeddelandets slutliga utgång.

mekanismen drivs främst av ett konverteringsmönster som innehåller konverteringsspecifikationer. Varje specifierare börjar med % – tecknet, följt av modifierare som styr saker som meddelandets bredd och färg, och ett konverteringstecken som representerar innehållet, till exempel datum eller trådnamn.

Låt oss titta på ett exempel på att konfigurera ett Mönsterlayout som konfigurerar loggrader för att visa datum, tråd, loggnivå och loggmeddelande med olika färger för olika loggnivåer:

dessa specifikationer är väl värda att förstå i detalj, så låt oss ta en närmare titt:

  • %d{HH:mm:ss.SSS} – matar ut datumet för logghändelsen i det angivna formatet
  • %t – matar ut trådnamnet
  • %level – visar loggnivån för meddelandet
  • %highlight{%level} – används för att definiera färgerna för mönstret mellan lockiga parenteser
  • %msg%n – matar ut loggmeddelandet

utgången visar loggnivåerna med olika färger:

Du kan läsa mer om hela uppsättningen av alternativ för att definiera mönster i log4j2 dokumentation på patternlayout.

Jsonlayout

Loggningsdata med JSON-formatet har några betydande fördelar, till exempel att göra loggarna enklare att analysera och bearbeta genom att logga verktyg längs linjen.

för att konfigurera JSONLayout i log4j2 kan du helt enkelt definiera motsvarande tagg:

<JSONLayout complete="true" compact="false"/>

inställning complete=true kommer att producera ett välformat JSON-dokument:

för att kunna producera JSON måste du också lägga till jackson-databind-biblioteket i klassvägen:

konfigurera filter

filter i log4j2 används för att avgöra om ett loggmeddelande ska behandlas eller hoppas över.

ett filter kan konfigureras för hela konfigurationen eller på logger-eller appender-nivå.

biblioteket innehåller flera typer av filter som kan användas:

  • BurstFilter – kontrollerar antalet logghändelser tillåtna
  • DynamicThresholdFilter – filtrerar loggrader baserade på vissa attribut
  • RegexFilter – filtrerar meddelanden baserat på om de matchar ett reguljärt uttryck

Du kan till exempel styra hastigheten med vilken applikationen får logga data.

För att göra det kan du ställa in ett BurstFilter och tillämpa det på informationsmeddelanden:

<Filters> <BurstFilter level="INFO" rate="10" maxBurst="100"/></Filters>

detta kommer selektivt ignorera kontrollera trafiken av info nivå meddelanden och nedan samtidigt som du ser till att du inte förlorar någon av de viktigare meddelandena ovan INFO.

i det här fallet definierar rate de genomsnittliga loggmeddelandena som ska behandlas per sekund, och maxBurst kontrollerar den totala storleken på trafikbrottet innan filtret börjar eliminera loggposter.

På samma sätt kan vi konfigurera tillägget bara för att acceptera loggmeddelanden som matchar ett specifikt Reguljärt uttryck:

<Appenders> <JDBC name="JDBCAppender"> <RegexFilter regex="*jdbc*" onMatch="ACCEPT" onMismatch="DENY"/> </JDBC></Appenders>

sammantaget kan denna filtreringsmekanism användas med stor precision för att se till att varje appender i din övergripande loggningskonfiguration spårar rätt information. Möjligheten att bara logga mycket specifik och relevant information leder generellt till mycket snabb grundorsaksanalys, särskilt i komplexa system-särskilt när de kombineras med ett kraftfullt loggvisningsverktyg.

konfigurera Loggers

förutom Rotloggern kan vi också definiera ytterligare Loggelement med olika loggnivåer, tillägg eller filter. Varje Logger kräver ett namn som kan användas senare för att referera till det:

<Loggers> <Logger name="RollingFileLogger"> <AppenderRef ref="RollingFileAppender" /> </Logger></Loggers>

för att skriva loggmeddelanden med den här loggen kan du få en referens till den med LogManager-klassen:

Logger rfLogger = LogManager.getLogger("RollingFileLogger");rfLogger.info("User info updated");

ett annat mycket vanligt sätt att strukturera hierarkin för dessa loggers är baserad på Java-klassen:

Logger logger = LogManager.getLogger(MyServiceTest.class);

använda uppslag

uppslag representerar ett sätt att infoga externa värden i log4j2-konfigurationen. Vi har redan sett ett exempel på datumuppslaget i RollingFileAppender-konfigurationen:

<RollingFile name="RollingFileAppender" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">

${date:yyy-MM} lookup kommer att infoga det aktuella datumet i filnamnet, medan föregående $ är ett escape-tecken, för att infoga lookup-uttrycket i filpattern-attributet.

Du kan också infoga Systemegenskapsvärden i log4j2-konfigurationen med formatet ${sys:property_name}:

<File name="ApplicationLog" fileName="${sys:path}/app.log"/>

en annan typ av information som du kan slå upp och infoga är Java miljöinformation:

<PatternLayout header="${java:version} - ${java:os}"> <Pattern>%d %m%n</Pattern></PatternLayout>

Du kan hitta mer information om vilken typ av data du kan infoga genom uppslag i sökningarna i log4j2 dokumentation.

programmatisk konfiguration

förutom konfigurationsfiler kan log4j2 också konfigureras programmatiskt. Det finns några olika sätt att göra det:

  • skapa en anpassad Konfigurationfactory
  • använd Konfiguratorklassen
  • ändra konfigurationen efter initialisering
  • kombinera egenskapsfiler och programmatisk konfiguration

Låt oss ta en titt på hur du konfigurerar en layout och appender programmatiskt:

därefter kan du definiera en logger med hjälp av LoggerConfig-klassen, associera appender till den och uppdatera konfigurationen:

sedan kan du börja använda loggen som vanligt:

Logger pLogger = LogManager.getLogger("programmaticLogger");pLogger.info("Programmatic Logger Message");

denna typ av flytande API kan leda till en snabbare utveckling och iteration på mer komplexa loggningskonfigurationer eftersom du nu drar nytta av fördelarna med att arbeta direkt med Java-kod.men med tanke på att XML fortfarande kan vara mer läsbart och kompakt kan du ofta utveckla konfigurationen programmatiskt och sedan konvertera den till XML när allt är klart.

anpassade Loggnivåer

de inbyggda loggnivåerna för log4j2 är:

  • OFF
  • FATAL
  • fel
  • varning
  • INFO
  • DEBUG
  • TRACE
  • Alla

utöver dessa kan du också definiera en anpassad loggnivå enligt dina applikationsbehov.

om du till exempel vill definiera den här nya loggnivån kan du använda nivån.forName () API-ange det nya nivånamnet och ett heltal som representerar platsen för nivån i loggnivåhierarkin:

Level myLevel = Level.forName("NEW_LEVEL", 350);

för att bestämma vilket heltal som ska användas kan du titta på de värden som definierats för de andra loggnivåerna i log4j2-dokumentationen:

350-värdet sätter nivån mellan WARN och INFO, vilket innebär att meddelandena visas när nivån är inställd på INFO eller högre.

för att logga ett meddelande på Anpassad nivå måste du använda log () – metoden:

logger.log(myLevel, "Custom Level Message");

motsvarande XML-konfiguration kan vara:

<CustomLevels> <CustomLevel name="NEW_XML_LEVEL" intLevel="350" /></CustomLevels>

då kan den användas via standard log API:

logger.log(Level.getLevel("NEW_XML_LEVEL"),"Custom XML Level Message");

de nya anpassade nivåerna visas på samma sätt som de vanliga:

11:28:23.558 NEW_LEVEL - Custom Level Message11:28:23.559 NEW_XML_LEVEL - Custom XML Level Message

Migrera från Log4j 1.x

om du migrerar ett program med 1.x version av biblioteket till nuvarande 2.X version, det finns ett par rutter du kan följa:

  • använd log4j 1.X bridge
  • uppdatera API manuellt och konfigurationen

med hjälp av bron är trivial. Du behöver bara ersätta log4j-beroendet med log4j-1.2-api-biblioteket:

även om detta är den snabbare metoden har den nackdelen att den är begränsad i den typ av konfiguration som kan konverteras.

den manuella metoden är naturligtvis mer arbete, men kommer så småningom att leda till en mer flexibel och kraftfull loggningslösning.

Här är några av de vanligaste typerna av ändringar du måste göra:

slutsats

loggfiler är kritiska i alla produktionsmiljöer, och att välja en bra loggningslösning kan vara skillnaden mellan att spendera 5 minuter och spendera en hel dag för att förstå ett problem i produktionen.

Log4j2 är en kraftfull och robust loggningslösning för moderna Java-applikationer, med ett brett utbud av konfigurationsalternativ.

det möjliggör enkel konfiguration av avancerade loggnings bästa praxis som rullande filer, olika typer av loggningsutgångsdestinationer, stöd för strukturerade loggningsformat som JSON eller XML, med flera loggers och filter och anpassade loggnivåer.

slutligen, när du behöver gå längre än att manuellt analysera loggdata, kolla definitivt loggningsfunktionerna som ingår i Retrace APM.