log4j2

42

Upload: joergreichert

Post on 19-Jan-2017

918 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Log4j2
Page 2: Log4j2

Trac

ing

use cases

Execution time

system statuscurrent environment

parameters

issue recognition

progress

Page 3: Log4j2

stackholders

developers

production timesystem engineers

managers

users

testers

lawyers DevOps

Page 4: Log4j2

requirements

easy to use APIstackholder specific logs

readable logs

completenessperformance

client specific logging (UI, console, build job)

reliablecorrectness

use case specific logging (production,testing, debugging)

historic data

relevant logs

Page 5: Log4j2

What to log

• reporter (who discovered)

• affected element

• severity

• message

• issue code

• additional data (e.g. exception object)

Page 6: Log4j2

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

Page 7: Log4j2

Log levels (2)<Configuration … status="INFO">

<Loggers>

<Root level="INFO">

<AppenderRef ref="SYSERROUT" />

</Root>

<Logger name="org.apache.logging.log4j2" level="INFO" />

<Logger name="my.package.MyIgnoreClass" level="OFF" />

</Loggers>

</Configuration>

Page 8: Log4j2

Appenders<?xml version="1.0" encoding="UTF-8"?> <Configuration …>

<Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> …</Console>

…</Appenders><Loggers>

<Logger name="my.package"> <appender-ref ref="STDOUT" /> </Logger>

</Loggers></Configuration>

Page 9: Log4j2

Appenders

• ConsoleAppender• FileAppender

– RollingFileAppender– RandomAccessFileAppender

• Messaging– JMSAppender– SMTPAppender

• DB– JDBCAppender– JPAAppender– NoSQLAppender

• Remote– SocketAppender– SyslogAppender

Page 10: Log4j2

Appenders

• Wrapper– FailoverAppender– AsyncAppender

<Async name="Async">

<AppenderRef ref="MyFile"/>

</Async>– RoutingAppender .. explained later with MDC– RewriteAppender .. explained later with Message API

Page 11: Log4j2

FailoverAppender<Failover name="Failover" primary="RollingFile">

<Failovers>

<AppenderRef ref="Console"/>

</Failovers>

</Failover>

Page 12: Log4j2

Layout

• PatternLayout

• HTMLLayout

• XMLLayout

• JSONLayout

• SerializedLayout

Page 13: Log4j2

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

Page 14: Log4j2

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

Page 15: Log4j2

Properties<?xml version="1.0" encoding="UTF-8"?><Configuration …>

<Properties><Property name="defaultDatePattern">

%date{dd.MM.yyyy HH:mm:ss,SSS} </Property>

<Property name="defaultLoggerPattern"> %5p %logger %marker %m%n </Property>

<Property name="defaultLogPattern"> ${defaultDatePattern} ${defaultLoggerPattern} </Property>

</Properties> … </Configuration>

Page 16: Log4j2

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

Page 17: Log4j2

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"

Page 18: Log4j2

Routing Appender<Console name="SYSERR"> … </Console>

<Routing name="ConsoleAppenderRouteIssueCode">

<Routes pattern="${ctx:issueCode}">

<Route>

<Console name="ConsoleAppenderWithIssueCode">

<PatternLayout pattern="${ctx:issueCode} -

${defaultLoggerPattern}"/>

</Console>

</Route>

<Route ref="SYSERR" key="${ctx:issueCode}" />

</Routes>

</Routing>

<AppenderRef ref="ConsoleAppenderRoute">

Page 19: Log4j2

Lookup● $${ctx:myThreadContextPropertyKey}● ${ctx:myThreadMapContextPropertyKey}● ${sys:mySystemPropertyKey}● ${map:myMapMessageKey}● $${date:MM-dd-yyyy}● $${env:USER}● ${java:runtime}● $${jndi:logging/context-name}● define custom lookup plugins

Page 20: Log4j2

Markersprivate 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);

Page 21: Log4j2

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

Page 22: Log4j2

Regex Filter<?xml version="1.0" encoding="ASCII"?>

<Configuration name=„MyLogger" …>

<Filters>

<RegexFilter regex=".*stringToMatch.*" onMatch="DENY"

onMismatch="NEUTRAL"/>

</Filters>

</Configuration>

Page 23: Log4j2

Thread Context Map Filter<Loggers>

<Root level="error">

<AppenderRef ref="RollingFile"/>

<ThreadContextMapFilter onMatch="ACCEPT"

onMismatch="NEUTRAL" operator="or">

<KeyValuePair key="foo" value="bar"/>

<KeyValuePair key="User2" value="WARN"/> </ThreadContextMapFilter>

</Root>

</Loggers>

Page 24: Log4j2

Message API

• pass built-in or custom message objects• org.apache.logging.log4j.message

– ParameterizedMessage– MapMessage– SimpleMessage– ObjectMessage– Message

logger.info(new LoggedInMessage(map, user));

Page 25: Log4j2

RewriteLogger logger = LogManager.getLogger(MyClass.class);

Map<String, String> msg = new HashMap<String, String>();

msg.put("creditcard", "123456789");

logger.info(new MapMessage(msg));

Page 26: Log4j2

Rewrite (2)<Rewrite name="rewrite">

<AppenderRef ref="myweb"/>

<MapRewritePolicy mode="Update">

<KeyValuePair key="creditcard" value="XXXXXXXXXX"/>

</MapRewritePolicy>

</Rewrite>

<Logger …>

<Appender-Ref ref="rewrite" />

</Logger>

source: https://gomtiprabha.wordpress.com/2014/03/11/rewrite-appender-in-log4j2/

Page 27: Log4j2

Flow tracingpublic String method(String input) {

logger.entry(input);

return logger.exit();

}

Page 28: Log4j2

package my.custom.log4j2.plugins;

@Plugin(name = "Sandbox", type = "Core", elementType = "appender")

public class SandboxAppender extends AppenderBase {

private SandboxAppender(String name, Filter filter) {

super(name, filter, null);

}

public void append(LogEvent event) {

System.out.println(event.getMessage().getFormattedMessage());

}

@PluginFactory

public static SandboxAppender createAppender(

@PluginAttr("name") String name,

@PluginElement("filters") Filter filter) {

return new SandboxAppender(name, filter);

}

}

Plug-in infrastructure

Page 29: Log4j2

Plug-in infrastructure (2)<configuration … packages="my.custom.log4j2.plugins">

<appenders>

<Sandbox />

</appender>

</configuration>

Page 30: Log4j2

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

Page 31: Log4j2

XInclude<?xml version="1.0" encoding="UTF-8"?>

<configuration …>

<ThresholdFilter level="debug"/>

<xi:include href="log4j-xinclude-appenders.xml" />

<xi:include href="log4j-xinclude-loggers.xml" />

</configuration>

Page 32: Log4j2

Performance

source: https://logging.apache.org/log4j/2.x/manual/async.html

Page 33: Log4j2

Logger configuration

• Centralize

• different context selectors– ThreadLocal– Classloader– JNDI– AsyncLogger

• Make all loggers async– Bundle

Page 34: Log4j2

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

Page 35: Log4j2

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

Page 36: Log4j2

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

Page 37: Log4j2

System.out.println(...)

System.err.println(...)

exception.printStackTrace()

FileWriter writer = ...;writer.write(...);writer.close();

LOGGER.error(...)

Bad practice (2)

Page 38: Log4j2

Bad practice (3)

Page 39: Log4j2

• 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

Page 40: Log4j2

Good practice (2)

Page 41: Log4j2

Log4J2 + Xtend Active Annotations

@Delegate (built-in)to derive custom loggers with a few customized methods

@Logto initialize instance log field with correct class as parameter

@TraceableTo annotate methods, so that logger.entry and logger.exit with input and output parameters are generated