SlideShare une entreprise Scribd logo
1  sur  61
Télécharger pour lire hors ligne
Helpful logging
with Java
Thomas Aglassinger
http://www.roskakori.at
v1.1.1
About me
●
Thomas Aglassinger
●
Software developer
– Industry experience since 2001 in various areas (health care, banking, e-commerce,
customer relationship management)
– Casual open source developer
– 2 x MSc
●
Links
– http://twtwtw.roskakori.at
– @TAglassinger
– https://github.com/roskakori
Agenda
●
Logging twith Java – the basics
●
Logging at diferent levels: INFO, ERROR, FATAL, WARNING,
DEBUG
●
Various considerations: performance, security, scaling,
operations
Logging – the basics
Why logging?
●
Analysis: even afer the fact, complements debugging twith
breakpoints
●
Monitoring: Can provide triggers for monitoring systems
→ react on certain log messages
●
Support: collects information even twhen run on a diferent
computer by another users
●
Application metrics: anstwer questions like “Hotw ofen did a
certain error occur in the past 3 months?”
Logging frameworks and libraries
●
Plenty of options
– Log4j: grand daddy of logging
– Java.util.logging: part of standard library
– Slf4j (Simple logging facade for Java) allotws to plug in logging frametwork during runtime
– ...and many others
●
Application can create multiple loggers, e.g. per class
●
Loggers can log messages at diferent levels
●
Messages can be...
– formatted flexibly: timestamp, level, message, logger name, thread, ...
– sent to various outputs: console, log file, data base, nettwork, ...
– filtered as needed: only certain loggers or levels
Logging example
import java.util.logging.Logger;
public class Example {
private static final Logger LOG = Logger.getLogger(Example.class.getName());
public void greet() {
LOG.info("Hello world!");
LOG.fine(() -> String.format("Greetings from %s!", Example.class.getName()));
}
public static void main(String[] args) {
Example example = new Example();
example.greet();
}
}
import java.util.logging.Logger;
public class Example {
private static final Logger LOG = Logger.getLogger(Example.class.getName());
public void greet() {
LOG.info("Hello world!");
LOG.fine(() -> String.format("Greetings from %s!", Example.class.getName()));
}
public static void main(String[] args) {
Example example = new Example();
example.greet();
}
}
Logging example
Default for java.util.logging:
Log level INFO or higher
to console
Create a netw logger
Will be logged
Will be suppressed
Message includes
variable
Lamda to resolve String.format()
only if log level is suficient
Logging levels
●
Something along the line of DEBUG, INFO, WARN, ERROR,
FATAL (see next slide for mapping)
●
Corresponding methods to log a message:
debug(), info(), twarn(), error(), fatal()
●
Messages belotw a certain level can be suppressed using e.g.
someLogger.setLevel() or configuration files
●
Use getLogger(Some.class.getName()) to use a class as name
●
Packages and sub-packages can be controlled hierarchically
Logging levels: mapping
slf4j Log4j java.util.logging
FATAL FATAL n/a
ERROR ERROR SEVERE
WARN WARN WARNING
INFO INFO INFO
DEBUG, TRACE DEBUG, TRACE, ALL FINE, FINER, FINEST
Logging the stack trace 2/2
●
What about exceptions not caught by any code?
– Depends on Java implementation
– Typically: print stack trace to stderr and terminate thread /
application
●
Solution:
1)Use Thread.setDefaultUncaughtExceptionHandler()
2)In handler, log exception
●
See also: Uncaught Java Thread Exceptions
Tools to collect and search logs
●
logstash and kibana (based on elasticsearch)
●
graylog
●
nagios core twith check_logfiles plugin
●
Available as basic open source product and fully featured
commercial product
INFO logging
Motivation for INFO messages
●
Quickly see twhat application is doing right notw (or twas doing
at a certain point in time)
●
Trace back twhat caused a certain error
●
High level
●
If possible using business terms (process, document, file,
customer record, ...)
●
Small amount of messages to avoid information overflotw and
excessive impact on log storage
When to use INFO
●
With high level components: business relevant actions and decisions that influence the result
– Business process start / end
– Input received / output sent
– Major branches in process logic
●
With lotw level components: essential operations
– Incoming requests
– Start / end of transactions (database, files, nettwork, …)
– Connection to other services or resources (database)
– Important state changes ( configuration changes, log in, session context, …)
– Start / end of complex calculation, important results
– Progress information (dotwnload, calculation, ...)
Logging before / after the fact
●
Before: use present tense participle (“-ing form”),
for example:
reading customer data from “customers.csv”
●
Afer: use past tense, for example:
read 1234 customer records from “customers.csv”
Perspective of log messages
●
Word log messages from the perspective of the application
●
I = the application
●
you = the reader of the log
●
In line twith usability engineering (i.e. status messages,
progress bars, error dialogs)
Grammar of log messages
●
When the application is about to do something: present progressive: for example:
– reading customer data from “customers.csv”
●
When the application finished doing something: past tense, for example:
– processed 1234 customer records from “customers.csv”
– read 1234 customer records from “customers.csv” [to read = irregular verb]
●
When the application expects the log reader to do something: imperative (German:
Befehlsform), for example:
– check proxy settings
– see section 12.3.4 of the user guide for more information
– visit https://example.com to dotwnload the update
Example: no logging
try (Stream<String> lines = Files.lines(customerPath)) {
lines.forEach(this::processCustomer);
};
Summary (so far)
●
Info-log only essential actions and decisions
●
When possible use business terms
●
Mind the grammar for clear twording
– Present progressive tense
– Past tense
●
I = software, you = log reader
– Imperative to address reader
ERROR logging
Detecting errors
1) Detect yourself twith „if“:
2) Detect error throtwn by called function using „catch“:
if (actualValue != expectedValue) {
// handle error
}
try {
doSomething();
} catch (SomeError error) {
// handle error
}
Examples for unsafe acts
●
Slip: person does something they did not intent to and twould knotw
better, e.g. type “their” instead of “there”
●
Lapse: person forgets to do something they intended to do, e.g. exit
application twithout saving
●
Mistakes: person "intentionally"carries out a sequence of actions
that - maybe even possible and correct for the application - do not
give them twhat they twant, e.g. try to open text document in
spreadsheet application
●
Violations: e.g. tworkaround, sabotage
Solving errors
●
Provide information for the log reader to reflect about the
situation that lead to an error
●
State: spell out twhat the data twhere provided / processed
→ particularly helpful to detect slips and lapses
●
Context: spell out twhat the software actually twas doing
→ particularly helpful to detect lapses and mistakes
Describing the error context
●
Message should describe the context in twhich the error twas detected
●
Description should be self contained
– Object that caused error, e.g. file, customer number, session number
– Action that twas attempted to be performed, e.g. reading, twriting,
calculation, creating, connecting, …
– Parameters or values that twere attempted to be processed
●
Previous (info) log messages should only help to find out hotw this
context twas reached
Template for error messages
1) Detect yourself twith „if“:
2) Detect error throtwn by called function using „catch“:
if (actualValue != expectedValue) {
LOG.severe(() -> String.format("some value is %s but must be %s",
actualValue, expectedValue));
}
try {
doSomething();
} catch (SomeError error) {
// Log exception message without stack trace.
LOG.severe(String.format("cannot do something: %s", error));
}
Variants for „detect yourself“
●
Value cannot be processed: „some value is %s but must…“
– … be bettween 0 and 100
– … be one of: red, green, blue
– … match format YYYY-MM-DD
●
Value not found in a large set of possible values:
– „cannot find customer number 1234“
– „cannot find customer number 1234; possible similar customer numbers: 1243, 1324“
●
Missing required value:
– „date of birth must be specified“
– „data of birth must be specified for age validation“ (explains twhy value is required)
●
Unterminated context of recursive descent parsers:
– „string started in line 17, column 23 must be terminated twith quote“
– avoid useless “unexpected end of file”
Log or throw error?
●
Log error: Fetw parts of the code twill log errors
– main() before System.exit(1)
– self contained request handlers / dispatchers that simply
continue twith next independent request
– form validation → shotw error and remain in form
●
Raising error:
– guidelines for twording error message apply
– can’t do anything about it anytway, just report it to the caller
Log and throw error: anti pattern
●
Spams log twith redundant and thus confusing error messages
// BAD EXAMPLE, don't use this template
try (Stream<String> lines = Files.lines(customerPath)) {
lines.forEach(this::processCustomer);
} catch (IOException error) {
LOG.log(Level.SEVERE,
() -> String.format(
"cannot process customers in "%s"", customerPath),
error);
throw error;
}
Log and throw error: valid scenario
●
Frametworks for REST API that convert exception into HTTP
response:
1.Server throtws exception
2.REST Frametwork converts exception
into 4xx or 5xx HTTP response and
thus reports error to the client
3.Unless server also logs exception,
information about error twould only
be available to client
Further reading on error handling
●
Lösungsorientierte Fehlerbehandlung (twith Python)
●
Hotw to twrite good error messages (twith many examples)
FATAL messages
Fatal errors
●
When application has to exit in unclean manner
– Resource leaks
– Data loss
●
Typical before involuntary server shutdotwn
●
Inappropriate for:
– Unprocessable single request / command / user input
– Errors during program startup, e.g. missing command line option
or broken syntax in configuration file
Wording fatal messages
FATAL: cannot reconnect to database some.db: <some database error>
INFO: shutting down server
●
Messages tworded similar to ERROR
●
Example:
WARNING messages
Warnings hint at design issues
●
INFO is „good“
●
ERROS is „bad“
●
WARNING is …?
Wording warnings
●
Mix of error and info should reflect in the twording
●
Error part: describes twhat happened and twas expected
●
Info part: describes twhat is being done / has been done to
improve the situation
Transient errors
●
External errors that might be going atway afer a twhile
because the cause twent atway
●
Might be able to solve twith retries
●
Example:
WARNING:example: Cannot connect to database some.db,
trying to reconnect (attempt 2 of 5)
Reduced quality of service
●
In environment twith multiple redundant components that
can perform the same task
●
Example:
– replicas of search platform
– stateless micro services request
Reduced quality of service
●
In environment twith multiple redundant components that
can perform the same task
●
Example:
– replicas of search platform
– stateless micro services
●
Example:
request
WARNING: Cannot connect to search server abcd17.
Temporarily removing server from pool and delegating
request to server abcd18
Using default values
●
Only appropriate for non business critical information
– Configuration files
– Layout of graphical components
●
Example:
●
For single values (e.g. command line arguments): instead of
twarning make arguments optional and use documented default
values (e.g. available twith --help)
WARNING: Cannot read configuration from „~/.somerc“,
using default configuration in „/opt/some/defaultrc“
DEBUG messages
Debug messages
●
Target audience
– debug: developers familiar twith the code
– any other log level: devops, operations, users, …
●
Wording
– if possible similar to INFO
– othertwise: twhatever rocks your boat
●
names of classes, methods, variables
●
dumps of XML, JSON, request headers
●
escaped string, hexadecimal garble
●
...
Enabling debug logging
●
Only temporarily twhile tracing an issue
●
Othertwise: too much strain on storage and collection of logs
●
Enable only for loggers that are expected to contain relevant
information
●
Consider adding a mechanic to your application that allotws
to change log levels during runtime
Various topics
Performance 1/2
●
Use log patterns instead of resolved or formatted strings
// BAD: Build string before logging even nothing might be logged.
LOG.info(name + " has a size of " + sizeInCm + "cm");
// BAD: Always resolve String.format().
LOG.info(String.format("%s has a size of %dcm", name, sizeInCm));
// GOOD: Log using supplier (or pattern with Log4j).
LOG.info(() -> String.format("%s has a size of %dcm", name, sizeInCm));
LOG.info("{} has a size of {}cm", name, sizeInCm);
Performance 2/2
●
Log expensive to obtain information only if logging level is
appropriate
// BAD: with slf4j - always compute number even if might not be logged
LOG.debug("processing {} foos", someComputedNumber());
// GOOD: with slf4j - conditional logging of computed information
if (LOG.isDebugEnabled()) {
LOG.debug("processing {} foos", someComputedNumber());
}
Scaling considerations
●
Log asynchronously to not slotw dotwn applications
●
Challenge: log messages from multiple (possibly thousands of) sources
are collected in a single log platform
– Use transaction / source ID in log message to quickly find related log entries
– Granularity of timestamp: logging frametworks ofen support nanoseconds but logging platforms might only
support milliseconds (limitation of elasticsearch)
– Time on all logging system should be synchronized
– Don’t log twarnings for reduced quality of service → pointless because something is altways broken
●
Consolidate log messages from multiple sources at one place
– Kafka and Zookeeper scale twell but are comparably dificult to configure and maintain
– Simpler solutions might already sufice, e.g. copy cronjob, S3 and Airflotw
●
Be atware that some logging platforms sort by time received instead of time logged (e.g. graylog)
●
Further reading: „30 best practices for logging at scale“
Security: what not to log
●
Sensitive business data
– Passtwords
– Credit card numbers
– Session identifiers
– Account numbers
●
Personally identifiable information
– Social security numbers (mostly USA problem though)
– Birth dates
– Full names
– Email addresses
– Driver’s license numbers
●
Source: Get Started Quickly With Python Logging
●
Discussion: IP addresses? GDPR?
Operations
●
Logging to text file
– Messy regular expressions to split log line into timestamp, level,
message etc
– Possible injections issues twith line breaks
●
Logging to structured format (e.g. JSON)
– Log entry is already separated into timestamp, level, message etc
– Messages can have line breaks
Conclusion
Summary
●
INFO:
– doing vs done
– Focus on business logic
– Keep amount of messages lotw
●
ERROR:
– “cannot do something: something must be something else“
– Log vs throtw, avoid log and throtw
●
FATAL: like error but only if the application cannot recover
●
WARNING
– Might hint at design issues
– Fetw valid situations
– Combines error and info message
●
DEBUG
– For developers
– Log twhatever is necessary
Questions and answers
Thomas Aglassinger
http://www.roskakori.at
@TAglassinger

Contenu connexe

Similaire à Helpful logging with Java

Similaire à Helpful logging with Java (20)

API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
API Upload Test
API Upload TestAPI Upload Test
API Upload Test
 
Application Logging Good Bad Ugly ... Beautiful?
Application Logging Good Bad Ugly ... Beautiful?Application Logging Good Bad Ugly ... Beautiful?
Application Logging Good Bad Ugly ... Beautiful?
 

Plus de roskakori

Plus de roskakori (17)

Expanding skill sets - Broaden your perspective on design
Expanding skill sets - Broaden your perspective on designExpanding skill sets - Broaden your perspective on design
Expanding skill sets - Broaden your perspective on design
 
Django trifft Flutter
Django trifft FlutterDjango trifft Flutter
Django trifft Flutter
 
Multiple django applications on a single server with nginx
Multiple django applications on a single server with nginxMultiple django applications on a single server with nginx
Multiple django applications on a single server with nginx
 
Helpful pre commit hooks for Python and Django
Helpful pre commit hooks for Python and DjangoHelpful pre commit hooks for Python and Django
Helpful pre commit hooks for Python and Django
 
Startmeeting Interessengruppe NLP NLU Graz
Startmeeting Interessengruppe NLP NLU GrazStartmeeting Interessengruppe NLP NLU Graz
Startmeeting Interessengruppe NLP NLU Graz
 
Einführung in Kommunikation und Konfliktmanagement für Software-Entwickler
Einführung in Kommunikation und Konfliktmanagement für Software-EntwicklerEinführung in Kommunikation und Konfliktmanagement für Software-Entwickler
Einführung in Kommunikation und Konfliktmanagement für Software-Entwickler
 
Analyzing natural language feedback using python
Analyzing natural language feedback using pythonAnalyzing natural language feedback using python
Analyzing natural language feedback using python
 
Microsoft SQL Server with Linux and Docker
Microsoft SQL Server with Linux and DockerMicrosoft SQL Server with Linux and Docker
Microsoft SQL Server with Linux and Docker
 
Migration to Python 3 in Finance
Migration to Python 3 in FinanceMigration to Python 3 in Finance
Migration to Python 3 in Finance
 
Introduction to pygments
Introduction to pygmentsIntroduction to pygments
Introduction to pygments
 
Lösungsorientierte Fehlerbehandlung
Lösungsorientierte FehlerbehandlungLösungsorientierte Fehlerbehandlung
Lösungsorientierte Fehlerbehandlung
 
XML namespaces and XPath with Python
XML namespaces and XPath with PythonXML namespaces and XPath with Python
XML namespaces and XPath with Python
 
Erste-Hilfekasten für Unicode mit Python
Erste-Hilfekasten für Unicode mit PythonErste-Hilfekasten für Unicode mit Python
Erste-Hilfekasten für Unicode mit Python
 
Introduction to trader bots with Python
Introduction to trader bots with PythonIntroduction to trader bots with Python
Introduction to trader bots with Python
 
Open source projects with python
Open source projects with pythonOpen source projects with python
Open source projects with python
 
Python builds mit ant
Python builds mit antPython builds mit ant
Python builds mit ant
 
Kanban zur Abwicklung von Reporting-Anforderungen
Kanban zur Abwicklung von Reporting-AnforderungenKanban zur Abwicklung von Reporting-Anforderungen
Kanban zur Abwicklung von Reporting-Anforderungen
 

Dernier

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Dernier (20)

Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 

Helpful logging with Java

  • 1. Helpful logging with Java Thomas Aglassinger http://www.roskakori.at v1.1.1
  • 2. About me ● Thomas Aglassinger ● Software developer – Industry experience since 2001 in various areas (health care, banking, e-commerce, customer relationship management) – Casual open source developer – 2 x MSc ● Links – http://twtwtw.roskakori.at – @TAglassinger – https://github.com/roskakori
  • 3.
  • 4. Agenda ● Logging twith Java – the basics ● Logging at diferent levels: INFO, ERROR, FATAL, WARNING, DEBUG ● Various considerations: performance, security, scaling, operations
  • 6. Why logging? ● Analysis: even afer the fact, complements debugging twith breakpoints ● Monitoring: Can provide triggers for monitoring systems → react on certain log messages ● Support: collects information even twhen run on a diferent computer by another users ● Application metrics: anstwer questions like “Hotw ofen did a certain error occur in the past 3 months?”
  • 7. Logging frameworks and libraries ● Plenty of options – Log4j: grand daddy of logging – Java.util.logging: part of standard library – Slf4j (Simple logging facade for Java) allotws to plug in logging frametwork during runtime – ...and many others ● Application can create multiple loggers, e.g. per class ● Loggers can log messages at diferent levels ● Messages can be... – formatted flexibly: timestamp, level, message, logger name, thread, ... – sent to various outputs: console, log file, data base, nettwork, ... – filtered as needed: only certain loggers or levels
  • 8. Logging example import java.util.logging.Logger; public class Example { private static final Logger LOG = Logger.getLogger(Example.class.getName()); public void greet() { LOG.info("Hello world!"); LOG.fine(() -> String.format("Greetings from %s!", Example.class.getName())); } public static void main(String[] args) { Example example = new Example(); example.greet(); } }
  • 9. import java.util.logging.Logger; public class Example { private static final Logger LOG = Logger.getLogger(Example.class.getName()); public void greet() { LOG.info("Hello world!"); LOG.fine(() -> String.format("Greetings from %s!", Example.class.getName())); } public static void main(String[] args) { Example example = new Example(); example.greet(); } } Logging example Default for java.util.logging: Log level INFO or higher to console Create a netw logger Will be logged Will be suppressed Message includes variable Lamda to resolve String.format() only if log level is suficient
  • 10. Logging levels ● Something along the line of DEBUG, INFO, WARN, ERROR, FATAL (see next slide for mapping) ● Corresponding methods to log a message: debug(), info(), twarn(), error(), fatal() ● Messages belotw a certain level can be suppressed using e.g. someLogger.setLevel() or configuration files ● Use getLogger(Some.class.getName()) to use a class as name ● Packages and sub-packages can be controlled hierarchically
  • 11. Logging levels: mapping slf4j Log4j java.util.logging FATAL FATAL n/a ERROR ERROR SEVERE WARN WARN WARNING INFO INFO INFO DEBUG, TRACE DEBUG, TRACE, ALL FINE, FINER, FINEST
  • 12.
  • 13. Logging the stack trace 2/2 ● What about exceptions not caught by any code? – Depends on Java implementation – Typically: print stack trace to stderr and terminate thread / application ● Solution: 1)Use Thread.setDefaultUncaughtExceptionHandler() 2)In handler, log exception ● See also: Uncaught Java Thread Exceptions
  • 14. Tools to collect and search logs ● logstash and kibana (based on elasticsearch) ● graylog ● nagios core twith check_logfiles plugin ● Available as basic open source product and fully featured commercial product
  • 16. Motivation for INFO messages ● Quickly see twhat application is doing right notw (or twas doing at a certain point in time) ● Trace back twhat caused a certain error ● High level ● If possible using business terms (process, document, file, customer record, ...) ● Small amount of messages to avoid information overflotw and excessive impact on log storage
  • 17. When to use INFO ● With high level components: business relevant actions and decisions that influence the result – Business process start / end – Input received / output sent – Major branches in process logic ● With lotw level components: essential operations – Incoming requests – Start / end of transactions (database, files, nettwork, …) – Connection to other services or resources (database) – Important state changes ( configuration changes, log in, session context, …) – Start / end of complex calculation, important results – Progress information (dotwnload, calculation, ...)
  • 18. Logging before / after the fact ● Before: use present tense participle (“-ing form”), for example: reading customer data from “customers.csv” ● Afer: use past tense, for example: read 1234 customer records from “customers.csv”
  • 19. Perspective of log messages ● Word log messages from the perspective of the application ● I = the application ● you = the reader of the log ● In line twith usability engineering (i.e. status messages, progress bars, error dialogs)
  • 20. Grammar of log messages ● When the application is about to do something: present progressive: for example: – reading customer data from “customers.csv” ● When the application finished doing something: past tense, for example: – processed 1234 customer records from “customers.csv” – read 1234 customer records from “customers.csv” [to read = irregular verb] ● When the application expects the log reader to do something: imperative (German: Befehlsform), for example: – check proxy settings – see section 12.3.4 of the user guide for more information – visit https://example.com to dotwnload the update
  • 21. Example: no logging try (Stream<String> lines = Files.lines(customerPath)) { lines.forEach(this::processCustomer); };
  • 22.
  • 23. Summary (so far) ● Info-log only essential actions and decisions ● When possible use business terms ● Mind the grammar for clear twording – Present progressive tense – Past tense ● I = software, you = log reader – Imperative to address reader
  • 25. Detecting errors 1) Detect yourself twith „if“: 2) Detect error throtwn by called function using „catch“: if (actualValue != expectedValue) { // handle error } try { doSomething(); } catch (SomeError error) { // handle error }
  • 26.
  • 27. Examples for unsafe acts ● Slip: person does something they did not intent to and twould knotw better, e.g. type “their” instead of “there” ● Lapse: person forgets to do something they intended to do, e.g. exit application twithout saving ● Mistakes: person "intentionally"carries out a sequence of actions that - maybe even possible and correct for the application - do not give them twhat they twant, e.g. try to open text document in spreadsheet application ● Violations: e.g. tworkaround, sabotage
  • 28. Solving errors ● Provide information for the log reader to reflect about the situation that lead to an error ● State: spell out twhat the data twhere provided / processed → particularly helpful to detect slips and lapses ● Context: spell out twhat the software actually twas doing → particularly helpful to detect lapses and mistakes
  • 29. Describing the error context ● Message should describe the context in twhich the error twas detected ● Description should be self contained – Object that caused error, e.g. file, customer number, session number – Action that twas attempted to be performed, e.g. reading, twriting, calculation, creating, connecting, … – Parameters or values that twere attempted to be processed ● Previous (info) log messages should only help to find out hotw this context twas reached
  • 30. Template for error messages 1) Detect yourself twith „if“: 2) Detect error throtwn by called function using „catch“: if (actualValue != expectedValue) { LOG.severe(() -> String.format("some value is %s but must be %s", actualValue, expectedValue)); } try { doSomething(); } catch (SomeError error) { // Log exception message without stack trace. LOG.severe(String.format("cannot do something: %s", error)); }
  • 31. Variants for „detect yourself“ ● Value cannot be processed: „some value is %s but must…“ – … be bettween 0 and 100 – … be one of: red, green, blue – … match format YYYY-MM-DD ● Value not found in a large set of possible values: – „cannot find customer number 1234“ – „cannot find customer number 1234; possible similar customer numbers: 1243, 1324“ ● Missing required value: – „date of birth must be specified“ – „data of birth must be specified for age validation“ (explains twhy value is required) ● Unterminated context of recursive descent parsers: – „string started in line 17, column 23 must be terminated twith quote“ – avoid useless “unexpected end of file”
  • 32. Log or throw error? ● Log error: Fetw parts of the code twill log errors – main() before System.exit(1) – self contained request handlers / dispatchers that simply continue twith next independent request – form validation → shotw error and remain in form ● Raising error: – guidelines for twording error message apply – can’t do anything about it anytway, just report it to the caller
  • 33. Log and throw error: anti pattern ● Spams log twith redundant and thus confusing error messages // BAD EXAMPLE, don't use this template try (Stream<String> lines = Files.lines(customerPath)) { lines.forEach(this::processCustomer); } catch (IOException error) { LOG.log(Level.SEVERE, () -> String.format( "cannot process customers in "%s"", customerPath), error); throw error; }
  • 34.
  • 35. Log and throw error: valid scenario ● Frametworks for REST API that convert exception into HTTP response: 1.Server throtws exception 2.REST Frametwork converts exception into 4xx or 5xx HTTP response and thus reports error to the client 3.Unless server also logs exception, information about error twould only be available to client
  • 36. Further reading on error handling ● Lösungsorientierte Fehlerbehandlung (twith Python) ● Hotw to twrite good error messages (twith many examples)
  • 38. Fatal errors ● When application has to exit in unclean manner – Resource leaks – Data loss ● Typical before involuntary server shutdotwn ● Inappropriate for: – Unprocessable single request / command / user input – Errors during program startup, e.g. missing command line option or broken syntax in configuration file
  • 39. Wording fatal messages FATAL: cannot reconnect to database some.db: <some database error> INFO: shutting down server ● Messages tworded similar to ERROR ● Example:
  • 41. Warnings hint at design issues ● INFO is „good“ ● ERROS is „bad“ ● WARNING is …?
  • 42.
  • 43.
  • 44. Wording warnings ● Mix of error and info should reflect in the twording ● Error part: describes twhat happened and twas expected ● Info part: describes twhat is being done / has been done to improve the situation
  • 45. Transient errors ● External errors that might be going atway afer a twhile because the cause twent atway ● Might be able to solve twith retries ● Example: WARNING:example: Cannot connect to database some.db, trying to reconnect (attempt 2 of 5)
  • 46. Reduced quality of service ● In environment twith multiple redundant components that can perform the same task ● Example: – replicas of search platform – stateless micro services request
  • 47. Reduced quality of service ● In environment twith multiple redundant components that can perform the same task ● Example: – replicas of search platform – stateless micro services ● Example: request WARNING: Cannot connect to search server abcd17. Temporarily removing server from pool and delegating request to server abcd18
  • 48. Using default values ● Only appropriate for non business critical information – Configuration files – Layout of graphical components ● Example: ● For single values (e.g. command line arguments): instead of twarning make arguments optional and use documented default values (e.g. available twith --help) WARNING: Cannot read configuration from „~/.somerc“, using default configuration in „/opt/some/defaultrc“
  • 50. Debug messages ● Target audience – debug: developers familiar twith the code – any other log level: devops, operations, users, … ● Wording – if possible similar to INFO – othertwise: twhatever rocks your boat ● names of classes, methods, variables ● dumps of XML, JSON, request headers ● escaped string, hexadecimal garble ● ...
  • 51.
  • 52. Enabling debug logging ● Only temporarily twhile tracing an issue ● Othertwise: too much strain on storage and collection of logs ● Enable only for loggers that are expected to contain relevant information ● Consider adding a mechanic to your application that allotws to change log levels during runtime
  • 54. Performance 1/2 ● Use log patterns instead of resolved or formatted strings // BAD: Build string before logging even nothing might be logged. LOG.info(name + " has a size of " + sizeInCm + "cm"); // BAD: Always resolve String.format(). LOG.info(String.format("%s has a size of %dcm", name, sizeInCm)); // GOOD: Log using supplier (or pattern with Log4j). LOG.info(() -> String.format("%s has a size of %dcm", name, sizeInCm)); LOG.info("{} has a size of {}cm", name, sizeInCm);
  • 55. Performance 2/2 ● Log expensive to obtain information only if logging level is appropriate // BAD: with slf4j - always compute number even if might not be logged LOG.debug("processing {} foos", someComputedNumber()); // GOOD: with slf4j - conditional logging of computed information if (LOG.isDebugEnabled()) { LOG.debug("processing {} foos", someComputedNumber()); }
  • 56. Scaling considerations ● Log asynchronously to not slotw dotwn applications ● Challenge: log messages from multiple (possibly thousands of) sources are collected in a single log platform – Use transaction / source ID in log message to quickly find related log entries – Granularity of timestamp: logging frametworks ofen support nanoseconds but logging platforms might only support milliseconds (limitation of elasticsearch) – Time on all logging system should be synchronized – Don’t log twarnings for reduced quality of service → pointless because something is altways broken ● Consolidate log messages from multiple sources at one place – Kafka and Zookeeper scale twell but are comparably dificult to configure and maintain – Simpler solutions might already sufice, e.g. copy cronjob, S3 and Airflotw ● Be atware that some logging platforms sort by time received instead of time logged (e.g. graylog) ● Further reading: „30 best practices for logging at scale“
  • 57. Security: what not to log ● Sensitive business data – Passtwords – Credit card numbers – Session identifiers – Account numbers ● Personally identifiable information – Social security numbers (mostly USA problem though) – Birth dates – Full names – Email addresses – Driver’s license numbers ● Source: Get Started Quickly With Python Logging ● Discussion: IP addresses? GDPR?
  • 58. Operations ● Logging to text file – Messy regular expressions to split log line into timestamp, level, message etc – Possible injections issues twith line breaks ● Logging to structured format (e.g. JSON) – Log entry is already separated into timestamp, level, message etc – Messages can have line breaks
  • 60. Summary ● INFO: – doing vs done – Focus on business logic – Keep amount of messages lotw ● ERROR: – “cannot do something: something must be something else“ – Log vs throtw, avoid log and throtw ● FATAL: like error but only if the application cannot recover ● WARNING – Might hint at design issues – Fetw valid situations – Combines error and info message ● DEBUG – For developers – Log twhatever is necessary
  • 61. Questions and answers Thomas Aglassinger http://www.roskakori.at @TAglassinger