This document provides an overview of logging concepts and configuration in Log4j 2. It describes what to log, different log levels, appenders for outputting logs, layouts for formatting log messages, and ways to filter, route, and rewrite logs. It also covers best practices for logging, programmatic configuration, plugins, and using Log4j 2 with other technologies like OSGi and Xtend annotations.
4. requirements
easy to use API
stackholder
specific logs
readable logs
completenessperformance
client specific
logging
(UI, console,
build job)
reliable
correctness
use case specific
logging (production,
testing, debugging)
historic data
relevant logs
5. What to log
• reporter (who discovered)
• affected element
• severity
• message
• issue code
• additional data (e.g. exception object)
6. Log levels
• built-in: OFF, TRACE, DEBUG, INFO, WARN, ERROR, FATAL
• Custom log levels
• no level inheritance (as in log4j 1.x and logback), because
separation of logger configuration and logger
13. Pattern Layout
<PatternLayout
pattern= " %date{dd.MM.yyyy HH:mm:ss,SSS} %5p %logger
%m%n" />
%5p (oder %level) .. log level, maximal 5 Buchstaben, rechtbündig
%logger .. logger name
%c .. class name
%m .. log message
%n .. platform dependent line break
%M .. class method
14. Pattern Layout (2)
• %t .. Name of the thread
• xException["none"|"short"|"full"|depth],[filters(packages)}
• xThrowable["none"|"short"|"full"|depth],[filters(packages)}
• xEx{"none"|"short"|"full"|depth],[filters(packages)}
– %xEx{short} .. Nur erste Zeile des Throwable
– %xEx{n} .. n Zeilen
– %xEx{none} oder %xEx{0} .. unterdrücken
• MDC{key} später erklärt
16. Nested Diagnostic Context
(NDC)
• stack
• context is stored per thread
• use push and pop to add and remove information
NDC.push("processingLevel2");
log.info("success");
log4j.appender.CA.layout.ConversionPattern
=%d{yyyy-MM-dd HH:mm:ss.SSSS} %p %C %x = %m%n
%x .. Accessing information
17. Mapped Diagnostic Context
(MDC)
• context is stored per thread
• MDC.put(), MDC.get(), and MDC.remove()
MDC.put("userIP", req.getRemoteAddr());
MDC.put("userName", foo.getName());
log.info("success");
log4j.appender.CA.layout.ConversionPattern=%d{yyyy-MM-dd
HH:mm:ss.SSSS} %p %X{userIP} %C %X{userName} = %m%n
%X{userName} .. retrieves value for key "userName"
20. Markers
private static final Marker SQL_MARKER =
MarkerManager.getMarker("SQL");
private static final Marker UPDATE_MARKER =
MarkerManager.getMarker("SQL_UPDATE", SQL_MARKER);
private static final Marker QUERY_MARKER =
MarkerManager.getMarker("SQL_QUERY", SQL_MARKER);
…
logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);
21. Filters
BurstFilter .. throttle logging when too many logs produced
ThresholdFilter .. filters by log level ranges
RegexFilter .. messages have to match regex
MarkerFilter .. log event filter by marker resp. its sub type
TimeFilter .. log only at certain times of day
MapFilter .. filters by entries in MapMessage
StructuredDataFilter .. special MapFilter
DynamicThresholdFilter .. z.B. debug only for user id X
ThreadContextMapFilter .. ThreadContext Map entries
CompositeFilter .. apply multiple filters
30. Reconfigure
<?xml version="1.0" encoding="UTF-8"?>
<configuration monitorInterval="30">
...
</configuration>
• monitoring interval is a value in seconds
• log4j 2 would reconfigure logging in case something has
changed in your configuration
• log4j 2.0 does not lose logging events at the time of
reconfiguration
33. Logger configuration
• Centralize
• different context selectors
– ThreadLocal
– Classloader
– JNDI
– AsyncLogger
• Make all loggers async
– Bundle
34. OSGi
• Configure BundleContextSelector
– associates LoggerContexts with the ClassLoader of the
bundle that created the caller of the getLogger call
• Own logger API and central logger config
– Derive Eclipse plug-in project from log4j2 jars
– Define fragment project to define your own logger API
• In MANIFEST set
– Eclipse-ExtensibleAPI: true
35. Programmatic access
-Dlog4j.configurationFile= ...
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig =
config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.setLevel(level);
ctx.updateLoggers(); // loggers refetch information from their
LoggerConfig
36. Bad practice
• logging errors that has been already handled by application
code (e.g. failed login)
• log messages with line breaks
• non unified formatted log messages (no tabs)
• long log messages (can be avoid by shorten the package
name)
• in tests use logging where assertions would have been a
better choice (as they really enforce expected behavior
where logs can be ignored)
• not logging exception objects
• using custom appenders holding state
39. • use timestamps for every event
• log thread name
• log source of event (e.g. class name and message)
• log ids from domain (e.g. transaction id)
• concise and descriptive messages
• use rolling file appender (to restrict single log file size)
• log method inputs and output at debug resp. trace level
• log full exception objects
• log no more than necessary in production
Good practice
41. Log4J2 + Xtend Active
Annotations
@Delegate (built-in)
to derive custom loggers with a few
customized methods
@Log
to initialize instance log field with correct
class as parameter
@Traceable
To annotate methods, so that logger.entry
and logger.exit with input and output
parameters are generated
42. Links
• Log4j2
• Apache Log4j 2.0 - Worth the Upgrade?
• The new log4j 2.0
• The Logging Olympics – A Race Between Today’s Top 5 Java
Logging Frameworks