2.1 Første logger - log4j

Som du allerede vet, begynte historien til logger med System.err.println()utdata av en post til konsollen. Den brukes fortsatt aktivt til feilsøking, for eksempel bruker Intellij IDEA den til å vise feilmeldinger til konsollen. Men dette alternativet har ingen innstillinger, så la oss gå videre.

Den første og mest populære loggeren ble kalt Log4j. Det var en god og svært tilpassbar løsning. På grunn av ulike omstendigheter kom denne avgjørelsen aldri inn i JDK, noe som opprørte hele samfunnet sterkt.

Denne loggeren var ikke bare i stand til å logge, den ble laget av programmerere for programmerere og lot dem løse problemer som stadig oppsto i forbindelse med logging.

Som du allerede vet, blir logger skrevet til slutt slik at noen leser dem og prøver å forstå hva som skjedde under programmets drift - hva og når gikk galt som forventet.

Det log4jvar tre ting for dette:

  • underpakke logging;
  • sett med vedlegg (resultater);
  • hot reload-innstillinger.

For det første kan innstillingene log4jskrives på en slik måte at de aktiverer pålogging i en pakke og deaktiverer den i en annen. For eksempel var det mulig å aktivere pålogging i com.codegym.server, men deaktivere den i com.codegym.server.payment. Dette gjorde det mulig å raskt fjerne unødvendig informasjon fra loggen.

For det andre log4jtillot det å skrive loggresultater til flere loggfiler samtidig. Og utgangen til hver kan konfigureres individuelt. For eksempel, i en fil var det mulig å skrive bare informasjon om alvorlige feil, i en annen - logger fra en bestemt modul, og i en tredje - logger for en viss tid.

Hver loggfil ble dermed innstilt på en bestemt type forventet problem. Dette forenkler livet til programmerere som ikke liker å se gjennom gigabyte-loggfiler manuelt.

Og til slutt, for det tredje, log4jtillot det å endre logginnstillingene direkte mens programmet kjørte, uten å starte det på nytt. Dette var veldig nyttig når det var nødvendig å rette arbeidet med loggene for å finne tilleggsinformasjon om en spesifikk feil.

Viktig! Det er to versjoner av loggen log4j: 1.2.x og 2.xx , som er inkompatible med hverandre .

Du kan koble loggeren til prosjektet ved å bruke koden:

<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
  </dependency>
 
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
  </dependency>
</dependencies>

2.2 Første offisielle logger - JUL: java.util.logging

Etter at dyrehagen av loggere dukket opp i Java-fellesskapet, bestemte utviklerne JDKseg for å lage en standard logger som alle ville bruke. Slik så loggeren ut JUL: pakke java.util.logging.

Under utviklingen tok imidlertid skaperne av loggeren ikke log4j, men en variant av loggeren fra IBM, som påvirket utviklingen. Den gode nyheten er at loggeren JULer inkludert JDK, den dårlige nyheten er at få mennesker bruker den.

JUL

JULIkke bare laget utviklerne "en annen universell standard" , de laget også sine egne loggingsnivåer for den, som skilte seg fra de som ble akseptert av populære loggere på den tiden.

Og det var et stort problem. Tross alt er produkter Javaofte samlet inn fra et stort antall biblioteker, og hvert slikt bibliotek hadde sin egen logger. Så det var nødvendig å konfigurere alle loggerne som er i applikasjonen.

Selv om loggeren i seg selv er ganske bra. Å lage en logger er mer eller mindre det samme. For å gjøre dette, må du importere:


java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());

Klassenavnet er spesielt bestått for å vite hvor loggingen kommer fra.

Bare med utgivelsen løste utviklerne viktige problemer, hvoretter det JULer veldig praktisk å bruke. Før det var det en slags annenrangs logger.

Denne loggeren støtter også lambda-uttrykk og lat evaluering. Fra og med Java 8, kan du bestå Supplier<String>. Dette hjelper å lese og lage en streng kun i det øyeblikket det virkelig trengs, og ikke hver gang, slik det var før.

Metoder med et argument Supplier<String> msgSupplierser slik ut:

public void info(Supplier msgSupplier) {
   log(Level.INFO, msgSupplier);
}

2.3 First logger wrapper - JCL: jakarta commons logging

Lenge var det ingen enkelt standard blant tømmerhoggere, den JULskulle ha blitt en, men det var verre log4j, så en enkelt standard dukket aldri opp. Men en hel dyrehage med tømmerhoggere dukket opp, som hver ønsket å bli den samme.

JCL

Vanlige Java-utviklere likte imidlertid ikke at nesten hvert bibliotek har sin egen logger og må konfigureres på en eller annen måte på en spesiell måte. Derfor bestemte samfunnet seg for å lage en spesiell innpakning over andre loggere - dette er hvordanJCL: jakarta commons logging

Og igjen, prosjektet, som ble opprettet for å være en leder, ble ikke det. Du kan ikke lage en vinner, du kan bare bli en vinner. Funksjonaliteten JCLvar svært dårlig og ingen ønsket å bruke den. Loggeren, designet for å erstatte alle loggere, møtte samme skjebne da den JULikke ble brukt.

Selv om det har blitt lagt til mange biblioteker utgitt av Apache-samfunnet, har dyrehagen av tømmerhoggere bare vokst.

2.4 Første siste logger - Loggtilbake

Men det er ikke alt. Utvikleren log4jbestemte at han var den smarteste (vel, tross alt brukte de fleste loggeren hans) og bestemte seg for å skrive en ny forbedret logger som ville kombinere fordelene log4jtil andre loggere.

Den nye loggeren ble kalt Logback. Det var denne loggeren som skulle bli den fremtidige enkeltloggeren som alle skulle bruke. Den var basert på samme idé som i log4j.

Du kan koble denne loggeren til prosjektet ved å bruke koden:


<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.6</version>
</dependency>

Forskjellene var i Logback:

  • forbedret ytelse;
  • lagt til innfødt støtte slf4j;
  • utvidet filtreringsalternativ.

En annen fordel med denne loggeren var at den hadde veldig gode standardinnstillinger. Og du måtte konfigurere loggeren bare hvis du ville endre noe i dem. Innstillingsfilen var også bedre tilpasset bedriftens programvare - alle dens konfigurasjoner ble satt som xml/.

Som standard Logbackkrever den ingen innstillinger og registrerer alle logger fra nivået DEBUGog over. Hvis du trenger annen oppførsel, kan den konfigureres via xmlkonfigurasjon:

<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
    <root level="info">
        <appender-ref ref="FILE" />
    </root>
</configuration>

2.5 Siste universallogger - SLF4J: Enkel loggingsfasade for Java

Hvor lang tid kan det være å finne den gyldne middelvei...

I 2006 forlot en av skaperne log4jprosjektet og bestemte seg for å prøve igjen for å lage en universell logger. Men denne gangen var det ikke en ny logger, men en ny universell standard (wrapper) som gjorde at forskjellige loggere kunne samhandle sammen.

Denne loggeren ble kalt slf4j — Simple Logging Facade for Java, det var en innpakning rundt log4j, JUL, common-loggins and logback. Denne loggeren løste et reelt problem - å administrere en dyrehage med loggere, så alle begynte umiddelbart å bruke den.

Vi løser heroisk problemene vi skaper for oss selv. Som du kan se, har fremgangen nådd det punktet at vi har laget en omslag over omslaget ...

Selve innpakningen består av to deler:

  • API, som brukes i applikasjoner;
  • Implementeringer som legges til som separate avhengigheter for hver logger.

Du kan koble loggeren til prosjektet ved å bruke koden:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.2</version>
</dependency>

Det er nok å koble til riktig implementering, og det er det: hele prosjektet vil jobbe med det.

2.6 Optimalisering i slf4j

Slf4jstøtter alle nye funksjoner som strengformatering for logging . Før dette var det et slikt problem. La oss si at du vil skrive ut en melding til loggen:

log.debug("User " + user + " connected from " + request.getRemoteAddr());

Det er et problem med denne koden. Anta at applikasjonen din fungerer på productionog ikke skriver noe til loggen DEBUG-messages, men metoden log.debug()vil fortsatt bli kalt, og når den kalles, vil følgende metoder også bli kalt:

  • user.toString();
  • request.getRemoteAddr();

Å kalle disse metodene bremser applikasjonen. Anropet deres er bare nødvendig under feilsøking, men de blir anropt likevel.

Fra et logisk synspunkt måtte dette problemet løses i selve loggbiblioteket. Og i den første versjonen av log4j kom løsningen opp:

if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}

I stedet for én linje for loggen, var det nå nødvendig å skrive tre. Noe som dramatisk forverret lesbarheten til koden, og reduserte populariteten til log4j.

Loggeren slf4jvar i stand til å forbedre situasjonen litt ved å tilby smart logging. Det så slik ut:

log.debug("User {} connected from {}", user, request.getRemoteAddr());

hvor {}angir innsetting av argumenter som er bestått i metoden. Det vil si at den første {}tilsvarer bruker, den andre {}tilsvarer request.getRemoteAddr().

Disse parameterne vil bare bli koblet sammen til en enkelt melding hvis loggingsnivået tillater logging. Ikke perfekt, men bedre enn alle de andre alternativene.

Etter det SLF4Jbegynte den å vokse raskt i popularitet, for øyeblikket er dette den beste løsningen.

Derfor vil vi vurdere å logge ved å bruke eksemplet med en bunt slf4j-log4j12.