Hei! Når jeg skriver leksjonene legger jeg spesielt vekt på om det er et spesifikt tema som vil være helt essensielt i virkelig arbeid. Så, LYTT OPP! Temaet vi skal dekke i dag vil definitivt komme godt med i alle prosjektene dine fra første dag av ansettelse. Vi skal snakke om Java-logging. Dette emnet er slett ikke komplisert (jeg vil til og med si enkelt). Men du vil ha nok åpenbare ting å stresse med på den første jobben din, så det er bedre å forstå det grundig akkurat nå :) Vel, la oss begynne.
Hva er logging i Java?
Logging er handlingen med å registrere data om driften av et program. Stedet hvor vi registrerer disse dataene kalles en "logg". To spørsmål dukker umiddelbart opp: hvilke data er skrevet og hvor? La oss starte med "hvor". Du kan skrive data om et programs arbeid på mange forskjellige steder. For eksempel, under studiene dine, vil du ofte System.out.println()for å sende ut data til konsollen. Dette er faktisk logging, om enn i sin enkleste form. Selvfølgelig er dette ikke veldig praktisk for brukere eller et produktstøtteteam: åpenbart vil de ikke installere en IDE og overvåke konsollen :) Det er et mer vanlig format for å registrere informasjon: tekstfiler. Mennesker er mye mer komfortable med å lese data i dette formatet, og det er absolutt mye mer praktisk å lagre data! Nå er det andre spørsmålet: hvilke programdata skal logges? Det er helt opp til deg! Javas loggsystem er veldig fleksibelt. Du kan konfigurere den til å logge alt programmet ditt gjør. På den ene siden er dette bra. Men på den annen side, se for deg hvor store Facebooks eller Twitters logger ville vært hvis de skrev alt i dem. Disse store selskapene har sannsynligvis muligheten til å lagre så mye data. Men forestill deg hvor vanskelig det ville være å finne informasjon om én kritisk feil i 500 gigabyte med tekstlogger? Det ville vært verre enn å lete etter en nål i en høystakk. Følgelig kan Java konfigureres til kun å logge feildata. Eller til og med bare kritiske feil! Når det er sagt, er det ikke helt nøyaktig å snakke om Javas opprinnelige loggingssystem. Faktum er at programmerere trengte logging før denne funksjonaliteten ble lagt til språket. Da Java introduserte sitt eget loggbibliotek, brukte alle allerede log4j-biblioteket. Historien om logging i Java er faktisk veldig lang og informativ. Kort sagt, Java har sitt eget loggbibliotek, men nesten ingen bruker det :) Senere, da flere forskjellige loggbiblioteker dukket opp og begynte å bli brukt av programmerere, oppsto kompatibilitetsproblemer. For å stoppe folk fra å finne opp hjulet på nytt i et dusin forskjellige biblioteker med forskjellige grensesnitt, ble det abstrakte SLF4J-rammeverket ("Service Logging Facade For Java") laget. Det kalles abstrakt, for selv om du bruker og kaller metodene til SLF4J-klasser, bruker de faktisk alle loggingsrammene som kom før under panseret: log4j, standard java.util.logging og andre. Hvis du på et tidspunkt trenger noen spesifikke funksjoner i Log4j som mangler i andre biblioteker, men du ikke vil koble prosjektet ditt direkte til dette biblioteket, bare bruk SLF4J. Og la den kalle Log4j-metodene. Hvis du ombestemmer deg og bestemmer deg for at du ikke lenger trenger Log4j-funksjoner, trenger du bare å rekonfigurere "her , og Log4j - biblioteket her . Pakk deretter ut arkivet og bruk IntelliJ IDEA for å legge til JAR-filene i klassebanen. Menyelementer: Fil -> Prosjektstruktur -> Biblioteker Velg de nødvendige JAR-filene og legg dem til prosjektet (arkivene vi lastet ned inneholder mange JAR-filer - se på bildene for å se de du trenger) Merk at denne instruksjonen for disse studentene som ikke vet hvordan de skal bruke Maven. Hvis du vet hvordan du bruker Maven, er det vanligvis bedre (mye enklere) å prøve å starte der. Hvis du bruker Maven , legg til denne avhengigheten:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.14.0</version>
</dependency>
Flott! Vi fant ut innstillingene :) La oss se hvordan SLF4J fungerer. Hvordan sørger vi for at programmets arbeid blir tatt opp et sted? For å gjøre dette trenger vi to ting: logger og appender. La oss starte med det første. En logger er et objekt som gir full kontroll over loggingen. Det er veldig enkelt å lage en logger: vi gjør dette ved å bruke de statiske LoggerFactory.getLogger()- metodene. Metodeparameteren er klassen hvis operasjon vil bli logget. La oss kjøre koden vår:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyTestClass {
public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);
public static void main(String[] args) {
LOGGER.info("Test log entry!!!");
LOGGER.error("An error occurred!");
}
}
Konsoll utgang:
ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error occurred!
Hva ser vi her? Først ser vi en feilmelding. Dette er et resultat av at vi nå mangler de nødvendige innstillingene. Følgelig kan loggeren vår for øyeblikket bare sende ut feilmeldinger (ERROR) og kun til konsollen. Logger.info () -metoden fungerte ikke. Men logger.error() gjorde det! På konsollen ser vi gjeldende dato, metoden der feilen oppsto ( main), ordet "FEIL", og vårt budskap! FEIL er loggingsnivået. Generelt, hvis en loggoppføring er merket med ordet "FEIL", så har det oppstått en feil på dette tidspunktet i programmet. Hvis oppføringen er merket med ordet "INFO", representerer meldingen ganske enkelt gjeldende informasjon om normal drift av programmet. SLF4J-biblioteket har mange forskjellige loggingsnivåer som lar deg konfigurere logging fleksibelt. Det hele er veldig enkelt å administrere: all nødvendig logikk er allerede i Java Logger -klassen. Du trenger bare å ringe de relevante metodene. Hvis du vil logge en rutinemelding, kaller du logger.info()- metoden. For en feilmelding, bruk logger.error() . For en advarsel, bruk logger.warn()
La oss nå snakke om appender
En vedlegg er stedet der dataene dine går. På en måte det motsatte av en datakilde, altså «punkt B». Som standard sendes data ut til konsollen. Merk at i det forrige eksemplet trengte vi ikke å konfigurere noe: teksten dukket opp i konsollen, og Log4j-bibliotekets logger kan bare sende ut meldinger på ERROR-nivå til konsollen. Det er åpenbart mer praktisk for folk å lese og skrive logger i en tekstfil. For å endre loggerens standardoppførsel, må vi konfigurere filtillegget vårt. For å komme i gang må du opprette en log4j.xml-fil direkte i src-mappen. Du er allerede kjent med XML-formatet: vi hadde nylig en leksjon om det :) Her er innholdet i filen:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="MyFileAppender"/>
</Root>
</Loggers>
</Configuration>
Ikke noe spesielt spesielt eller vanskelig her :) Men likevel, la oss gå gjennom innholdet.
<Configuration status="INFO">
Dette er den såkalte StatusLogger. Den er ikke relatert til loggeren vår og brukes i Log4js interne prosesser. Hvis du setter status="TRACE" i stedet for status="INFO", og all informasjon om Log4js interne arbeid vil vises på konsollen (StatusLogger viser data på konsollen, selv om vår appender er en fil). Vi trenger det ikke nå, så la oss la det være som det er.
<Appenders>
<File name="MyFileAppender" fileName="C:\Users\Evgeny\Desktop\testlog.txt" append="true">
<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
Her lager vi vår appender. <Fil> -taggen indikerer at det vil være en filtillegg. name="MyFileAppender" angir navnet på vedlegget. fileName="C:\Users\Username\Desktop\testlog.txt" angir banen til loggfilen der alle dataene skal skrives. append="true" indikerer om dataene skal skrives på slutten av filen. I vårt tilfelle er det nettopp dette vi skal gjøre. Hvis du setter verdien til false, vil det gamle innholdet i loggfilen slettes hver gang programmet startes. <PatternLayout pattern="%d{ååå-MM-dd TT:mm:ss.SSS} [%t] %-5nivå %logger{36} - %msg%n"/>angir formateringsinnstillingene. Her kan vi bruke regulære uttrykk for å tilpasse hvordan tekst formateres i loggen vår.
<Loggers>
<Root level="INFO">
<AppenderRef ref="MyFileAppender"/>
</Root>
</Loggers>
Her angir vi rotnivået. Vi har satt "INFO"-nivået, som betyr at alle meldinger hvis nivå er høyere enn INFO (i henhold til tabellen som vi så på ovenfor) ikke vil bli logget. Programmet vårt vil ha 3 meldinger: én INFO, én ADVARSEL og én FEIL. Med gjeldende konfigurasjon vil alle 3 meldingene bli logget. Hvis du endrer rotnivået til ERROR, vil bare den siste meldingen fra LOGGER.error()-metodekallet havne i loggen. I tillegg kommer en referanse til vedlegget også her. For å lage en slik referanse, må du lage en <ApprenderRef> -tag i <Root> -taggen og legge til ref='din appender's name'- attributt til den. I tilfelle du har glemt det, er det her vi setter tilhengerens navn: <. Og her er koden vår!
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyTestClass {
public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);
public static void main(String[] args) {
LOGGER.info("The program is starting!!!");
try {
LOGGER.warn("Attention! The program is trying to divide a number by another.
System.out.println(12/0);
} catch (ArithmeticException x) {
LOGGER.error("Error! Division by zero!");
}
}
}
Selvfølgelig er det litt rart (å fange et RuntimeException er en tvilsom idé), men det er perfekt for våre formål :) La oss kjøre vår main() -metode 4 ganger på rad og se på vår testlog.txt-fil. Du trenger ikke opprette det på forhånd: biblioteket vil gjøre dette automatisk. Alt fungerte! :) Nå har du en konfigurert logger. Du kan leke med noen av de gamle programmene dine, og legge til logger-anrop til hver metode. Se så på den resulterende loggen :) Den vurderer emnet logging i dybden. Det ville vært utfordrende å lese alt på én gang. Når det er sagt, inneholder den mye mer nyttig informasjon. Du vil for eksempel lære hvordan du konfigurerer loggeren slik at den lager en ny tekstfil hvis testlog.txt-filen vår når en viss størrelse :) Og det avslutter timen vår! I dag ble du kjent med et veldig viktig emne, og denne kunnskapen vil definitivt være nyttig for deg i ditt fremtidige arbeid. Til neste gang! :)
GO TO FULL VERSION