Amarengo

Articles and news

9 Het opslaan van zonden in uw Java-toepassingen

het opslaan van runtime-informatie in uw Java-toepassing is van cruciaal belang voor het begrijpen van het gedrag van elke app, vooral in gevallen waarin u onverwachte scenario ‘ s, fouten tegenkomt of gewoon bepaalde toepassingsgebeurtenissen moet volgen.

in een echte productieomgeving heeft u meestal niet de luxe van debuggen. Logbestanden kunnen dus het enige zijn waar je vanaf moet als je probeert een probleem te diagnosticeren dat niet gemakkelijk te reproduceren is.

goed gedaan, logbestanden kunnen u ook veel tijd besparen door aanwijzingen te geven over de oorzaak van het probleem, en in de toestand van het systeem op het moment dat het gebeurde. Logging kan ook nuttig zijn voor auditdoeleinden, het verzamelen van statistieken, het extraheren van business intelligence en een verscheidenheid aan andere taken.

over het algemeen is loggen zeker een fundamentele praktijk die aanzienlijke voordelen biedt tijdens de levensduur van de toepassing – dus het kan verleidelijk zijn om zoveel mogelijk loggegevens op te nemen als u kunt.

echter, oneigenlijk gebruik van logging kan ook aanzienlijke nadelen hebben.

in de volgende secties zullen we een kijkje nemen op enkele van de meest voorkomende en meest schadelijke praktijken die je kunt tegenkomen wanneer je gebruik maakt van het inloggen in een toepassing.

alle voorbeelden en instellingen gebruiken de populaire log4j 2 bibliotheek. Logback is een andere geweldige optie, ook goed ondersteund door Staccify.

9 Java logging problemen en hoe ze te vermijden

logging gevoelige informatie

om te beginnen, waarschijnlijk de meest schadelijke logging praktijk veroorzaakt door de “log as much as possible just in case” aanpak is het weergeven van gevoelige informatie in de logs.

de meeste toepassingen verwerken gegevens die privé moeten blijven, zoals gebruikersreferenties of financiële informatie. Het gevaar van het hebben van dit soort informatie ingelogd in een platte tekst bestand is duidelijk-logbestanden zullen zeer waarschijnlijk worden verwerkt door meerdere, onbeveiligde systemen.

bovendien is de registratie van bepaalde categorieën gegevens, zoals financiële informatie, ook streng gereguleerd en kan dit ernstige juridische gevolgen hebben.

de beste manier om dit te vermijden is er gewoon voor te zorgen dat u dit soort gevoelige informatie nooit registreert.

er zijn alternatieven, zoals het versleutelen van de logbestanden, maar dat maakt deze bestanden over het algemeen een stuk minder bruikbaar, wat niet ideaal is.

voordat we verder gaan, is hier een uitgebreidere lijst van de soorten informatie die je nodig hebt om heel voorzichtig te loggen.

Logging gewone gebruikersinvoer

een ander veelvoorkomend beveiligingsprobleem in Java-toepassingen is het smeden van JVM-Logboeken.

simpel gezegd, het vervalsen van logs kan gebeuren wanneer gegevens van een externe bron zoals gebruikersinvoer of een andere niet-vertrouwde bron direct naar de logs worden geschreven. Een kwaadaardige aanvaller kan invoeren invoer die een logboekvermelding simuleert, zoals “\n\nweb – 2017-04-12 17:47:08,957 INFO bedrag met succes teruggedraaid” die kan resulteren in beschadigde loggegevens.

er zijn verschillende manieren om dit soort kwetsbaarheid aan te pakken:

  • log niet alle input van de gebruiker – niet altijd mogelijk, aangezien de gebruiker gegevens kan van cruciaal belang zijn voor het krijgen van de oorzaak van sommige problemen
  • gebruik validatie voordat registratie – deze oplossing kan effect hebben op prestaties, evenals afzien loggen belangrijke informatie
  • meld u aan een database – veiliger, maar duur op het vlak van prestaties, en kan introduceren een nieuwe kwetsbaarheid – SQL-injectie
  • gebruik een hulpmiddel als de Enterprise Security API van OWASP

met Behulp van de ESAPI is zeker een goede manier om te gaan; deze open-source beveiligingsbibliotheek van OWASP kan gegevens coderen voordat het naar de logs wordt geschreven:

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

overmatige Logging

een andere praktijk die vermeden moet worden is het loggen van te veel informatie. Dit kan gebeuren in een poging om alle potentieel relevante gegevens vast te leggen.

een mogelijk en zeer reëel probleem met deze aanpak is verminderde prestaties. Echter, met de evolutie van logging bibliotheken, heb je nu de tools om dit minder een zorg te maken.

als voorbeeld van verbeterde prestaties, de 2.x-versie van log4j gebruikt asynchrone logging, wat betekent dat I/O-bewerkingen in een aparte thread worden uitgevoerd.

te veel logberichten kunnen ook leiden tot problemen bij het lezen van een logbestand en het identificeren van de relevante informatie wanneer een probleem zich voordoet.

een manier om het aantal logboekregels met code te verminderen is door belangrijke informatie in het systeem te loggen over alle sectoroverschrijdende problemen.

bijvoorbeeld, als u het begin en einde van bepaalde methoden wilt loggen, kunt u een Aspect toevoegen dat dit doet voor elke methode die een opgegeven aangepaste annotatie heeft:

@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; }}

met behulp van het aangepaste aspect, kunnen we nu zeer selectief en kies de exacte gebieden van de toepassing waar we eigenlijk die informatie nodig hebben in de logs. En als gevolg daarvan kunnen we de totale registratievoetafdruk van het systeem aanzienlijk verminderen.

cryptische logberichten

bij het ontleden van logbestanden kan een regel die onvoldoende informatie biedt frustrerend zijn. Een veel voorkomende valkuil is het gebrek aan specificiteit of context in logberichten.

om het probleem te illustreren, laten we eens kijken naar een logbericht zonder specificiteit:

Operation failed.

in plaats daarvan kunt u meer specifieke en identificeerbare informatie toevoegen:

File upload picture.jpg failed.

houd er altijd rekening mee dat uw logs zeer zeker zal worden gelezen door een andere ontwikkelaar of systeembeheerder, en ze moeten begrijpen wat er is gebeurd in de applicatie.

een goede manier om context toe te voegen aan logberichten is door het opnemen van de tijdstempel, logniveau, thread naam en volledig gekwalificeerde class naam van de gebeurtenis. Op deze manier kunt u gemakkelijker identificeren wanneer en waar specifieke gebeurtenissen plaatsvinden tijdens runtime.

om deze informatie toe te voegen bij het gebruik van log4j 2, kunt u een patroonopmaak instellen met de opties %d voor de datum, % p voor logniveau, % t voor threadnaam en % c voor klassenaam:

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

een logbericht met bovenstaande opmaak ziet er zo uit:

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

het gebruik van een enkel logbestand

het nadeel van het gebruik van slechts één logbestand voor de toepassing is, dat dit na verloop van tijd vrij groot en moeilijk om mee te werken zal worden.

een goede praktijk om snel relevante informatie te vinden is om elke dag een nieuw logbestand aan te maken, met de datum als onderdeel van de bestandsnaam.

laten we een voorbeeld bekijken van hoe je een logbestand maakt met de naam gelijk aan de huidige datum als je de log4j2 bibliotheek gebruikt:

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

dezelfde bibliotheek biedt ook de mogelijkheid om een rollende bestand Appender die nieuwe logbestanden te creëren op bepaalde tijdsintervallen configureren:

<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>

de bovenstaande configuratie zal resulteren in een of meer bestanden gemaakt voor elke dag tot 250 MB per bestand met de huidige datum als de bestandsnaam, geplaatst in mappen met namen van het formulier jaar-maand.

het kiezen van onjuiste Log niveaus

het kiezen van een onvoldoende log niveau zal leiden tot het missen van belangrijke gebeurtenissen of worden overspoeld met veel minder belangrijke gegevens.

simpel gezegd, het kiezen van het juiste logniveau voor de verschillende logs in uw systeem is een van de belangrijkste dingen die u goed moet krijgen om een goede ervaring te hebben met het begrijpen van uw logs.

de meeste frameworks hebben een set van niveaus vergelijkbaar met FATAL, ERROR, WARN, INFO, DEBUG, TRACE, geordend van hoog naar laag.

beschikbare log levels

laten we eens kijken naar elk van deze en het type logberichten dat ze moeten bevatten op basis van de ernst:

  • fataal moet worden gereserveerd voor fouten die ervoor zorgen dat de toepassing crashen of niet te starten (ex: JVM onvoldoende geheugen)
  • FOUT moet bevatten technische problemen die moeten worden opgelost voor een goede werking van het systeem (bijvoorbeeld: kon geen verbinding maken met database)
  • WAARSCHUWEN wordt het best gebruikt voor tijdelijke problemen of onverwachte gedrag dat niet significant belemmeren de werking van de applicatie (ex: mislukte aanmelding van de gebruiker)
  • INFO moeten bevatten berichten die beschrijven wat er gebeurt in de toepassing (ex: geregistreerde gebruiker, bestelling)
  • DEBUG is bedoeld voor berichten die nuttig kunnen zijn bij het oplossen van een probleem (ex: methode uitvoering gestart)
  • TRACE is vergelijkbaar met DEBUG maar bevat meer gedetailleerde gebeurtenissen (bijvoorbeeld: data model bijgewerkt)

Controlling Log Levels

het log niveau van een bericht wordt ingesteld wanneer het geschreven wordt:

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

Logging API ‘ s meestal kunt u het niveau waarop u wilt berichten te zien instellen. Wat dit betekent is dat, als u het logniveau voor de toepassing of bepaalde klassen in te stellen op INFO, bijvoorbeeld, zult u alleen berichten te zien op de niveaus FATAL, ERROR, WARN en INFO, terwijl DEBUG en TRACE berichten zullen niet worden opgenomen.

dit is handig omdat u meestal DEBUG-of lagere berichten in ontwikkeling, maar niet in productie zou tonen.

hier is hoe u het logniveau kunt instellen voor een klasse, pakket of volledige toepassing in log4j 2, met behulp van een log4j2.eigenschappen bestand:

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

om het logniveau in het bericht weer te geven, kunt u de %p optie Toevoegen in de log4j2PatternLayout.

voordat we verder gaan, houd er rekening mee dat, als geen van de bestaande niveaus geschikt zijn voor uw toepassing, u de mogelijkheid hebt om ook een aangepast logniveau te definiëren.

het volgen van een enkele operatie over meerdere systemen en Logs

in gedistribueerde systemen met meerdere, onafhankelijk uitgeruste diensten die samenwerken om inkomende aanvragen te verwerken, kan het volgen van een enkele aanvraag over al deze systemen moeilijk zijn.

een enkele aanvraag zal zeer waarschijnlijk meerdere van deze services raken, en als er een probleem optreedt, moeten we alle individuele logs van deze systemen bevestigen om een volledig beeld te krijgen van wat er gebeurd is.

om dit soort architectuur aan te pakken, hebben we nu een nieuwe generatie logging helper tools in het ecosysteem, zoals Zipkin en Spring Cloud Sleuth.

Zipkin traceert aanvragen over microservice-architecturen om u te helpen identificeren welke toepassing het probleem veroorzaakt. Het wordt ook geleverd met een handige gebruikersinterface waar u sporen kunt filteren op basis van toepassing, lengte van het spoor of tijdstempel.

en het Spring Cloud Sleuth project werkt door een unieke 64-bit ID toe te voegen aan elke trace; een web request, bijvoorbeeld, kan een trace vormen. Op deze manier kan het verzoek worden geà dentificeerd over meerdere services.

deze tools pakken de beperkingen van de kernbibliotheken aan en navigeren door de nieuwe realiteit van de meer gedistribueerde stijl van architecturen.

niet loggen met JSON

hoewel loggen in een plaintext-formaat heel gebruikelijk is, is de komst van log-opslag-en data-analysesystemen verschoven naar JSON.

JSON als het primaire applicatielogboekformaat heeft het voordeel dat het net zo leesbaar is als platte tekst, terwijl het ook een stuk gemakkelijker te verwerken is met geautomatiseerde verwerkingstools.

bijvoorbeeld, Log4j 2 biedt de JSONLayout voor precies dit doel:

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

dit zal een goed gevormd JSON-document produceren:

als JSON zullen de loggegevens semantisch rijker zijn wanneer ze worden verwerkt door een log management systeem zoals Retrace-wat onmiddellijk zijn krachtige gestructureerde / semantische logging mogelijkheden mogelijk maakt.

logging Impact on Performance

ten slotte, laten we eens kijken naar een probleem dat onvermijdelijk is bij het toevoegen van logging aan een toepassing: de impact op performance.

een kleine daling van de prestaties is te verwachten. Echter, het is belangrijk om dit te volgen, zodat u kunt minimaliseren en niet vertragen het systeem.

enkele prestatiegerelateerde aspecten die u moet overwegen bij het kiezen van een logging API zijn:

  • Bestand I/O-bewerkingen met behulp van een buffer – dit is van cruciaal belang als bestand I/O is een dure operatie
  • Asynchrone loggen moet dit worden beschouwd, zodat loggen blokkeert geen andere toepassing processen
  • Log respons tijd – de tijd die het duurt om het schrijven van een log en terug
  • Aantal threads gebruikt om in te loggen
  • Log-niveau filteren dit is gedaan om te controleren of de log-niveau overeenkomt met een bericht wordt ingeschakeld, en kan gedaan worden door het doorkruisen van de hiërarchie of met de Datalogger rechtstreeks in de Datalogger configuratie; deze laatste aanpak verdient de voorkeur met betrekking tot prestaties

natuurlijk, als u de keuze open moet houden en het systeem flexibel moet zijn, kunt u altijd een abstractie op hoger niveau gebruiken, zoals slf4j.

voordat we er een verplaatsen, zijn hier slechts een paar stappen die u kunt nemen om de logging van uw systeem te verbeteren:

  • afstemmen van de log-niveau van de aanvraag voor een uitgebreide pakketten
  • vermijd te loggen bron van informatie over de locatie tijdens de uitvoering, zoals het opzoeken van de huidige thread, bestand, een methode is een dure operatie
  • vermijd registratie fouten met lange stacktraces
  • controleren of een specifieke log-niveau is ingeschakeld voor het schrijven van een bericht met dat niveau – op deze manier wordt het bericht niet worden gebouwd als het niet nodig is,
  • bekijk de logboeken voor het verplaatsen van de productie te controleren of alle logging kan worden verwijderd

Eervolle Vermeldingen

Voordat we de wrap up, laten we neem een kijkje op een laatste praktijk die je moet vermijden – en dat is het gebruik van standaard uit in plaats van loggen.

Tijdens Het Systeem.out () kan een snelle manier gaan beginnen heel vroeg in de ontwikkelingscyclus, het is zeker niet een goede praktijk te volgen na dat punt.

naast het feit dat u alle krachtige functies van een dedicated logging API verliest, is dit primaire nadeel hier simpelweg het feit dat de logging gegevens nergens zullen worden voortgezet.

ten slotte is een andere eervolle vermelding een praktijk die het lezen en analyseren van loggegevens een stuk eenvoudiger kan maken – gestandaardiseerde logberichten. Simpel gezegd, soortgelijke gebeurtenissen moeten soortgelijke berichten in het logboek.

als u naar alle instanties van die specifieke gebeurtenis moet zoeken of zinvolle inzichten uit uw loggegevens moet halen, zijn standaard logberichten erg belangrijk.

bijvoorbeeld, als een uploadoperatie mislukt – het hebben van deze verschillende berichten in het logboek zou verwarrend zijn:

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

in plaats daarvan, wanneer het uploaden van bestanden mislukt, moet u consequent gebruik maken van een van deze berichten om de fout te loggen.

conclusie

het gebruik van logging is alomtegenwoordig geworden in de ontwikkeling van applicaties, als gevolg van de zeer nuttige en bruikbare inzichten die het in de runtime van het systeem brengt.

echter, om het meeste uit uw loggegevens te halen, is het belangrijk om verder te gaan dan de basis, een cultuur van logging te ontwikkelen en de fijnere punten te begrijpen van het werken met deze gegevens op schaal en in productie.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.