Apache Log4j
Apache Log4J
This is the second Java library I’ve mentioned (the first was Apache Commons Primitives), and it won’t be the last.
Apache Log4J is a logging system that is designed to have the same interface as java.util.Logging’s (the faq suggests a find and replace of all the util.Logger calls with org.apache.log4j.Logger will do the trick).
Why should you use a logging framework rather than System.out.println / System.err.println calls throughout your code? Here are a few reasons
- Ability to specify the level of detail of a message, whether it is a warning vs an error vs a debug statement. With this granularity you can filter out all but a certain level of messages so as to avoid scroll blindness when too much is being printed out to the screen.
- Ability to configure the logger at run time without changing the binary as to whether or not certain logging is performed.
- You get more information about when and where a logged statement came from. By default you get the time the statement was logged, as well as name of the logger that logged the message (which, if you follow the Log4j suggestion to use the class name of the file containing the logger, will tell you where the statement came from)
- It will prepare you for developing for the Android operating system, where you cannot just call System.out.println and have it appear in a terminal. I learned about logging from Android before finding out about this log4j library; they have very similar syntax, though with slightly more succint method names

- You can customize the way objects are rendered as text by the logger via an ObjectRenderer instance
Here’s some source code to get you started:
// Similar to the example from http://logging.apache.org/log4j/1.2/manual.html
// with additional comments
public class TestLogging {
// Idiomatic way of getting one logger per class; will automatically
// extract class name etc from this .class object
private static final Logger logger = Logger.getLogger(TestLogging.class);
public static void main(String[] args) {
// This call is necessary somewhere to actually hook up the Logger's
// with sensible default values. If you don't need course grained
// control over what is logged, this is sufficient. Output
// will go to standard out (terminal) after this command.
BasicConfigurator.configure();
logger.error("There was an error");
logger.warn("Warning");
logger.info("Informational message");
logger.debug("Debug message");
logger.trace("Really, really fine grained detail")
}
}
I haven’t learned all the ins and outs of the library yet, but it definitely seems a bit more scalable and professional than having print statements littered throughout the code base. Furthermore, the library was designed with speed in mind so the cost of logging statements is barely more than simply dumping it to standard out.