Sie sind auf Seite 1von 84

Logging

or System.out.println() 2.0 author: Alex Maskovyak date: 2012-04-27

Logging
or System.out.println() 2.0 author: Alex Maskovyak date: 2012-04-27

Metadata

Agenda

S Objectives

S Overview
S Principles S Next Steps

Objectives

Objectives

S Define what logging is.

S Understand the benefits of logging.


S Identify logging best practices. S Understand how to use the new logging framework.

Motivation

S Make the life of you, the developer, easier

S Make the life of the developer after you easier

Overview

Definition

S process of recording events, with an automated

computer program, in a certain scope in order to provide an audit trail that can be used to understand the activity of the system and to diagnose problems

Definition

S process of recording events, with an automated

computer program, in a certain scope in order to provide an audit trail that can be used to understand the activity of the system and to diagnose problems

What it is

S Provides insight into the state and operation of the

system.

S Provides application-level information in an

audience-appropriate manner.

S Necessary operation of software during the S Part of the Definition of Done

maintenance phase of an applications life.

Purposes

S Expose application state

S Trace execution
S Document configuration state S Monitor for errors/warnings S Debug code S Provide system performance/timing

What it isnt

S Calls to System.out.println()

S Necessary only during development


S Magic that occurs without developer support S Complete substitute for documentation, comments,

and testing.

Java Logging

Libraries
S

S
S S S

JDK 1.4+ java.util.logging (JUL) log4j nlog4j log5j LogBack

Common frameworks
S S

Jakarta/Apache Commons Logging Slf4j

Log Viewers Analyzers


S S

Chainsaw Lilith

slf4j

S S S S S

Simple Logging Facade for Java Designed by log4j creator Binds to logging frameworks Bridges to legacy logging APIs Provides a migrator

S
S S

Supports parameterized logging


slf4j-access provides servlet support JBoss provides slf4j-jboss-logmanager.jar

LogBack

S Successor to log4j

S Fast message generation


S Automatic configuration file reloading S Conditional configuration files S Filters S Logback Console Plugin

Java Logging Example JUL

public class AwesomeObject { private static Logger logger = Logger.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.log(Level.INFO, Starting app, explicit Level ex.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = Logger.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.log(Level.INFO, Starting app, explicit Level ex.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = Logger.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.log(Level.INFO, Starting app, explicit Level ex.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = Logger.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.log(Level.INFO, Starting app, explicit Level ex.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = Logger.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.log(Level.INFO, Starting app, explicit Level ex.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = Logger.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.log(Level.INFO, Starting app, explicit Level ex.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public static void main(String args) { logger.entering( AwesomeObject.class.getName(), main, args); try { crash(); } catch( Exception e ) { logger.logp( Level.SEVERE, AwesomeObject.class.getName(), main, Encountered a problem! See exc, e); } logger.exiting( AwesomeObject.class.getName(), main, Exiting application., 0);

public static void main(String args) { logger.entering( AwesomeObject.class.getName(), main, args); try { crash(); } catch( Exception e ) { logger.logp( Level.SEVERE, AwesomeObject.class.getName(), main, Encountered a problem! See exc, e); } logger.exiting( AwesomeObject.class.getName(), main, Exiting application., 0);

public static void main(String args) { logger.entering( AwesomeObject.class.getName(), main, args); try { crash(); } catch( Exception e ) { logger.logp( Level.SEVERE, AwesomeObject.class.getName(), main, Encountered a problem! See exc, e); } logger.exiting( AwesomeObject.class.getName(), main, Exiting application., 0);

Java Logging Example slf4j & LogBack

public class AwesomeObject { private static Logger logger = Logger.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = LoggerFactory.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = LoggerFactory.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.finer(Got arg0=+args[0]+ arg1+args[1]);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = LoggerFactory.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.debug(Got args: {}, args);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = LoggerFactory.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.debug(Got args: {}, args);

try { crash(); } catch( Exception e ) { logger.severe(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = LoggerFactory.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.debug(Got args: {}, args);

try { crash(); } catch( Exception e ) { logger.error(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = LoggerFactory.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.debug(Got args: {}, args);

try { crash(); } catch( Exception e ) { logger.error(Encountered a problem! See exc, e); } logger.log(Level.FINER, Exiting application.);

public class AwesomeObject { private static Logger logger = LoggerFactory.getLogger(AwesomeObject.class.getName()); public static void main(String args) { logger.info(Starting application.); logger.debug(Got args: {}, args);

try { crash(); } catch( Exception e ) { logger.error(Encountered a problem! See exc, e); } logger.log(new myExitMarker(), Exiting application.);

Know Your Audience

S System administrators/operators
S Installing application.
S Starting application. S Shutting down application.

Know Your Audience

S Support Personnel
S Monitors of application.

Know Your Audience

S Developers
S Debugging applications.
S Measuring performance. S Using your class/API.

Know Your Audience

S Machines
S Scripts
S Automation tools S Operation tools

Severity Levels

S Partition log space


S Digestible pieces
S Triage-able levels.

Not Triage-able
S S S S S

DEBUG: Began session DEBUG: DB access pass for user_id=154314, measure_id=14. DEBUG: DB access fail for user_id=41234113, measure_id=15. DEBUG: DB access pass for user_id=1341234, measure_id=14. DEBUG: DB access pass for user_id=8224122, measure_id=14.

S
S S S S

DEBUG: DB access pass for user_id=1143456, measure_id=14.


DEBUG: DB access pass for user_id=17111341, measure_id=14. DEBUG: DB access fail for user_id=17521344113, measure_id=14. DEBUG: DB access pass for user_id=17, measure_id=131422. DEBUG: Ended session

via audit tool ...or even a grep


S S S S S

DEBUG: Began session DEBUG: DB access pass for user_id=154314, measure_id=14. ERROR: DB access fail for user_id=41234113, measure_id=15. DEBUG: DB access pass for user_id=1341234, measure_id=14. DEBUG: DB access pass for user_id=8224122, measure_id=14.

S
S S S S

DEBUG: DB access pass for user_id=1143456, measure_id=14.


DEBUG: DB access pass for user_id=17111341, measure_id=14. ERROR: DB access fail for user_id=17521344113, measure_id=14. DEBUG: DB access pass for user_id=17, measure_id=131422. DEBUG: Ended session

Severity Levels

S FATAL
S Application down.
S Application inaccessible. S High-level features are inaccessible. S Application aborted.

Severity Levels

S ERROR (SEVERE)
S Application was unable to recover from a problem.
S Application was able to recover but was unable to

fulfill a request or contract.

Severity Levels

S WARN
S Potentially harmful problem has occurred that warrants

further investigation. S No fault occurred.

Severity Levels

S INFO
S Broad-brush
S High-level S Coarse-grain S System progress or state.

Severity Levels

S DEBUG (FINE)
S Low-level
S Fine-grain S Information for debugging S Generally turned off on production systems unless a

problem is detected where high-level information is insufficient.

Hierarchies

S Further separation of concerns

Hierarchies

S NONE: All technical details

S TIMING: Performance info

Hierarchies

S SECURITY: Security relevant information


S Failed logins
S Creation of users S Access to invalid URLs S Potentially unsafe user-input

S Spikey user requests

Hierarchies

S AUDIT
S Completed / Failed business transactions.
S DB access. S Service access.

Hierarchies

S USER: user behavior


S Invalid data entered
S Actions used

Persistence

S Multiple files.
S Per application.
S Per date. S Per hierarchy/concerns.

Persistence

S File-system first, HBase later.

S /usr/local/explorys/[application-name]/
S [application-name]-[date].log

Principles
What, Where, When, & How

Principle #1

System.out is not adequate logging

Principle #2

Logging should occur during development

Principle #3

Logging must be descriptive and useful to others

Principle #3 Ex.1
S NO (does not contain valuable information):
S log.debug(Here);
S log.debug(+++DEBUG+++); S log.debug(randomVariableWithoutLogComment);

Principle #3 Ex.2
S NO: S log.debug(Array values: {}, myArray); S Will print out a reference identity: Array@4dc911a5 S Does not have an overloaded toString();

S YES S log.debug(Array values: {}, Arrays.toString(myArray)); S Prints out a human-readable string value.

Principle #3 Recipe for a Good Message


S What is your reason for logging

/ Why are you logging.

S Root cause.

Principle #3 Recipe for a Good Message


S What needed to happen

/ Affected use-case.

S User creation? S Measure execution? S Measure deletion?

Principle #3 Recipe for a Good Message


S What instance was effected?
S User id.
S Measure id. S Measure group id.

Principle #3 Recipe for a Good Message


S What did and what didnt happen

/ Effect on Use-case

S User needs to repeat action, or did it succeed? S Did entire batch fail, or did just a single step?

Principle #3 Where & When


S Application state changes
S Startup
S Shut-down

Principle #3 Where & When


S Configuration
S Source of configuration
S S S

Files used Environment VM arguments

S Values of parameters
S Packages/Libraries

Principle #3 Where & When


S Method Invocation S Start
Method name S Parameter names/values S Time entered
S

S End S Method return value S Exit statement S Time returned

Principle #3 Ex.3
public Measures[] getMeasures(User user, String type) { log.debug( BEGIN getMeasures(user={}, type={}), user, type); Measures[] res = ; log.debug(END getMeasures() => {}, res.length); return res; }

Principle #3 Where & When


S Exceptions
S Where the exception is actually handled/caught.
S S S

Top-most level. Not where it is transformed. Not when it is first thrown.

S When all information is available


S Avoid repetition

Principle #3 Ex.4
S NO:

try {} catch(Exception e) { log.error(Caught exception, did nothing, e); throw e; } Exception e = ; log.error( Created exc and printed it redundantly here, e); throw e;

S NO:

Principle #3 Where & When


S Long-lived Calls S e.g.
S

IO
S File S DB

Services S SOA S REST

S Log before & after call

Principle #4

Logging should be DRY and concise.

Principle #5

Log with an audience in mind.

Principle #5 Ex.1
S ADMIN: S log.error( PDV failed to start because the datasource {} could not be accessed, please ensure that {} is accessible by); S DEV: S log.error( PDV attempted to do {} but was unable to because of exception {});

Principle #6

Be mindful of performance

Principle #6 Ex.1
S Acquire a single logger instance.
S private Logger logger =

LoggerFactory.getLogger(classname); S @Inject Logger logger;


S Avoid processing large collections of objects.
S No: log.info(Returning measures {}, measures); S Yes: log.info(Returning measured ids {}, ); S Yes: log.info(Returning total measure id count {}, );

Principle #6 Ex.2
S Logging info quantity/size can/should be altered

based upon status.

If (log.isDebugEnabled()) { log.debug(Measures requested {}); } else { log.info(Measure ids requested {}); }

Principle #7

Use performance values appropriately.

Principle #7 Ex.1
S Yes:

StopWatch watch = new LoggingStopWatch( dbio ); longlivedIO(); watch.stop();


S Yes:

log.info(Finished {} measure results in {} secs.); log.info(Average calculation {} secs / result);


S No:

public String getName() {}

Principle #8

S Be safe

S Avoid causing problems


S Avoid side effects

Principle #8 Ex.1
S log.debug(Obtained {}, user.getId()); S are you sure user isnt null? S log.debug(Obtained {}, collection.get(1)); S are you sure there there are enough elements? S log.debug(Connection closed: {}, conn.close()); S are you sure debug level statements are enabled? S are you sure theyll be enabled in production?

Next Steps

Action Items

S Alex
S Test slf4j and LogBack integration in current environment.
S Test slf4j migrator. S Test LogBack Eclipse tool.

S Team
S Study logger use. S Begin using standard jdk logging in the areas identified. S Be mindful of best-practices and principles.

Das könnte Ihnen auch gefallen