2.1 Første logger - log4j

Som du allerede ved, begyndte loghistorien med System.err.println()output af en post til konsollen. Den bruges stadig aktivt til fejlretning, for eksempel bruger Intellij IDEA den til at vise fejlmeddelelser til konsollen. Men denne mulighed har ingen indstillinger, så lad os gå videre.

Den første og mest populære logger hed Log4j. Det var en god og meget tilpasselig løsning. På grund af forskellige omstændigheder kom denne beslutning aldrig ind i JDK, hvilket i høj grad forstyrrede hele samfundet.

Denne logger var ikke bare i stand til at logge, den blev skabt af programmører til programmører og gav dem mulighed for at løse problemer, der konstant opstod i forbindelse med logning.

Som du allerede ved, bliver logs skrevet til sidst, så en person læser dem og forsøger at forstå, hvad der skete under programmets drift - hvad og hvornår gik galt som forventet.

Der log4jvar tre ting til dette:

  • logning af underpakke;
  • sæt af bilag (resultater);
  • hot reload indstillinger.

log4jFor det første kunne indstillingerne skrives på en sådan måde, at de aktiverer logning i én pakke og deaktiverer den i en anden. For eksempel var det muligt at aktivere logning i com.codegym.server, men deaktivere det i com.codegym.server.payment. Dette gjorde det muligt hurtigt at fjerne unødvendig information fra loggen.

For det andet log4jtillod det at skrive logningsresultater til flere logfiler på én gang. Og output til hver kunne konfigureres individuelt. For eksempel var det muligt i en fil kun at skrive information om alvorlige fejl, i en anden - logfiler fra et bestemt modul og i en tredje - logs for en bestemt tid.

Hver logfil blev således indstillet til en bestemt type forventet problem. Dette forenkler i høj grad livet for programmører, der ikke kan lide at gennemse gigabyte-logfiler manuelt.

Og endelig, for det tredje, log4jtillod det at ændre logindstillingerne direkte, mens programmet kørte, uden at genstarte det. Dette var meget praktisk, når det var nødvendigt at rette arbejdet i loggene for at finde yderligere information om en specifik fejl.

Vigtig! Der er to versioner af loggen log4j: 1.2.x og 2.xx , som er inkompatible med hinanden .

Du kan tilslutte loggeren til projektet ved hjælp af 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 officielle logger - JUL: java.util.logging

Efter at zoo af loggere dukkede op i Java-fællesskabet, besluttede udviklerne JDKat lave en standard logger, som alle ville bruge. Sådan så loggeren ud JUL: pakke java.util.logging.

Men under dens udvikling tog skaberne af loggeren som grundlag ikke log4j, men en variant af loggeren fra IBM, som påvirkede dens udvikling. Den gode nyhed er, at loggeren JULer inkluderet JDK, den dårlige nyhed er, at få mennesker bruger den.

JUL

Udviklerne JULlavede ikke kun "en anden universel standard" , de lavede også deres egne logningsniveauer for det, som adskilte sig fra dem, der blev accepteret af populære loggere på det tidspunkt.

Og det var et stort problem. Når alt kommer til alt, indsamles produkter Javaofte fra et stort antal biblioteker, og hvert sådant bibliotek havde sin egen logger. Så det var nødvendigt at konfigurere alle de loggere, der er i applikationen.

Selvom loggeren i sig selv er ret god. At oprette en logger er mere eller mindre det samme. For at gøre dette skal du importere:


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

Klassenavnet er specielt bestået for at vide, hvor logningen kommer fra.

Først med udgivelsen løste udviklerne vigtige problemer, hvorefter det JULer virkelig praktisk at bruge. Før det var det en slags andenrangs logger.

Denne logger understøtter også lambda-udtryk og doven evaluering. Fra og med Java 8, kan du bestå Supplier<String>. Dette hjælper til kun at læse og skabe en streng i det øjeblik, hvor det virkelig er nødvendigt, og ikke hver gang, som det var før.

Metoder med et argument Supplier<String> msgSupplierser således ud:

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

2.3 Første logger-indpakning - JCL: jakarta commons-logning

I lang tid var der ikke en enkelt standard blandt skovhuggere, den JULskulle være blevet en, men det var værre log4j, så en enkelt standard dukkede aldrig op. Men en hel zoologisk have af skovhuggere dukkede op, som hver især ønskede at blive den samme.

JCL

Men almindelige Java-udviklere kunne ikke lide, at næsten alle biblioteker har sin egen logger og skal konfigureres på en eller anden måde på en speciel måde. Derfor besluttede fællesskabet at skabe en speciel indpakning over andre loggere - sådan er detJCL: jakarta commons logging

Og igen blev projektet, som blev skabt for at være leder, ikke det. Du kan ikke skabe en vinder, du kan kun blive en vinder. Funktionaliteten JCLvar meget dårlig, og ingen ønskede at bruge den. Loggeren, designet til at erstatte alle loggere, mødte samme skæbne, da den JULikke blev brugt.

Selvom det er blevet tilføjet til mange biblioteker udgivet af Apache-samfundet, er den zoologiske have af skovhuggere kun vokset.

2.4 Første sidste logger - Logback

Men det er ikke alt. Udvikleren log4jbesluttede, at han var den klogeste (nå, de fleste brugte trods alt hans logger) og besluttede at skrive en ny forbedret logger, der ville kombinere fordelene log4jved andre loggere.

Den nye logger blev kaldt Logback. Det var denne logger, der skulle blive den fremtidige single logger, som alle ville bruge. Det var baseret på samme idé som i log4j.

Du kan forbinde denne logger til projektet ved hjælp af koden:

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

Forskellene var i Logback:

  • forbedret ydeevne;
  • tilføjet indbygget støtte slf4j;
  • udvidet filtreringsmulighed.

En anden fordel ved denne logger var, at den havde meget gode standardindstillinger. Og du skulle kun konfigurere loggeren, hvis du ville ændre noget i dem. Indstillingsfilen var også bedre tilpasset virksomhedens software - alle dens konfigurationer blev indstillet som xml/.

Som standard Logbackkræver det ingen indstillinger og registrerer alle logfiler fra niveauet DEBUGog derover. Hvis du har brug for anden adfærd, kan den konfigureres via xmlkonfiguration:

<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 Seneste universal logger - SLF4J: Simple Logging Facade til Java

Hvor lang tid kan det være at finde den gyldne middelvej...

I 2006 forlod en af ​​skaberne log4jprojektet og besluttede at prøve igen at oprette en universel logger. Men denne gang var det ikke en ny logger, men en ny universel standard (indpakning), der gjorde det muligt for forskellige loggere at interagere sammen.

Denne logger hed slf4j — Simple Logging Facade for Java, det var en indpakning omkring log4j, JUL, common-loggins and logback. Denne logger løste et reelt problem - at styre en zoologisk have af skovhuggere, så alle begyndte straks at bruge den.

Vi løser heroisk de problemer, vi skaber for os selv. Som du kan se, har fremskridt nået det punkt, at vi har lavet en indpakning over indpakningen ...

Selve indpakningen består af to dele:

  • API, som bruges i applikationer;
  • Implementeringer, der tilføjes som separate afhængigheder for hver logger.

Du kan tilslutte loggeren til projektet ved hjælp af 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 at forbinde den korrekte implementering, og det er det: hele projektet vil arbejde med det.

2.6 Optimering i slf4j

Slf4junderstøtter alle nye funktioner såsom strengformatering til logning . Før dette var der et sådant problem. Lad os sige, at du vil udskrive en besked til loggen:

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

Der er et problem med denne kode. Antag, at din applikation fungerer på productionog ikke skriver noget til loggen DEBUG-messages, men metoden log.debug()vil stadig blive kaldt, og når den kaldes, vil følgende metoder også blive kaldt:

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

Kaldning af disse metoder gør applikationen langsommere. Deres opkald er kun nødvendigt under fejlfinding, men de kaldes alligevel.

Fra et logisk synspunkt skulle dette problem løses i selve logbiblioteket. Og i den første version af log4j kom løsningen op:

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

I stedet for én linje til loggen, var det nu nødvendigt at skrive tre. Hvilket dramatisk forværrede kodens læsbarhed og sænkede populariteten af log4j​​.

Loggeren slf4jvar i stand til at forbedre situationen en smule ved at tilbyde smart logning. Det så sådan her ud:

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

hvor {}angiver indsættelsen af ​​argumenter, der sendes i metoden. Det vil sige, at den første {}svarer til bruger, den anden {}til request.getRemoteAddr().

Disse parametre vil kun blive sammenkædet i en enkelt meddelelse, hvis logningsniveauet tillader logning. Ikke perfekt, men bedre end alle de andre muligheder.

Derefter SLF4Jbegyndte det at vokse hurtigt i popularitet, i øjeblikket er dette den bedste løsning.

Derfor vil vi overveje at logge ved hjælp af eksemplet med et bundt slf4j-log4j12.