Jumat, 08 Agustus 2014

Why use SLF4J over Log4J for logging in Java




Every Java programmers knows that logging is critical for any Java
application, especially server side application, and many of them are already
familiar with various logging libraries e.g.
java.util.logging, Apache
log4j,
logback, but if you don't know about SLF4J, Simple logging facade for Java, 
then it's time to learn and use SLF4J in your project. In this Java article, we
will learn why using SLF4J is better than using
log4j or java.util.logging. It’s been
long time, since I wrote 10
logging tips for Java programmer
,I don’t remember anything I have writing about
logging. Anyway, let’s get back to 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 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 make your code independent of any particular
logging API, which is good think 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




Prefer SL4j over Log4j in Java 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. But apart from that, there is one more
feature of SLF4J API, which convinced me to use SL4J over my long time favorite
Log4j, that is know as place holder and represented as
{} in code.
Placeholder is pretty much same as
%s in format()
method of String
, because it get substituted  by actual string supplied at runtime. 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 String pool, they consume heap
memory
and most of the time they are not needed e.g. an String used in
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
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 reduce
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 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 cost of
temporary not need String. Instead, we write log message in a template format
with placeholder and supply actual value as parameters. You might be thinking
about what if I have multiple parameters, well you can either use variable
arguments version of log methods or pass them as Object array. This is really
convenient and efficient way of logging. Remember, before generating final
String for logging message, this method check 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 SLF4J logger
method from it's 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());
}
}







It's also worth knowing that logging has severe impact on performance
of application, and it's always advised to only mandatory logging in production
environment.





How to use SLF4J with Log4J for logging



Apart from above benefits, I think there is one caveat though, in order
to use
SLF4J you not only need to include SLF4J API Jar
e.g.
slf4j-api-1.6.1.jar, but also companion JAR, depending upon which
logging library, you are using in backend. Suppose If you want to use SLF4J, Simple Logging Facade for Java,  along with Lo4J, you need to
include following jars in your classpath,
depending upon which version of SLF4J and log4J you are using e.g.





 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





If you are using Maven
to mange dependency in your project, you can just include SLF4J JAR, and maven
will include it's dependent companion JAR. In order to use Log4J along with
SLF4J, you can include following dependency in your project's
pom.xml




<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>








By the way, if you are interested in using variable
argument version
of logger methods, than include SLF4J 1.7 version.





Summary



To summarize this post, I would suggest 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 configuration 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 SLF4J logging method, you defer cost of constructing logging
messages (String), until you need it, which is both memory and CPU efficient.





4) As a side note, less number of temporary strings means less work for Garbage
Collector
, which means better throughput and performance for your
application.





These advantages are just tip of 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.





























Source:http://javarevisited.blogspot.com/2013/08/why-use-sl4j-over-log4j-for-logging-in.html

Tidak ada komentar:

Posting Komentar