Are there technical reasons to prefer using logback instead of log4j?

Should new projects use logback instead of log4j as a logging framework ?

Or with other words :'Is logback better than log4j (leaving the SLF4J-'feature' of logback beside)?'


Solution 1:

You should use SLF4J+Logback for logging.

It provides neat features like parametrized messages and (in contrast to commons-logging) a Mapped Diagnostic Context (MDC, javadoc, documentation).

Using SLF4J makes the logging backend exchangeable in a quite elegant way.

Additionally, SLF4J supports bridging of other logging frameworks to the actual SLF4J implementation you'll be using so logging events from third party software will show up in your unified logs - with the exception of java.util.logging that can't be bridged the same way that other logging frameworks are.

Bridging jul is explained in the javadocs of SLF4JBridgeHandler.

I've had a very good experience using the SLF4J+Logback combination in several projects and LOG4J development has pretty much stalled.

SLF4J has the following remaining downsides:

  • It does not support varargs to stay compatible with Java < 1.5
  • It does not support using both parametrized message and an exception at the same time.
  • It does not contain support for a Nested Diagnostic Context (NDC, javadoc) which LOG4J has.

Solution 2:

The author (of both Logback and Log4j) has a list of reasons to change at http://logback.qos.ch/reasonsToSwitch.html.

Here are a few that stuck out at me;

  • Faster implementation

    Based on our previous work on log4j, logback internals have been re-written to perform about ten times faster on certain critical execution paths. Not only are logback components faster, they have a smaller memory footprint as well.

  • Automatic reloading of configuration files

    Logback-classic can automatically reload its configuration file upon modification. The scanning process is both fast and safe as it does not involve the creation of a separate thread for scanning. This technical subtlety ensures that logback plays well within application servers and more generally within the JEE environment.

  • Stack traces with packaging data

    When logback prints an exception, the stack trace will include packaging data. Here is a sample stack trace generated by the logback-demo web-application.

    14:28:48.835 [btpool0-7] INFO c.q.l.demo.prime.PrimeAction - 99 is not a valid value java.lang.Exception: 99 is invalid
    at ch.qos.logback.demo.prime.PrimeAction.execute(PrimeAction.java:28) [classes/:na] at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431) [struts-1.2.9.jar:1.2.9] at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236) [struts-1.2.9.jar:1.2.9] at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) [struts-1.2.9.jar:1.2.9] at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) [servlet-api-2.5-6.1.12.jar:6.1.12]
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502) [jetty-6.1.12.jar:6.1.12] at ch.qos.logback.demo.UserServletFilter.doFilter(UserServletFilter.java:44) [classes/:na] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115) [jetty-6.1.12.jar:6.1.12] at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361) [jetty-6.1.12.jar:6.1.12] at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417) [jetty-6.1.12.jar:6.1.12] at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230) [jetty-6.1.12.jar:6.1.12]

    From the above, you can recognize that the application is using Struts version 1.2.9 and was deployed under jetty version 6.1.12. Thus, stack traces will quickly inform the reader about the classes invervening in the exception but also the package and package versions they belong to. When your customers send you a stack trace, as a developer you will no longer need to ask them to send you information about the versions of packages they are using. The information will be part of the stack trace. See "%xThrowable" conversion word for details.

    This feature can be quite helpful to the point that some users mistakenly consider it a feature of their IDE.

  • Automatic removal of old log archives

    By setting the maxHistory property of TimeBasedRollingPolicy or SizeAndTimeBasedFNATP, you can control the maximum number of archived files. If your rolling policy calls for monthly rollover and you wish to keep one year's worth of logs, simply set the maxHistory property to 12. Archived log files older than 12 months will be automatically removed.

There may be a bias there, but the same guy did write both frameworks and if he is saying use Logback over Log4j he's probably worth listening to.

Solution 3:

I would use slf4j for logging in all cases. This allow you to choose which actual logging backend you want to use, at deploy time instead of code time.

This has proven to be very valuable to me. It allows me to use log4j in old JVM's, and logback in 1.5+ JVM's, and also java.util.logging if needed.

Solution 4:

Logback more Java EE aware:
in general (from code to documentation) it’s keeping in mind containers – how multiple apps coexist, how class loaders implemented etc. Contexts for loggers, JNDI, JMX configuration included etc.

from developer prospective almost same, Logback adds Parameterized logging (no need to use if(logger.isDebugEnabled()) to avoid string concatenation overhead )

Log4j – only giant plus is old JVM support, small (IMO) NDC (Logback only MDC), some extensions. For example I wrote extension for configureAndWatch for Log4j, no such thing for Logback