Earlier this year I revisited how I was logging things in Java, and decided I would try a hybrid approach. I’m reporting back to say that it’s been successful. There are basically two ways I do it now:
Use java.util.Logging for libraries
It turns out that there’s nothing actually wrong with JUL aside from its limitations in terms of configuration. It has different names than the Ceki Gülcü loggers (warning() instead of warn(), finest() instead of trace(), etc.) but otherwise works the same. The configuration side of things I can’t even speak do as I haven’t had to configure it, I never use the actual JUL output.
Use Logback for applications
As suspected, Logback is basically just a new version of Log4J. It’s got some niceties like MDCInsertingServletFilter that means I don’t have to write that filter myself anymore, and it’s supposedly faster and more stable, so there’s no reason I can see not to use it. I also like that it has a format for condensing class names without completely losing the package names, so it goes from “com.efsavage.application.servlet.LoginServlet” to “c.e.a.s.LoginServlet” instead of just “LoginServlet”.
Why use two?
I like the fact that my libraries have zero logging dependencies and configuration, so I can always pop them into another app without adding baggage or conflicts or much additional configuration. I can upgrade the logger in one application without having to deal with version conflicts of my other apps and having to do classpath exclusions and that type of nastiness.
Tip
If you do it this way, and you see your JUL logging showing up twice, you can edit the default logging config in your JDK installation, or if you prefer to leave that untouched as I do, try this (via Java Bits):
java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
for (int i = 0; i < handlers.length; i++) {
rootLogger.removeHandler(handlers[i]);
}
SLF4JBridgeHandler.install();
This basically yankts out the default logger and let’s SLF4J do it’s thing alone. In a webapp you’ll probably throw this in your context listener or startup servlet where you previously did your log4j config.