There are actually 6 levels of debugging with log4j now:
We use Trace for following the flow of the application between methods and classes.
Debug is used for printing out state information about different classes. The attributes of an Email that is send.
Info is used when something interesting occurs in the application. Email is Send, Database connection created, contacted another external service, etc...
Warn, haven't used much.
Error, for when errors and exceptions occur that can be recovered from.
Fatal, for when errors and exceptions occur that CAN NOT be recovered from.
Log4j javadocs have a good explanation of when to use each level:
We also use if statements around all our trace, debug, and info statements to check if we're actually logging those values. If not, we do not produce the String that goes into the log method. In some case it is possible to create some pretty large strings that it would just be best not to produce if we don't have too.
// the toString() method of the Person class in this instance will print
// out all its attributes and if that attribute is an Object its toString()
// method will be called, etc... So this string can be quite expensive
// to create.
logger.debug("Person: " + person);