Amarengo

Articles and news

9 Logging Synder I Java-Programmer

Logging runtime informasjon i Java-programmet er kritisk nyttig for å forstå oppførselen til noen app, spesielt i tilfeller når du støter på uventede scenarier, feil eller bare trenger å spore visse programhendelser.

i et ekte produksjonsmiljø har du vanligvis ikke luksusen til feilsøking. Og så kan loggfiler være det eneste du må gå ut av når du prøver å diagnostisere et problem som ikke er lett å reprodusere.

gjort riktig, loggfiler kan også spare deg for mye tid ved å gi ledetråder til årsaken til problemet, og inn i tilstanden til systemet da det skjedde. Logging kan også være nyttig for revisjonsformål, samle statistikk, utvinne forretningsinformasjon og en rekke andre oppgaver.

logging er absolutt en grunnleggende praksis som gir betydelige fordeler i løpet av søknadens levetid-så det kan være fristende å begynne å registrere så mye loggdata som mulig.

feilaktig bruk av logging kan imidlertid også ha betydelige ulemper.

i de følgende avsnittene tar vi en titt på noen av de vanligste og mest skadelige praksisene du kan støte på når du bruker innlogging i et program.

alle eksempler og konfigurasjon bruker det populære log4j 2-biblioteket. Logback er et annet flott alternativ, også godt støttet Av Stackify.

9 Java Logging Problemer Og Hvordan Du Kan Unngå Dem

Logging Sensitiv Informasjon

til å begynne med, sannsynligvis den mest skadelige logging praksis brakt videre av» log så mye som mulig bare i tilfelle » tilnærming viser sensitiv informasjon i loggene.

de fleste programmer håndterer data som bør forbli private, for eksempel brukerlegitimasjon eller finansiell informasjon. Faren for å få denne typen informasjon logget inn i en ren tekstfil er klar-loggfiler vil sannsynligvis bli behandlet av flere, usikrede systemer.

i tillegg er logging av enkelte kategorier av data, for eksempel finansiell informasjon, også tungt regulert og kan ha alvorlige juridiske implikasjoner.

Den beste måten å unngå dette på er ganske enkelt å sørge for at du aldri logger denne typen sensitiv informasjon.

det finnes alternativer, for eksempel kryptering av loggfilene, men det gjør vanligvis disse filene mye mindre brukbare generelt, noe som ikke er ideelt.

Før Vi går videre, er det en mer omfattende liste over hvilke typer informasjon du må være veldig forsiktig med å logge.

Logging Av Vanlig Brukerinngang

Et annet vanlig sikkerhetsproblem I Java-programmer ER Jvm Log Smiing.

enkelt sagt kan loggsmiing skje når data fra en ekstern kilde som brukerinngang eller en annen uklarert kilde skrives direkte til loggene. En ondsinnet angriper kan legge inn inndata som simulerer en loggoppføring, for eksempel «\n\nweb-2017-04-12 17: 47: 08,957 Info Amount reversed successful», som kan føre til ødelagte loggdata.

det finnes ulike måter å håndtere denne typen sårbarhet på:

  • ikke logg noen brukerinndata – ikke alltid mulig, siden brukerdataene kan være kritiske for å komme til grunnårsaken til noen problemer
  • bruk validering før logging – denne løsningen kan påvirke ytelsen, samt avstå fra å logge viktig informasjon
  • logg på en database – sikrere, men kostbar når det gjelder ytelse, og kan introdusere et annet sikkerhetsproblem – SQL injection
  • bruk et verktøy som Enterprise sikkerhet api fra owasp

bruke esapi er definitivt en god måte å gå; DETTE sikkerhetsbiblioteket med åpen kildekode fra OWASP kan kode data før du skriver det til loggene:

message = message.replace( '\n' , '_' ).replace( '\r' , '_' ) .replace( '\t' , '_' );message = ESAPI.encoder().encodeForHTML( message );

Overdreven Logging

en annen praksis som må unngås, er å logge for mye informasjon. Dette kan skje i et forsøk på å fange opp alle potensielt relevante data.

et mulig og veldig reelt problem med denne tilnærmingen er redusert ytelse. Men med utviklingen av logging biblioteker, har du nå verktøy for å gjøre dette mindre av en bekymring.

som et eksempel på forbedret ytelse, er 2.x versjon av log4j bruker asynkron logging, som betyr å utføre i / O-operasjoner i en egen tråd.

For Mange loggmeldinger kan også føre til problemer med å lese en loggfil og identifisere relevant informasjon når et problem oppstår.

en måte å redusere antall logglinjer med kode er ved å logge viktig informasjon på tvers av tverrgående bekymringer i systemet.

hvis du for eksempel vil logge starten og slutten av bestemte metoder, kan du legge til Et Aspekt som vil gjøre dette for hver metode som har en angitt egendefinert merknad:

@Aspectpublic class MyLogger { private static final Logger logger = LogManager.getLogger(MyLogger.class); @Around("execution(* *(..)) && @annotation(LogMethod)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { logger.info("Starting method execution: " + joinPoint.getSignature().getName() + " in class:"+joinPoint.getSignature().getDeclaringTypeName()); Object result = joinPoint.proceed(); logger.info("Exiting method execution: " + joinPoint.getSignature().getName() + " in class:"+joinPoint.getSignature().getDeclaringTypeName()); return result; }}

ved hjelp av det tilpassede aspektet kan vi nå være veldig selektive og velge de nøyaktige områdene i applikasjonen der vi faktisk trenger den informasjonen i loggene. Og som et resultat kan vi redusere systemets samlede loggavtrykk betydelig.

Kryptiske Loggmeldinger

når du analyserer loggfiler, kan det være frustrerende å møte en linje som ikke gir tilstrekkelig informasjon. En vanlig fallgruve er mangelen på spesifisitet eller kontekst i loggmeldinger.

for å illustrere problemet, la oss se på en loggmelding som mangler spesifisitet:

Operation failed.

I Stedet kan du legge til mer spesifikk og identifiserbar informasjon:

File upload picture.jpg failed.

alltid huske på at loggene vil absolutt bli lest av en annen utvikler eller systemadministrator, og de trenger å forstå hva som har skjedd i programmet.

en god måte å legge til kontekst i loggmeldinger er ved å inkludere tidsstempel, loggnivå, trådnavn og fullt kvalifisert klassenavn på arrangementet. På denne måten kan du lettere identifisere når og hvor bestemte hendelser oppstår under kjøring.

hvis du vil legge til denne informasjonen når du bruker log4j 2, kan du konfigurere Et Mønsteroppsett med alternativene %d for datoen, %p for loggnivå, %t for trådnavn og %c for klassenavn:

<PatternLayout> <Pattern>%d %p %c - %m%n</Pattern></PatternLayout>

en loggmelding ved hjelp av oppsettet ovenfor vil se slik ut:

2017-05-11 22:51:43,223 INFO com.stackify.service.MyService - User info updated

Ved Å Bruke En Enkelt Loggfil

ulempen Ved å bare bruke en loggfil for applikasjonen er at dette over tid vil bli ganske stort og vanskelig å jobbe med.

en god praksis for raskt å finne relevant informasjon er å opprette en ny loggfil hver dag, med datoen som en del av filnavnet.

la oss ta en titt på et eksempel på hvordan du lager en loggfil med navnet lik dagens dato hvis du bruker log4j2-biblioteket:

SimpleLayout layout = new SimpleLayout();FileAppender appender = new FileAppender(layout, LocalDate.now().toString(), false);logger.addAppender(appender);

det samme biblioteket gir også muligheten til å konfigurere En Rullende Fil Appender som vil skape nye loggfiler på bestemte tidsintervaller:

<RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c - %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> <DefaultRolloverStrategy max="20"/></RollingFile>

konfigurasjonen ovenfor vil resultere i en eller flere filer opprettet for hver dag opp til 250 MB per fil med gjeldende dato som filnavn, plassert i mapper med navn på skjemaet år-måned.

Hvis Du Velger Feil Loggnivå

Hvis du Velger et utilstrekkelig loggnivå, vil det føre til at du enten mangler viktige hendelser eller blir oversvømmet med mye mindre viktige data.

enkelt sagt, å velge riktig loggnivå for de forskjellige loggene i systemet ditt er en av de viktigste tingene du trenger for å få rett til å ha en god opplevelse å forstå loggene dine.

de fleste loggingsrammer har et sett med nivåer som LIGNER FATAL, ERROR, WARN, INFO, DEBUG, TRACE, bestilt fra høyeste til laveste.

tilgjengelige loggnivåer

La oss ta en titt på hver av disse og typen loggmeldinger de skal inneholde basert på alvorlighetsgrad:

  • FATAL bør reserveres for feil som fører til at programmet krasjer eller ikke starter (ex: KAN ikke koble til databasen)
  • FEILEN bør inneholde tekniske problemer som må løses for riktig funksjon av systemet (f. eks: kunne ikke koble til databasen)
  • WARN er best brukt for midlertidige problemer eller uventet atferd som ikke vesentlig hemme driften av programmet (f. eks: mislyktes brukerinnlogging)
  • INFO bør inneholde meldinger som beskriver hva som skjer i programmet (f. eks: bruker registrert, bestilling plassert)
  • feilsøking er ment for meldinger som kan være nyttige ved feilsøking av ET PROBLEM (ex: metode kjøring startet)
  • SPOR ligner DEBUG, men inneholder mer detaljerte hendelser (f. eks.)

Kontrollere Loggnivåer

loggnivået for en melding angis når den skrives:

logger.info("Order ID:" + order.getId() + " placed.");

Logging Av Api-Er lar deg vanligvis angi nivået du vil se meldinger på. Hva dette betyr er at hvis du setter loggnivået for programmet eller bestemte klasser TIL INFO, for eksempel, vil du bare se meldinger PÅ nivåene FATAL, ERROR, WARN og INFO, mens DEBUG og SPORINGSMELDINGER ikke vil bli inkludert.

Dette er nyttig som du vanligvis vil vise DEBUG eller lavere meldinger i utvikling, men ikke i produksjon.

slik kan du angi loggnivået for en klasse, pakke eller hele programmet i log4j 2, ved hjelp av en log4j2.egenskaper fil:

loggers=classLogger,packageLoggerlogger.classLogger.name=com.stackify.service.MyServicelogger.classLogger.level=infologger.packageLogger.name=com.stackify.configlogger.packageLogger.level=debug
rootLogger.level=debug

for å vise loggnivået i meldingen, kan du legge til alternativet %p i log4j2PatternLayout.

før vi går Videre, må du huske på at hvis ingen av de eksisterende nivåene passer for dine applikasjonsbehov, har du også mulighet til å definere et tilpasset loggnivå.

Sporing Av En Enkelt Operasjon På Tvers Av Flere Systemer Og Logger

i distribuerte systemer med flere, uavhengig distribuerte tjenester som arbeider sammen for å behandle innkommende forespørsler, kan det være vanskelig å spore en enkelt forespørsel på tvers av alle disse systemene.

en enkelt forespørsel vil sannsynligvis treffe flere av disse tjenestene, og hvis det oppstår et problem, må vi bekrefte alle de individuelle loggene til disse systemene for å få hele bildet av hva som skjedde.

For å adressere denne typen arkitektur har vi nå en ny generasjon logghjelperverktøy i økosystemet, for Eksempel Zipkin og Spring Cloud Sleuth.

Zipkin sporer forespørsler på tvers av mikrotjenestearkitekturer for å hjelpe deg med å identifisere hvilket program som forårsaker problemet. Den kommer også med en nyttig UI der du kan filtrere spor basert på søknad, lengden på spor eller tidsstempel.

Og Spring Cloud Sleuth-prosjektet fungerer ved å legge til en unik 64-biters ID til hvert spor; en webforespørsel kan for eksempel utgjøre et spor. På denne måten kan forespørselen identifiseres på tvers av flere tjenester.

disse verktøyene adresserer begrensningene i kjernebibliotekene, og du navigerer i de nye realitetene i den mer distribuerte arkitekturstilen.

Ikke Logging MED JSON

mens logging i et ren tekstformat er svært vanlig, har adventen av logglagring og dataanalysesystemer skiftet det mot JSON.

JSON som det primære applikasjonsloggformatet har fordelen av å være like lesbar som ren tekst, samtidig som den er mye lettere å analysere av automatiserte behandlingsverktøy.

Log4j 2 tilbyr For eksempel JSONLayout for dette nøyaktige formålet:

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

Dette vil produsere et godt formet json-dokument:

som JSON vil loggdataene bli semantisk rikere når de behandles av et loggstyringssystem som Retrace – som umiddelbart vil aktivere sine kraftige strukturerte / semantiske loggingsfunksjoner.

Logging Innvirkning På Ytelsen

Til Slutt, la Oss vurdere et problem som er uunngåelig når du legger logging til et program: virkningen på ytelsen.

en liten nedgang i ytelsen kan forventes. Det er imidlertid viktig å spore dette slik at du kan minimere det og ikke senke systemet.

noen ytelsesrelaterte aspekter å vurdere når du velger en logging API er:

  • fil I/O – operasjoner ved hjelp av en buffer – dette er kritisk da fil i/O er en dyr operasjon
  • Asynkron logging – dette bør vurderes slik at logging ikke blokkerer andre applikasjonsprosesser
  • Logging responstid – tiden det tar å skrive en loggoppføring og returnere
  • antall tråder som brukes til logging
  • loggnivåfiltrering-dette gjøres for å kontrollere om loggnivået som svarer til en melding, er aktivert, og kan gjøres ved å krysse hierarkiet eller ha Loggerpunktet direkte til loggerkonfigurasjonen; sistnevnte tilnærming er å foretrekke når det gjelder ytelse

selvfølgelig, hvis du trenger å holde valget åpent og systemet fleksibelt, kan du alltid bruke et høyere abstraksjon som slf4j.

Før vi flytter en, her er bare noen få skritt du kan ta for å forbedre loggingsytelsen til systemet ditt:

  • tune loggnivået i programmet for utførlige pakker
  • unngå logging kildeplasseringsinformasjon under kjøring, som å se opp den nåværende tråden, fil, er en metode en kostbar operasjon
  • unngå loggfeil med lange stakkspor
  • kontroller om et bestemt loggnivå er aktivert før du skriver en melding med det nivået. 4306>
  • se gjennom loggene før du går til produksjon for å sjekke om noen logging kan fjernes

hederlig omtale

før vi pakker opp, la oss ta en titt på en siste praksis som du bør unngå – og det bruker standard ut i stedet for å logge.

Mens Systemet.ut () kan være en rask måte å starte veldig tidlig i utviklingssyklusen, det er definitivt ikke en god praksis å følge etter det punktet.

Foruten det faktum at du mister alle de kraftige funksjonene til en dedikert logging API, er denne primære ulempen her bare det faktum at loggdataene ikke vil bli vedvarende hvor som helst.

endelig er en annen hederlig omtale en praksis som kan gjøre lesing og analyse av loggdata mye enklere – standardiserte loggmeldinger. Enkelt sagt, lignende hendelser bør ha lignende meldinger i loggen.

hvis du trenger å søke etter alle forekomster av den aktuelle hendelsen eller trekke ut meningsfull innsikt ut av loggdataene dine, er standard loggmeldinger ganske viktige.

for eksempel, hvis en opplastingsoperasjon mislykkes, vil det være forvirrende å ha disse forskjellige meldingene i loggen:

Could not upload file picture.jpg
File upload picture.jpg failed.

I Stedet, når filopplastingen mislykkes, bør du konsekvent bruke en av disse meldingene til å logge feilen.

Konklusjon

bruken av logging har blitt allestedsnærværende i applikasjonsutvikling, på grunn av den svært nyttige og handlingsbare innsikten det bringer inn i kjøretiden til systemet.

men for å få mest mulig ut av loggdataene dine, er det viktig å gå utover det grunnleggende, utvikle en loggskultur og forstå de finere punktene for å operere med disse dataene i skala og i produksjon.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.