Why use SLF4J over Log4J for logging in Java? Example
Anyway, let’s get back to the topic, on contrary to all those logging libraries, there is a major difference between them and SLF4J. SLF4J or Simple logging Facade for Java is not really a logging implementation, instead, it’s an abstraction layer, which allows you to use any logging library in the back-end.
If you are writing API or utility library, which can be used internally or externally, then you really don’t want that any client, which uses your library, should also stick with your choice of logging library.
Suppose, if a project is already using log4j, and you included a library say Apache Active MQ, which has dependency on logback, another logging library, then you need to include them as well, but if Apache Active MQ uses SL4J, you can continue with your logging library, without pain of adding and maintaining new logging framework.
In short, SLF4J makes your code independent of any particular logging API, which is a good thing for public API developers.
Though idea of abstracting logging library is not new and Apache commons logging is already using it, but now SLF4J is quickly becoming an standard for logging in Java world.
Let’s see couple of more reason to use SLF4J over log4j, logback or java.util.logging.
Prefer SLF4J over Log4J, logback and java.util.Logging
As I said earlier, main motivation of using SLF4J in your code to write log statements is, to make your program, independent of any particular logging library, which might require different configuration than you already have, and introduce more maintenance headache.
This not only reduce lot of String concatenation in your code, but also cost of creating String object. This is true even if you might not need that, depending upon your log level in production environment e.g. String concatenation on DEBUG and INFO levels.
Since Strings are immutable and they are created in the String pool, they consume heap memory and most of the time they are not needed e.g. a String used in the DEBUG statement is not needed when your application is running on ERROR level in production.
By using SLF4J, you can defer String creation at runtime, which means only required Strings will be created.
If you have been using log4j then you are already familiar with a workaround of putting debug statement inside if() condition, but SLF4J placeholders are much better than that.
This is how you would do in Log4j, but surely this is not fun and reduces the readability of code by adding unnecessary boiler-plate code.
if (logger.isDebugEnabled()) { logger.debug("Processing trade with id: " + id + " symbol: " + symbol); }
On the other hand, if you use SLF4J, you can get the same result in much concise format as shown below :
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
In SLF4J, we don’t need String concatenation and don’t incur the cost of temporary not need String. Instead, we write log messages in a template format with a placeholder and supply actual values as parameters.
This is a really convenient and efficient way of logging. Remember, before generating final String for logging message, this method checks if a particular log level is enabled or not, which not only reduce memory consumption but also CPU time involved for executing those String concatenation instruction in advance.
Here is the code of the SLF4J logger method from its Log4j Adapter class Log4jLoggerAdapter from slf4j-log4j12-1.6.1.jar.
public void debug(String format, Object arg1, Object arg2) { if (logger.isDebugEnabled()) { FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable()); } }
How to use SLF4J with Log4J for logging
Apart from the above benefits, I think there is one caveat though, in order to use SLF4J you not only need to include SLF4J API Jar like slf4j-api-1.6.1.jar, but also companion JAR, depending upon which logging library, you are using in the backend.
slf4j-api-1.6.1.jar – JAR for SLF4J API
log4j-1.2.16.jar – JAR for Log4J API
slf4j-log4j12-1.6.1.jar – Log4J Adapter for SLF4J
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.1</version> </dependency>
Summary
To summarize this post, I would suggest the following reasons are good enough to choose SLF4J over Log4j, commons-logging, logback or java.util.logging directly.
1) Using SLF4J in your open-source library or internal library, will make it independent of any particular logging implementation, which means no need to manage multiple logging configurations for multiple libraries, your client will going to appreciate this.
2) SLF4J provides place holder based logging, which improves readability of code by removing checks lie isDebugEnabled(), isInfoEnabled() etc.
3) By using the SLF4J logging method, you defer cost of constructing logging messages (String), until you need it, which is both memory and CPU efficient.
And, here is a nice diagram which not only summarizes the pros and cons of using SLF4j or any other logging abstraction library over Log4j
These advantages are just the tip of the iceberg, you will learn about more benefits when you start using SL4J and reading about it. I strongly suggest any new code development in Java should use SLF4J for logging over any other logging API including log4J.