Articles

hoe Log4J2 werkt: 10 manieren om er het meeste uit te halen

Log4j2 is de bijgewerkte versie van de populaire en invloedrijke log4j-bibliotheek, die gedurende vele jaren veel gebruikt wordt in het hele Java-ecosysteem. Versie 2.x behoudt alle logging functies van zijn voorganger en bouwt voort op die basis met een aantal belangrijke verbeteringen, vooral op het gebied van prestaties.

en natuurlijk, gezien hoe instrumenteel loggen is voor elke toepassing, zowel voor audit als voor debugging doeleinden, is het kiezen van een solide logboekbibliotheek een heel belangrijke beslissing.

In de volgende secties gaan we kijken waarom de log4j2 bibliotheek een geweldige keuze is voor die beslissing en hoe we het kunnen gebruiken in een toepassing.

basis Log4j2 configuratie

om log4j2 in uw project te gebruiken, moet u simpelweg de log4j-Core afhankelijkheid toevoegen. Als u Maven gebruikt, kunt u de volgende afhankelijkheid aan uw pom toevoegen.xml-bestand:

en als u met Gradle werkt, moet u de afhankelijkheid aan de build toevoegen.gradle file:

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

uit het kader zal log4j2 automatisch een eenvoudige configuratie leveren, als u er zelf niet expliciet een definieert. De standaardconfiguratie logt naar de console op een FOUTNIVEAU of hoger.

om berichten te loggen met deze basisconfiguratie, hoeft u alleen maar een logger-instantie te verkrijgen met behulp van de LogManager-klasse:

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

dan kunt u het logger-object gebruiken met methoden die overeenkomen met het gewenste logniveau:

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

aanpassen van de Log4j2-configuratie

een aangepaste log4j2-configuratie kan programmatisch of via een configuratiebestand worden gemaakt.

de bibliotheek ondersteunt config bestanden geschreven in XML, JSON, YAML, evenals de .eigenschappen formaat. Hier gaan we XML gebruiken om alle voorbeelden in de eerste plaats te bespreken.

eerst kunt u de standaard configuratie overschrijven door simpelweg een log4j2 aan te maken.xml-bestand op het klasspad:

laten we eens een kijkje nemen op de tags die gebruikt worden in deze eenvoudige configuratie:

  • configuratie: het root-element van een log4j2-configuratiebestand; het status-attribuut vertegenwoordigt het niveau waarop interne log4j-gebeurtenissen moeten worden gelogd
  • Appenders: dit element bevat een lijst met appenders; in ons voorbeeld wordt een appender gedefinieerd die overeenkomt met de systeemconsole
  • Loggers: dit element bevat een lijst met Logger-instanties. Het root element is een standaard logger die alle berichten

uitzendt het is belangrijk om te begrijpen dat de Root logger verplicht is in elke configuratie. Zoals besproken, als je er geen opgeeft, wordt het automatisch standaard geconfigureerd met een Console-appender en het FOUTLOGBOEKNIVEAU.

Appenders configureren

in de log4j2-architectuur is een appender in principe verantwoordelijk voor het verzenden van logberichten naar een bepaalde uitvoerbestemming.

Hier zijn enkele van de meest bruikbare typen appenders die de bibliotheek biedt:

  • ConsoleAppender – logs berichten tot de Systeem console
  • FileAppender – schrijft log-berichten naar een bestand
  • RollingFileAppender – schrijft de berichten om een rollend log bestand
  • JDBCAppender – maakt gebruik van een relationele database voor logs
  • AsyncAppender – bevat een lijst van andere appenders en bepaalt de logboeken voor deze worden geschreven in een aparte thread

om beter Te begrijpen hoe appenders werk, laten we eens kijken naar een aantal configuratie voorbeelden.

de RollingFileAppender

alles in een enkel bestand inloggen is natuurlijk niet ideaal. Het is meestal veel beter om regelmatig over het actieve logbestand te rollen – dat is precies wat de RollingFileAppender doet.

u kunt ook verder gaan dan de basis met dit type appender en zowel een aangepast triggerbeleid als een rolloverstrategie configureren.

het triggerbeleid bepaalt wanneer het logbestand wordt gerold, wat betekent dat er een nieuw bestand wordt aangemaakt, terwijl de rolloverstrategie bepaalt hoe het bestand wordt gerold.

als snel voorbeeld, laten we een appender instellen die een nieuw logbestand maakt op basis van 3 beleidsregels:

  • OnStartupTriggeringPolicy – een nieuw logbestand wordt aangemaakt elke keer dat de JVM start
  • TimeBasedTriggeringPolicy – het logbestand wordt gerold op basis van een datum/tijd patroon
  • SizeBasedTriggeringPolicy – het bestand wordt gerold wanneer het een bepaalde grootte bereikt

de configuratie zal de defaultrolloverstrategie gebruiken:

u kunt zien hoe flexibel deze stijl van configuratie is, en hoe u de exacte semantiek van uw logging strategie kunt afstemmen – tot in het kleinste detail.

de JDBCAppender

zoals de naam al doet vermoeden, gebruikt deze appender JDBC om logs naar een relationele database te schrijven.

voor deze configuratie moet u een Verbindingsbron definiëren, die een JNDI-gegevensbron of een aangepaste Verbindingsfactory kan zijn. De logger gebruikt de ConnectionSource om JDBC-verbindingen te krijgen, daarom is het belangrijk om een verbindingspool te gebruiken voor betere prestaties.

om de appender in het XML-configuratiebestand te configureren, kunt u de JDBC-tag gebruiken:

zoals u kunt zien, wordt de JNDI-gegevensbron eenvoudig opgegeven met behulp van de jndiname-attribuut van de DataSource-tag. Samen met de Verbindingsbron, kunt u de tabel en de kolommen te gebruiken voor het opslaan van de loggegevens definiëren.

de FailoverAppender

ten slotte, laten we eens een kijkje nemen op de FailoverAppender; dit definieert een primaire appender en een lijst van back-ups die zullen stappen om de logging af te handelen in het geval de primaire mislukt.

bijvoorbeeld, u kunt een primaire JDBCAppender configureren, met een secundaire de RollingFile en Console appenders in het geval een database verbinding niet kan worden gemaakt:

In een productieomgeving is het altijd een goed idee om een failover strategie voor uw logging mechanisme te hebben.

lay-outs configureren

terwijl de appenders verantwoordelijk zijn voor het verzenden van logberichten naar een bestemming, worden de lay-outs gebruikt door appenders om te bepalen hoe een logbericht zal worden opgemaakt.

Hier is een korte beschrijving van enkele van de meest gebruikte lay-outs die log4j2 biedt:

  • PatternLayout-configureert berichten volgens een Stringpatroon
  • JsonLayout – definieert een JSON – indeling voor logberichten
  • CsvLayout-kan worden gebruikt om berichten in een CSV-indeling aan te maken

The PatternLayout

het eerste type opmaak waar we naar gaan kijken is de PatternLayout. Dit is een vrij flexibele oplossing die u veel controle geeft over de uiteindelijke uitvoer van het Logbericht.

het mechanisme wordt voornamelijk aangedreven door een conversiepatroon dat conversie-specificaties bevat. Elke specifier begint met het % teken, gevolgd door modifiers die dingen zoals breedte en kleur van het bericht regelen, en een conversie teken dat de inhoud vertegenwoordigt, zoals datum of thread naam.

laten we eens kijken naar een voorbeeld van het configureren van een PatternLayout die logregels configureert om de datum, thread, logniveau en Logbericht te tonen met verschillende kleuren voor verschillende logniveaus:

deze specificaties zijn de moeite waard om in detail te begrijpen, dus laten we eens nader kijken:

  • %d{HH:mm:ss.SSS} – geeft de datum van de log gebeurtenis in het opgegeven formaat
  • %t – geeft de thread naam
  • %level – geeft het log niveau van het bericht
  • %highlight{%level} – wordt gebruikt om de kleuren te definiëren voor het patroon tussen accolades
  • %msg%n – geeft het log bericht

De output zal de log niveaus met verschillende kleuren weergeven:

u kunt meer lezen over de volledige set van opties voor het definiëren van patronen in de log4j2 documentatie op patternlayout.

de Jsonlayout

Logging data met behulp van het JSON formaat heeft een aantal belangrijke voordelen, zoals het gemakkelijker maken van de logs te analyseren en te verwerken door het loggen gereedschappen langs de lijn.

om de JSONLayout in log4j2 te configureren, kunt u eenvoudig de bijbehorende tag definiëren:

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

instelling compleet = true zal een goed gevormd JSON-document produceren:

om JSON te kunnen produceren, moet u ook de Jackson-databindbibliotheek toevoegen aan het classpath:

Filters configureren

Filters in log4j2 worden gebruikt om te bepalen of een logbericht moet worden verwerkt of overgeslagen.

een filter kan worden geconfigureerd voor de gehele configuratie of op logger-of appender-niveau.

de bibliotheek biedt verschillende soorten filters die gebruikt kunnen worden:

  • BurstFilter-bepaalt het aantal toegestane loggebeurtenissen
  • Dynamictherhoudfilter – filtert logregels op basis van bepaalde attributen
  • RegexFilter – filtert berichten op basis van of ze overeenkomen met een reguliere expressie

u kunt bijvoorbeeld de snelheid bepalen waarmee de toepassing gegevens mag loggen.

om dit te doen, kunt u een BurstFilter instellen en dat toepassen op INFO-berichten:

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

Dit zal selectief de controle van het verkeer van INFO level berichten en lager negeren terwijl u ervoor zorgt dat u geen van de belangrijkste berichten boven INFO verliest.

in dit geval definieert de snelheid De gemiddelde logboekberichten die per seconde moeten worden verwerkt, en maxBurst bepaalt de totale grootte van de Traffic burst voordat het filter logboekvermeldingen begint te elimineren.

Op dezelfde manier kunnen we de appender alleen configureren om logberichten te accepteren die overeenkomen met een specifieke reguliere expressie:

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

over het algemeen kan dit filtermechanisme met grote precisie worden gebruikt om ervoor te zorgen dat elke appender in uw algemene logboekconfiguratie de juiste informatie volgt. De mogelijkheid om alleen zeer specifieke en relevante informatie te loggen leidt over het algemeen tot een zeer snelle analyse van de onderliggende oorzaak, vooral in complexe systemen – vooral wanneer gekoppeld aan een krachtige logweergave tool.

Loggers configureren

naast de Root logger kunnen we ook extra Loggerelementen definiëren met verschillende logniveaus, appenders of filters. Elke Logger heeft een naam nodig die later gebruikt kan worden om ernaar te verwijzen:

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

om logberichten te schrijven met behulp van deze specifieke Logger, kunt u een referentie krijgen met behulp van de LogManager class:

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

een andere veel voorkomende manier om de hiërarchie van deze loggers te structureren is gebaseerd op de Java class:

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

met behulp van lookups

lookups vertegenwoordigen een manier om externe waarden in te voegen in de log4j2 configuratie. We hebben al een voorbeeld gezien van de datum lookup in de RollingFileAppender configuratie:

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

De ${date:yyy-MM} lookup zal de huidige datum in de bestandsnaam invoegen, terwijl de voorgaande $ een escape-teken is, om de lookup-expressie in het attribuut filePattern in te voegen.

U kunt ook waarden voor Systeemeigenschappen invoegen in log4j2-configuratie met het formaat ${sys:property_name}:

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

een ander type informatie dat u kunt opzoeken en invoegen is Java-omgevingsinformatie:

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

u kunt meer details vinden over het soort gegevens dat u kunt invoegen via lookups in de log4j2 documentatie.

programmatische configuratie

naast configuratiebestanden kan log4j2 ook programmatisch worden geconfigureerd. Er zijn een paar verschillende manieren om dat te doen:

  • Maak een aangepaste Configuratiefactory
  • gebruik de configurator class
  • wijzig de configuratie na initialisatie
  • combineer eigenschappen bestanden en programmatische configuratie

laten we eens kijken hoe je een lay-out kunt configureren en programmatisch toevoegen:

Vervolgens kun je een logger definiëren met behulp van de loggerconfig class, associate the toevoegen aan het, en update de configuratie:

dan kunt u de logger zoals gewoonlijk gebruiken:

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

Deze stijl van vloeiende API kan leiden tot een snellere ontwikkeling en iteratie op complexere logconfiguraties omdat u nu profiteert van de voordelen van direct werken met Java-code.

echter, aangezien XML nog steeds leesbaarder en compacter kan zijn, kunt u de configuratie vaak programmatisch ontwikkelen en vervolgens naar XML converteren als alles klaar is.

aangepaste Log niveaus

De ingebouwde log niveaus voor log4j2 zijn:

  • OFF
  • FATAL
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE
  • ALL

naast deze, kunt u ook een aangepast logniveau definiëren volgens uw toepassingsbehoeften.

bijvoorbeeld, om dit nieuwe logniveau te definiëren, kunt u gebruik maken van het niveau.FORNAME () API-het opgeven van de nieuwe niveau naam en een geheel getal dat de plaats van het niveau in de log levels hiërarchie vertegenwoordigt:

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

om te bepalen welke integer waarde moet worden gebruikt, kunt u een kijkje nemen op de waarden gedefinieerd voor de andere log niveaus in de log4j2 documentatie:

de waarde 350 zet het niveau tussen WARN en INFO, wat betekent dat de berichten worden weergegeven wanneer het niveau is ingesteld op INFO of hoger.

om een bericht op Aangepast niveau te loggen, moet u de methode log() gebruiken:

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

de equivalente XML-configuratie kan zijn:

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

dan kan het worden gebruikt via de standaard log API:

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

de nieuwe aangepaste niveaus zullen op dezelfde manier worden weergegeven als de standaard niveaus:

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

migreren van Log4j 1.x

Als u een toepassing migreert met de 1.x versie van de bibliotheek naar de huidige 2.X versie, er zijn een paar routes die u kunt volgen:

  • gebruik de log4j 1.x bridge
  • handmatig de API bijwerken en de configuratie

met behulp van de bridge is triviaal. U hoeft alleen de log4j afhankelijkheid te vervangen door log4j-1.2-api bibliotheek:

hoewel dit de snellere methode is, heeft het nadeel dat het beperkt is in het type configuratie dat geconverteerd kan worden.

De handmatige methode is natuurlijk meer werk, maar zal uiteindelijk leiden tot een meer flexibele en krachtige logging oplossing.

Hier zijn enkele van de meest voorkomende wijzigingen die u moet doen:

conclusie

logbestanden zijn cruciaal in elke productieomgeving, en het kiezen van een goede logoplossing kan het verschil zijn tussen 5 minuten besteden en een volledige dag besteden om een probleem in de productie te begrijpen.

Log4j2 is een krachtige en robuuste logging oplossing voor moderne Java-toepassingen, met een breed scala aan configuratie-opties.

Het maakt eenvoudige configuratie van geavanceerde logging best practices zoals rollende bestanden, verschillende soorten logging output bestemmingen, ondersteuning voor gestructureerde logging formaten zoals JSON of XML, met behulp van meerdere loggers en filters, en aangepaste log niveaus.

ten slotte, wanneer je verder moet gaan dan het handmatig analyseren van loggegevens, bekijk dan zeker de logboekmogelijkheden die zijn opgenomen in Retrace APM.