the art of logging an exploration with apache log4j 2 gary gregory [email protected]

72
The Art of Logging An exploration with Apache Log4j 2 Gary Gregory [email protected]

Upload: jason-stevens

Post on 18-Jan-2016

229 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

The Art of LoggingAn exploration with Apache Log4j 2

Gary Gregory

[email protected]

Page 2: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Gary Gregory

Principal Software Engineer, Rocket Software

C

Smalltalk

Java

Apache: Commons, Log4j, HttpComponents, Xalan

Books

Page 3: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com
Page 4: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Thank you Dealer.com for sponsoring this meeting and the Pumpkin Race!

Page 5: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Why log?

“Logs are like car insurance. Nobody wants to pay for it, but when something goes wrong everyone wants the best available” 

– Pablo Kraan

Page 6: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

The Road to Nowhere (0)

System.out.println("Starting " + new Date());

System.console().printf("Starting %s“, new Date());

Page 7: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

The Road to Nowhere (1)

public void test() {

println("Starting " + new Date());

}

private void println(String message) {

System.out.println(message);

}

Page 8: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

The Road to Nowhere (2)

public static boolean DEBUG = true;

public void test() {

println("Starting " + new Date());

}

private void println(String message) {

if (DEBUG) {

System.out.println(message);

}

}

Page 9: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

The Road to Nowhere (3)

public static boolean DEBUG = Boolean.getBoolean(“EBUG");

public void test() {

println("Starting " + new Date());

}

private void println(String message) {

if (DEBUG) {

System.out.println(message);

}

}

Page 10: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

The Road to Nowhere (4)

Destinations Console out, err. Files, what format(s)? And so on…

Event levels Source location? Timestamp formats Thread info? Configuration On and on and on…

Page 11: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Key Concepts: architecture

Split Logging API and implementations

Pluggable implementations

Modern logging frameworks do this

Apache Log4j 2

SLF4J + Logback

Apache Commons Logging (API only)

JUL

Log4j 1 did not, all-in-one

Page 12: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Log4j API architecture

Page 13: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Pluggable implementation: SLF4J

Page 14: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Key concepts

API

Configuration

Customization/Pluggability

Page 15: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Key concepts APIs

LogManager

Level

Logger

Marker

More:

Flow tracing with fish tagging

Context stack and context map

Page 16: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

LogManager

Creates Loggers

LogManager.getLogger(“com.example.SomeClass”);

LogManager.getLogger(SomeClass.class);

LogManager.getLogger();

Page 17: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

LogManager and Message Factories

Message factories

Login OK for user {} from terminal {}

Login OK for user {0} from terminal {1}

Login OK for user %s from terminal %s

ETL processed %,d records

Page 18: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Message Factories

org.apache.logging.log4j.LogManager.getLogger(Class|String|Object, MessageFactory)

FormattedMessageFactory

LocalizedMessageFactory

MessageFormatMessageFactory

ParameterizedMessageFactory

ParameterizedNoReferenceMessageFactory

SimpleMessageFactory

StringFormatterMessageFactory

Page 19: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Levels

How important is this event?

Who needs to know about this event?

Custom levels

Page 20: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

6 built-in Levels

Page 21: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Using Levels in applications

INFO : User Alice logged in.

WARN : User Bob entered an invalid password.

ERROR: User Bob entered an invalid password three times, user locked out.

DEBUG: Loading user Bob from database jdbc:...

INFO : Emailed user Bob: three login attempts rejected, user locked out.

ERROR: Email to Alice bounced back; subject: Your weekly summary.

Page 22: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Understanding Levels vs. Loggers

Message:

What it is I am telling my audience?

Levels

How important is this?

Loggers

Who’s talking now?

Page 23: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Hierachical Loggers

Loggers are named

Names are hierarchical: a.b.c, a,b, a, …

Page 24: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Hierachical loggers example

Kitchen

Kitchen.Oven

Kitchen.Oven.BottomOven

Kitchen.Oven.BottomOven.Door

Kitchen.Oven.BottomOven.Timer

Kitchen.Oven.BottomOven.Light

Kitchen.Oven.TopOven.Door

Kitchen.Oven.TopOven.Timer

Kitchen.Oven.TopOven.Light

Kitchen.Dishwasher

Kitchen.Refrigerator

Kitchen.Refrigerator.Door

Kitchen.Refrigerator.Filter

Kitchen.Refrigerator.Light

Kitchen.Refrigerator.Freezer.Door

Kitchen.Refrigerator.Freezer.Light

And so on…

Page 25: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Logger configuration

Hierarchical names: com.example.app.foo

Configure a logger or whole hierarchy:

<Root level=“warn">

<Logger name="javax.management" level="INFO" />

<Logger name=“com.example.app" level="INFO" />

<Logger name=“com.example.app.foo" level=“DEBUG" />

<Logger name=“com.example.app.bar" level=“TRACE" />

Page 26: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Using a Logger

logger.debug(“User {} logged in”, user);

logger.info(“User {} logged in”, user);

Page 27: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Logger granularity

One global logger

The root logger

Nah.

One per class

Use the FQCN

One per instance?

In specific cases

Use the FQCN + instance info

Watch for lots of short lived objects

Examples

Page 28: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Clever logger names

One per instance

Must use the logger name to uniquely identify a logger

com.example.server.socket.8080

com.example.rest.get.GetCustomer

Page 29: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced logging (0)

logger.debug("There are " + getUserCount() + " users logged in now.");

You are always building the full string before calling debug()

You are always calling getUserCount()

Both of the above happens even if debug logging is disabled!

Page 30: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced logging (1)

Guard it:

if (logger.isDebugEnabled()) {

logger.debug("There are " + getUserCount() + " users logged in now.");

}

Page 31: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced logging (3)

Parameterize it:

logger.debug("There are {} users logged in now.", getUserCount());

Page 32: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced logging (4)

Use lambdas!

logger.debug("There are {} users logged in now.", () -> getUserCount());

Page 33: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced message formatting (0)

FromThere are 2147483647 users logged in now.

ToThere are 2,147,483,647 users logged in now.

Page 34: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced message formatting (1)

Use a formatter logger:

Logger logger = LogManager.getFormatterLogger();

logger.debug("There are %,d users logged in now.", () -> getUserCount());

Page 35: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced message formatting (2)

You can format numbers like this as well:

logger.debug("Gain or loss: $ %(,.2f", delta);

Gives you:

Gain or loss: $ (12,582.19)

Page 36: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Getting to advanced message formatting (3)

You can get extra fancy with dates:

Calendar c = new GregorianCalendar(1918, MAY, 11);

logger.info("Richard Feynman's Birthday: %1$tb %1$te, %1$tY", c);

Gives you:

Richard Feynman's: May 11, 1918

Page 37: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Noodle on that one for a minute…

How would you only log open and close door events using loggers and levels?

You can assume that door events are logged at… what? Maybe some appliances log door events at the INFO level and others at the DEBUG level.

What if doors from a third party library log this kind of event at TRACE, another twist!

Page 38: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Understanding Markers

Instead of:

logger.info("Door opened");

...

logger.info("Door closed");

Do this:

logger.info(DOOR, "Door opened");

...

logger.info(DOOR, "Door closed");

Where DOOR is a constant that defines a marker:

public static final Marker DOOR = MarkerManager.getMarker(“DOOR”);

Page 39: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Configuring Makers (inclusive)<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="WARN" monitorInterval="5">

<Appenders>

<Console name="Console" target="SYSTEM_OUT" />

</Appenders>

<Loggers>

<Root level="WARN">

<AppenderRef ref="Console" />

</Root>

<Logger name="com.example.oven" level="DEBUG" />

<Logger name="com.example.garage" level="INFO" />

</Loggers>

<Filters>

<MarkerFilter marker="DOOR" onMatch="ACCEPT" onMismatch="DENY" />

</Filters>

</Configuration>

Page 40: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Hiding Marked events

If instead, we wanted to hide DOOR events, we’d say:

<MarkerFilter marker=“DOOR" onMatch="DENY" onMismatch="NEUTRAL" />

Page 41: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Marker usage examples

I’ve used markers for:

Different kinds of hex dumps:

Compressed buffers

Decompressed buffers

IO buffers

Different kinds of SQL statements:

Queries

Batches

Prepared statements

Flow tracing (built-in Log4j)

and more

Page 42: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Coding Flow Tracing

public String doIt() {

logger.entry();

String testMsg = compute()

return logger.exit(testMsg);

}

Page 43: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Configuring Flow Tracing

<File name="log" fileName="target/test.log" append="false">

<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>

</File>

Page 44: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Reading Flow Tracing

19:08:07.060 TRACE com.test.TestService 38 doIt - entry parms(0)

19:08:07.060 TRACE com.test.TestService 42 doIt - exit with (Hello, World)

Page 45: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Flow Tracing and Better Stack Traces

19:08:07.077 DEBUG com.test.TestService 32 exampleException - catching java.lang.ArrayIndexOutOfBoundsException: 3

at com.test.TestService.exampleException(TestService.java:29) [classes/:?]

at com.test.App.main(App.java:9) [classes/:?]

at com.test.AppTest.testApp(AppTest.java:15) [test-classes/:?]

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.6.0_29]

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[?:1.6.0_29]

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[?:1.6.0_29]

at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]

at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99) [junit-4.3.1.jar:?]

at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81) [junit-4.3.1.jar:?]

at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34) [junit-4.3.1.jar:?]

at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75) [junit-4.3.1.jar:?]

at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45) [junit-4.3.1.jar:?]

at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66) [junit-4.3.1.jar:?]

Page 46: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Flow Tracing Gotcha

Class

Method

Line

All comes from a stack snapshot

Page 47: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Fish Tagging

Many clients

Many threads

One logger per unique client

Page 48: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Fish tagging with context stack

ThreadContext.push(UUID.randomUUID().toString()); // Add the fishtag;

logger.debug("Message 1");

...

logger.debug("Message 2");

ThreadContext.pop();

Page 49: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Fish tagging with context map

ThreadContext.put("id", UUID.randomUUID().toString(); // Add the fishtag;

ThreadContext.put("ipAddress", request.getRemoteAddr());

ThreadContext.put("loginId", session.getAttribute("loginId"));

ThreadContext.put("hostName", request.getServerName());

...

logger.debug("Message 1");

...

logger.debug("Message 2");

...

ThreadContext.clear();

Page 50: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Fish tagging with pattern layout

Use %X by itself to include the full contents of the Map.

Use %X{key} to include the specified key.

Use %x to include the full contents of the Stack.

Page 51: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Key Concepts: Configuration

Appenders

Layouts

Filters

Page 52: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Appenders – where log events go

Async

Console

Failover

File

Flume

JDBC

JMS Queue

JMS Topic

JPA

Kafka

Memory-mapped file

NoSQL: CouchDB, MongoDB

Random-access file

Rewrite

Rolling file

Rolling random-access file

Routing

SMTP

Socket

Syslog

ZeroMQ

Page 53: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Layouts: What log events look like

Some appenders need a layout

Pattern layout

%d %-5level [%t][%logger] %msg%n%throwable

2015-10-25 19:23:10,652 DEBUG [main][org.jboss.logging] Logging Provider: org.jboss.logging.Log4j2LoggerProvider

2015-10-25 19:23:10,802 INFO [main][org.hibernate.Version] HHH000412: Hibernate Core {5.0.2.Final}

2015-10-25 19:23:10,802 INFO [main][org.hibernate.cfg.Environment] HHH000206: hibernate.properties not found

2015-10-25 19:23:10,802 INFO [main][org.hibernate.cfg.Environment] HHH000021: Bytecode provider name : javassist

Page 54: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

When to use %logger

Development, show who does the logging

Advanced configuration, for carefully control amount of logging

Page 55: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Layouts

CSV GELF HTML JSON Pattern RFC 5424 (enhanced

Syslog) Serialized

Syslog XML

Page 56: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Pattern Layout

%m%n

%d %-5level [%t][%logger]%notEmpty{[%markerSimpleName]} %msg%n%throwable

Page 57: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

PatternLayout %logger tricks

Conversion Pattern Logger Name Result

%c{1} org.apache.commons.Foo Foo

%c{2} org.apache.commons.Foo commons.Foo

%c{1.} org.apache.commons.Foo o.a.c.Foo

%c{1.1.~.~} org.apache.commons.test.Foo

o.a.~.~.Foo

%c{.} org.apache.commons.test.Foo

....Foo

Page 58: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

PatternLayout timestamp formats

Pattern Example

%d{DEFAULT} 2012-11-02 14:34:02,781

%d{ISO8601} 2012-11-02T14:34:02,781

%d{ISO8601_BASIC} 20121102T143402,781

%d{ABSOLUTE} 14:34:02,781

%d{DATE} 02 Nov 2012 14:34:02,781

%d{COMPACT} 20121102143402781

%d{HH:mm:ss,SSS} 14:34:02,781

%d{dd MMM yyyy HH:mm:ss,SSS} 02 Nov 2012 14:34:02,781

%d{HH:mm:ss}{GMT+0} 18:34:02

%d{UNIX} 1351866842

%d{UNIX_MILLIS} 1351866842781

Page 59: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

CSV columns

Time Nanos

Time Millis

Level

Thread Name

Formatted Message

Logger FQCN

Logger Name

Marker

Thrown Proxy

Source

Context Map

Context Stack

Page 60: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

CSV example

0,1441617184044,DEBUG,main,"one=1, two=2, three=3",org.apache.logging.log4j.spi.AbstractLogger,,,,org.apache.logging.log4j.core.layout.CsvLogEventLayoutTest.testLayout(CsvLogEventLayoutTest.java:98),{},[]

Page 61: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

JSON example[

{

"logger":"com.foo.Bar",

"timestamp":"1376681196470",

"level":"INFO",

"thread":"main",

"message":"Message flushed with immediate flush=true"

},

{

"logger":"com.foo.Bar",

"timestamp":"1376681196471",

"level":"ERROR",

"thread":"main",

"message":"Message flushed with immediate flush=true"

}

]

Page 62: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

XML example

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

2. <Events xmlns="http://logging.apache.org/log4j/2.0/events">

3. <Event logger="com.foo.Bar" timestamp="1373436580419" level="INFO" thread="main">

4. <Message><![CDATA[This is a log message 1]]></Message>

5. <Marker parent="Parent Marker"><Child Marker></Marker>

6. </Event>

7. <Event logger="com.foo.Baz" timestamp="1373436580420" level="INFO" thread="main">

8. <Message><![CDATA[This is a log message 2]]></Message>

9. <Marker><The Marker Name></Marker>

10. </Event>

11. </Events>

Page 63: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Know you audience

You’re a developer

Debug and trace your own code

DEBUG Opening file config.xml…

DEBUG Reading account [email protected] from…

TRACE Enter connectJdbc(“jdbc:…”)

TRACE Exit connectJdbc(“jdbc:…”): true

You inform users:

Display status:

INFO Starting server on port 80

INFO Listening for requests…

Page 64: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Know you audience

No clear cut rules

A warning to a developer may not be appropriate for a user

WARN Failed to connect to database DB1, failing over to DB2.

WARN Failed logon attempt #2, one more try before account lock out.

Page 65: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Asynchronous logging

Asynchronous Logging

Asynchronous Loggers

Page 66: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Synchronous logging

Page 67: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Asynchronous logging

LMAX Disruptor library

Page 68: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Mule ESB latency vs. concurrency

“how much latency was

added as we added more concurrent messages. The blue line are the

results of using Mule 3.5. The green line represent the latency of doing no logging at all. The read

line are the results using the new logging

infrastructure. Hey wait? Where’s the red line?!

Look closely, it’s almost on top of the green line, which means that now

logging doesn’t add any significant latency.“

http://blogs.mulesoft.com/dev/mule-dev/mule-3-6-asynchronous-logging/

Page 69: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Mule ESB throughput vs. concurrency

“we see how many TPS (transactions per second) were delivered as the concurrency increased. Again, we see our new asynchronous logging infrastructure performing very closely to not logging at all and showing a huge improvement from our prior solution.”

http://blogs.mulesoft.com/dev/mule-dev/mule-3-6-asynchronous-logging/

Page 70: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

What we did not talk about

Custom loggers

Custom levels

Custom appenders

Custom layouts

Custom message factories

Using multiple-inheritance with Markers

The plugin system

Logger contexts

Web app configuration

Page 71: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Learning more

Gary Gregory

[email protected]

https://garygregory.wordpress.com/

Log4j

https://logging.apache.org/log4j/2.x

https://logging.apache.org/log4j/2.x/articles.html

Page 72: The Art of Logging An exploration with Apache Log4j 2 Gary Gregory garydgregory@gmail.com

Q & A