Slide 1

Slide 1 text

Java Logging: Ninth Circle of Hell A Gentle Introduction to Java Logging April 18th, 2013 Thursday, April 18, 13

Slide 2

Slide 2 text

So you want to log something System.out.println(); That’s it! Thursday, April 18, 13

Slide 3

Slide 3 text

Error logging If you’re Kyle (or sometimes me): println(“_______IN HERE ${important.var}”) println(“_________FFFFFUUUUU (${i})”) Thursday, April 18, 13

Slide 4

Slide 4 text

This is noise For the love of all that’s holy, use real logging We need more random output like we need AIDS Thursday, April 18, 13

Slide 5

Slide 5 text

Okay, so System.*.println() is so 1996, what’s the right way? Thursday, April 18, 13

Slide 6

Slide 6 text

The Right Way(TM) Thursday, April 18, 13

Slide 7

Slide 7 text

The Right Way(TM) So you’ve got... Thursday, April 18, 13

Slide 8

Slide 8 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) Thursday, April 18, 13

Slide 9

Slide 9 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Thursday, April 18, 13

Slide 10

Slide 10 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Apache Log4j Thursday, April 18, 13

Slide 11

Slide 11 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Apache Log4j SLF4J Thursday, April 18, 13

Slide 12

Slide 12 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Apache Log4j SLF4J Logback Thursday, April 18, 13

Slide 13

Slide 13 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Apache Log4j SLF4J Logback Blitz4j Thursday, April 18, 13

Slide 14

Slide 14 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Apache Log4j SLF4J Logback Blitz4j Apache Log4j2 Thursday, April 18, 13

Slide 15

Slide 15 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Apache Log4j SLF4J Logback Blitz4j Apache Log4j2 Proprietary crap Thursday, April 18, 13

Slide 16

Slide 16 text

The Right Way(TM) So you’ve got... Jakarta Commons Logging (JCL, ACL) java.util.logging (JUL) Apache Log4j SLF4J Logback Blitz4j Apache Log4j2 What. Proprietary crap Thursday, April 18, 13

Slide 17

Slide 17 text

How did we get here? What framework should we choose? Thursday, April 18, 13

Slide 18

Slide 18 text

A/S/L log4j (1999-2008) java.util.logging (2002) Jakarta Commons Logging (2002) Logback (2006-) SLF4J (2007-) Log4j2 (2012-) Blitz4j (??-) Thursday, April 18, 13

Slide 19

Slide 19 text

Thursday, April 18, 13

Slide 20

Slide 20 text

Thursday, April 18, 13

Slide 21

Slide 21 text

Logging Frameworks Thursday, April 18, 13

Slide 22

Slide 22 text

log4j Solid first choice, always a contender. Nobody was fired for using Log4j Old. You know you’re old when open Bugzilla tickets make it to primary school Pretty much dead. Little active development Java 4 compatible -- no Java 5 or 6 classes used, like Reentrant locks or CopyOnWrite lists for appenders Easily baffled if you step outside the box RollingFileAppender can deadlock easily Or reconfiguring Appenders at runtime, @Ken :) Thursday, April 18, 13

Slide 23

Slide 23 text

java.util.logging (JUL) log4j popped up when there was no logging Java introduced java.util.logging as a “standard” given log4j’s popularity It sucked in 1.4 and it sucks now Still better than println’s Advantage: Every VM since 1.4 has it Thursday, April 18, 13

Slide 24

Slide 24 text

Apache Commons Logging (JCL, ACL) Sort of like SLF4J, ‘ultra-thin facade’ JCP’s attempt to water down log4j Has serious issues with classloading If you’re using it, I weep for your children Thursday, April 18, 13

Slide 25

Slide 25 text

logback Successor of the log4j framework, many of the same developers Fixes many architectural issues More scalable (10x performance over log4j) Java code not written by prehistoric man “simply put, logback is just a better log4j” 3 packages: logback-core, logback-classic, logback-access logback-classic implements SLF4J natively Thursday, April 18, 13

Slide 26

Slide 26 text

logback-continued 14:28:48.835  [btpool0-­‐7]  INFO    c.q.l.demo.prime.PrimeAction  -­‐  99  is  not  a  valid  value java.lang.Exception:  99  is  invalid    at  ch.qos.logback.demo.prime.PrimeAction.execute(PrimeAction.java:28)  [classes/:na]    at  org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)  [struts-­‐1.2.9.jar:1.2.9]    at  org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)  [struts-­‐1.2.9.jar:1.2.9]    at  org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)  [struts-­‐1.2.9.jar:1.2.9]    at  javax.servlet.http.HttpServlet.service(HttpServlet.java:820)  [servlet-­‐api-­‐2.5-­‐6.1.12.jar:6.1.12]    at  org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)  [jetty-­‐6.1.12.jar:6.1.12]    at  ch.qos.logback.demo.UserServletFilter.doFilter(UserServletFilter.java:44)  [classes/:na]    at  org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115)  [jetty-­‐6.1.12.jar:6.1.12]    at  org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361)  [jetty-­‐6.1.12.jar:6.1.12]    at  org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)  [jetty-­‐6.1.12.jar:6.1.12]    at  org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)  [jetty-­‐6.1.12.jar:6.1.12] HELL YEAH Packaging information! (If enabled) Thursday, April 18, 13

Slide 27

Slide 27 text

Blitz4j Written by Netflix, framework on top of log4j that doesn’t suck Uses modern Java More granular locks Summarization logback wasn’t an option when they started “Blitz4j is a logging framework built on top of log4j to reduce multithreaded contention and enable highly scalable logging without affecting application performance characteristics. ... Blitz4j makes runtime reconfigurations of log4j pretty easy. Blitz4j also tries to mitigate data loss and provides a way to summarize the log information during log storms.” Thursday, April 18, 13

Slide 28

Slide 28 text

Log4j2 Forked log4j - competes with logback Uses Java 5 and Java 6 improvements Log4j 1 and 2 are NOT 100% compatible. Also very good, on par with logback in performance Configurable with XML or JSON Up to 10x faster than log4j 1.2.x Thursday, April 18, 13

Slide 29

Slide 29 text

So WTF is SLF4J? Simple Logging Facade for Java Thursday, April 18, 13

Slide 30

Slide 30 text

SLF4J Not really a ‘logging framework’ A facade around logging which allows any underlying framework to handle logging Allows framework-to-framework bridges Libraries become logging framework-agnostic Developed by log4j’s founder, Ceki Gülcü Thursday, April 18, 13

Slide 31

Slide 31 text

Basic API, use everywhere private  static  Logger  log  =  LoggerFactory.getLogger(MyClass.class); log.info(“It  usually  just  {}”,  “works”); log.error(“Oh  no!”,  e); Avoid  this: static  final  Logger  log  =  org.apache.log4j.LogManager.getLogger(this) Dependency on log4j SLF4J style Parameterized logging! org.slf4j.* Thursday, April 18, 13

Slide 32

Slide 32 text

Performance Gotchas if (log.isDebugEnabled()) { log.debug(“xxx” + user.getId()); } Thursday, April 18, 13

Slide 33

Slide 33 text

Performance Gotchas if (log.isDebugEnabled()) { log.debug(“xxx” + user.getId()); } log.debug(“xxx {}”, user.getId()); 2x slower than If user.getId() is cheap. Otherwise use the if guard for expensive operations. Both avoid .toString() costs Thursday, April 18, 13

Slide 34

Slide 34 text

Log levels Pretty standard across implementations TRACE DEBUG INFO WARN ERROR FATAL Pretty self explanatory Thursday, April 18, 13

Slide 35

Slide 35 text

Diagnostic Contexts Contextual logging (e.g. thread name, userId) Available on log4j, logback, and log4j2 Two different types: Nested & Mapped Thursday, April 18, 13

Slide 36

Slide 36 text

NDC Nested Diagnostic Contexts are stacks NDC.push(“x”); NDC.pop(); Useful for debugging looping or recursive structures Thursday, April 18, 13

Slide 37

Slide 37 text

MDC Mapped Diagnostic Context key-value pairs MDC.put(“userId”, user.getId()) Usually what you’ll use Show up in Graylog using the Graylog Appender Thursday, April 18, 13

Slide 38

Slide 38 text

Use any logging framework Or no framework - /dev/null Thursday, April 18, 13

Slide 39

Slide 39 text

Don’t use log4j-over-slf4j and slf4j-over-log4j .:. Your application will not boot. Thursday, April 18, 13

Slide 40

Slide 40 text

SLF4J & Log4j log4j-over-slf4j - convert log4j-only projects to SLF4J e.x. library uses log4j, you’re on logback slf4j-log4j - Anything using the SLF4J API now uses log4j as a backend logger Thursday, April 18, 13

Slide 41

Slide 41 text

Framework Support Supports log4j, log4j2, logback, JCL, and JUL All you really need is slf4j-api (1.7.5+ preferred) Usually just have to include the proper framework-slf4j jar Can also spawn nasty dependency issues Data must flow in one direction, so choose yours and use dependency reports & exclusions to make it happen Thursday, April 18, 13

Slide 42

Slide 42 text

Keep an eye on dependencies Thursday, April 18, 13

Slide 43

Slide 43 text

SLF4J over JUL over JCL over log4j Thursday, April 18, 13

Slide 44

Slide 44 text

Don’t do that Thursday, April 18, 13

Slide 45

Slide 45 text

| Error SLF4J: Class path contains multiple SLF4J bindings. | Error SLF4J: Found binding in [jar:file:/Users/xorlev/.grails/ivy-cache/org.grails/grails-plugin-log4j/jars/grails-plugin-log4j-2.1.1.jar!/org/slf4j/impl/ StaticLoggerBinder.class] | Error SLF4J: Found binding in [jar:file:/Users/xorlev/.grails/ivy-cache/org.slf4j/slf4j-log4j12/jars/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class] | Error SLF4J: Found binding in [jar:file:/Users/xorlev/.grails/ivy-cache/org.slf4j/slf4j-nop/jars/slf4j-nop-1.6.4.jar!/org/slf4j/impl/StaticLoggerBinder.class] StackOverflowException log4j-over-slf4j & slf4j-log4j You aren’t a Java engineer until you’ve debugged SLF4J Thursday, April 18, 13

Slide 46

Slide 46 text

Implement SLF4J API in Libraries People I will thank you - It’s easy and just works* * Usually Thursday, April 18, 13

Slide 47

Slide 47 text

Configuring log4j & logback Thursday, April 18, 13

Slide 48

Slide 48 text

Appenders Send data places ConsoleAppender NTEventLogAppender SyslogAppender SMTPAppender GraylogAppender Implementing your own is easy Thursday, April 18, 13

Slide 49

Slide 49 text

Log4j Configured using log4j.properties files Issues? -Dlog4j.debug Thursday, April 18, 13

Slide 50

Slide 50 text

# Appender config log4j.appender.A1.File = ${storm.home}/logs/${logfile.name} log4j.appender.A1.Append = true log4j.appender.A1.DatePattern = '.'yyy-MM-dd log4j.appender.A1.layout = org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c [%p] %m%n log4j.appender.graylog=org.graylog2.log.GelfAppender log4j.appender.graylog.graylogHost=graylog.site.com log4j.appender.graylog.facility=storm log4j.appender.graylog.extractStacktrace=true log4j.appender.graylog.addExtendedInformation=true log4j.appender.graylog.additionalFields={'environment': 'production', 'application': 'storm'} log4j.appender.graylog.Threshold=ERROR log4j.rootLogger=INFO, graylog, AI Thursday, April 18, 13

Slide 51

Slide 51 text

Logback Configured using logback.xml (or .groovy) Or programmatically https://github.com/smarchive/dropwizard-gelf/blob/ master/src/main/java/com/smarchive/dropwizard/ gelf/bundles/GelfLoggingBundle.java Thursday, April 18, 13

Slide 52

Slide 52 text

%d{HH:mm:ss.SSS} TKD [%thread] %-5level %logger{36} - %msg%n See https://github.com/Moocar/logback-gelf for a Graylog example Compose appenders Also works in log4j Thursday, April 18, 13

Slide 53

Slide 53 text

Questions? TL;DR: Use logback or log4j if you can Using the SLF4J API makes it easy to log without knowing what your host VM looks like e.x. Tomcat / Storm Log4j2 is still in alpha/beta Thursday, April 18, 13