Dragons in the Algorithm
Adventures in Programming
by Michael Chermside

Logging APIs - Evaluating Options

In my previous post, I defined a number of different features that logging libraries could have. This time, I will evaluate some Java libraries based on those features. I'll start by ranking these according to how important I think they are, at least for my purposes.

  1. Severity - mandatory: no logging system should be without this
  2. Tree of Log Topics - mandatory: no logging system should be without this
  3. Configurable - vital: configuring log levels at runtime is something we use often
  4. Rotating Log Files - vital: our log files would be too big for the OS without this
  5. Configurable Log Line Format - vital: it is unlikely that the off-the-shelf fields would be the ones we want to use
  6. Logging of Exceptions - vital: getting stack traces from logs is one of our most productive debugging techniques
  7. Delayed String Construction - vital: I consider this to be an very undervalued feature. Without it, software will be slowed significantly and also will be less readable.
  8. Log to Multiple Locations - desirable: sometimes this is handy. We used to use it, but at the moment we don't.
  9. Configure where Logs are Directed - desirable: this, too, we have used in the past but are not using right now.
  10. Standard or Widely Used - desirable: in the Java world, only Log4J (the most widely used library) and java.util logging (which is in the standard library).
  11. Unique Messages - desirable: as suggested in the comments, an ability to identify each log usage uniquely (probably by source file and line number) would be handy.
  12. Sensible Fallbacks - desirable: it's nice that the library works OK when your config fails, because it helps in debugging the config problem.
  13. Logging Queued to Avoid Delays - nice extra: although this seems like it would be a very useful feature, I do not know of any serious production logging tools that implement it.
  14. Threadlocal Context Data - nice extra: theoretically, this is extremely useful. In practice, people usually live without it and find the data by reading back through the log.
  15. Log Filtering - nice extra: if this were easy, we would use it to filter out SSNs and passwords from our logs, but we can live without it.
  16. Internationalization - undesirable: I recommend against ever using this. Use logging ONLY for developers, NOT for end users; all developers should speak the same language.

Next, I will assemble a list of different logging libraries in Java to be evaluated.

  • `Log4J <http://logging.apache.org/log4j/>`__: Log4J by Apache is the most widely used logging framework in Java.
  • `Java util logging <http://java.sun.com/javase/6/docs/api/index.html?java/util/logging/package-summary.html>`__: Rather than adopting Log4J as the standard for logging in Java, Sun chose to clone it, creating something almost-but-not-quite the same as a standard Java library.
  • `Commons Logging/Log4J <http://commons.apache.org/logging/>`__: Commons Logging is a wrapper from Apache which is designed for use in libraries. It simply delegates to an underlying logging framework. The purpose is so a library can be configured to use the same logging system as the rest of the application. I will consider Commons Logging backed by Log4J.
  • `SLF4J/Log4J <http://www.slf4j.org/>`__: SLF4J is a project begun by the original author of Log4J. It is intended to provide a better API for calling into a logging framework, and it can connect to different logging back ends. I will consider SLF4J backed by Log4J.

There are others (logback, jLo, and many others), but I am fairly confident that one of these 4 will be the final choice, so at this point I am going to perform a full analysis just on these 4.

Feature   Log4J JavaUtil Commons /Log4J SLF4J/Log4J
Severity mandatory Yes Yes Yes Yes
Tree of Log Topics mandatory Yes Yes Yes Yes
Configurable vital Yes Yes Yes Yes
Rotating Log Files vital Yes Yes Yes Yes
Configurable Log Line Format vital Yes Yes Yes Yes
Logging of Exceptions vital Yes Yes Yes Yes
Delayed String Construction vital No No No Yes
Log to Multiple Locations desirable Yes Yes Yes Yes
Configure where Logs are Directed desirable Yes Yes Yes Yes
Standard or Widely Used desirable Yes Yes No No
Unique Message desirable No No No No
Sensible Fallbacks desirable Meh Meh Meh Meh
Logging Queued to Avoid Delays nice extra No No No No
Threadlocal Context Data nice extra Yes No No Yes
Log Filtering nice extra No No No No
Internationalization undesirable No No No No

Woodpile

So, after considering all of these options, I have concluded that my preference is to use SLF4J as an interface, with the implementation from Log4J. Most of the options I have considered have more or less the same features. The deciding factors are (1) Threadlocal storage (MDC) is useful and not present in java.util.logging, and (2) The API for SLF4J provides an elegant solution to delay string construction, which is rather important for performance.

Conveniently, SLF4J publishes a tool for automatically converting existing java.util.logging and Log4J code to SLF4J, so the conversion should be relatively painless.

Posted Tue 09 February 2010 by mcherm in Programming