java.util.logging keeps you from having to tote one more jar file around with your application, and it works well with a good Formatter.
In general, at the top of every class, you should have:
Copyprivate static final Logger LOGGER = Logger.getLogger( ClassName.class.getName() );
Then, you can just use various facilities of the Logger class.
Use Level.FINE for anything that is debugging at the top level of execution flow:
CopyLOGGER.log( Level.FINE, "processing {0} entries in loop", list.size() );
Use Level.FINER / Level.FINEST inside of loops and in places where you may not always need to see that much detail when debugging basic flow issues:
CopyLOGGER.log( Level.FINER, "processing[{0}]: {1}", new Object[]{ i, list.get(i) } );
Use the parameterized versions of the logging facilities to keep from generating tons of String concatenation garbage that GC will have to keep up with. Object[] as above is cheap, on the stack allocation usually.
With exception handling, always log the complete exception details:
Copytry {
...something that can throw an ignorable exception
} catch( Exception ex ) {
LOGGER.log( Level.SEVERE, ex.toString(), ex );
}
I always pass ex.toString() as the message here, because then when I "grep -n" for "Exception" in log files, I can see the message too. Otherwise, it is going to be on the next line of output generated by the stack dump, and you have to have a more advanced RegEx to match that line too, which often gets you more output than you need to look through.
java.util.logging keeps you from having to tote one more jar file around with your application, and it works well with a good Formatter.
In general, at the top of every class, you should have:
Copyprivate static final Logger LOGGER = Logger.getLogger( ClassName.class.getName() );
Then, you can just use various facilities of the Logger class.
Use Level.FINE for anything that is debugging at the top level of execution flow:
CopyLOGGER.log( Level.FINE, "processing {0} entries in loop", list.size() );
Use Level.FINER / Level.FINEST inside of loops and in places where you may not always need to see that much detail when debugging basic flow issues:
CopyLOGGER.log( Level.FINER, "processing[{0}]: {1}", new Object[]{ i, list.get(i) } );
Use the parameterized versions of the logging facilities to keep from generating tons of String concatenation garbage that GC will have to keep up with. Object[] as above is cheap, on the stack allocation usually.
With exception handling, always log the complete exception details:
Copytry {
...something that can throw an ignorable exception
} catch( Exception ex ) {
LOGGER.log( Level.SEVERE, ex.toString(), ex );
}
I always pass ex.toString() as the message here, because then when I "grep -n" for "Exception" in log files, I can see the message too. Otherwise, it is going to be on the next line of output generated by the stack dump, and you have to have a more advanced RegEx to match that line too, which often gets you more output than you need to look through.
Should declare logger like this:
Copyprivate final static Logger LOGGER = Logger.getLogger(MyClass.class.getName());
so if you refactor your class name it follows.
I wrote an article about java logger with examples here.