Overview
Slf4j to logging is what JDBC is to Database access: an interface that streamlines logging api, plugs into several implementations at deploy time, and promotes best practices of logging.
When should you use slf4j?
If you believe coding for Interfaces works well in your project(s), then you need no explanation. Though slf4j is “not necessary” in a standalone application, it’s recommended: what if, after developing several apps, you discover a new logging implementation? Would you rather plug-in a new implementation or rewrite logging for all your apps?
Features
1. Abstraction layer
slf4j’s api provides generic access to many logging frameworks, including advanced features like MDC, along with boilerplate code, allowing existing code to be used easily. Which one you use, is then decided at deployment time, not when you write your code.
2. Plug in logging framework at deployment time
SLF4J statically binds to a particular logging implementation so that there is no automatic discovery for configuration. This gets around the class loading issues with JCL, providing a fail-fast operation and the framework binding will be verified automatically very early on. SLF4J will abort execution with a warning if no binding is present.
3. Parametrized logging
Write
log.debug("hello world {}", a, b);
instead of:
if(log.isDebugEnabled()){
log.debug("hello " + a + " world" + b);
}
The former code has the same performance if you do not log in debug mode. Note there’s no need of string concatenation and the {}-placeholders delay the actual creation of the full string to be logged as much as possible, notably after the event has been determined to need to be logged.
4. Support legacy logging
For existing projects using legacy logging frameworks, SLF4J bridging removes their dependencies from the project and routes the calls to use SLF4J, effectively swapping the implementation to a new logging library with minimal code changes. Also, a migrator tool utility can help you migrate your source to use SLF4J.
5. Marker Interface for slicing, dicing and filtering specialized events
To expand logging categories beyond info, warn, error, and provide an event-like capability to mark and fire off a message (“business-process”, “fatal”) to notify the logger to respond specifically to such messages. You can even, for instance, process marker messages to hook up an email notification workflow.
Read this for some of the best practices on using Markers.
Note that currently only logback supports the Marker interfaces.
6. Profiler
Slf4j extensions like Profiler can add timer operations around method invocations.
7. Others
- A powerful Logger interface
- A useful Extended Logger forlogging method entry, exit, etc
- As a service provider, limit the use of transitive dependencies
For further info read the excellent FAQ on slf4j.
Usage
Maven:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
To exclude commons-logging as a Maven dependency: Declare version 99-empty of commons-logging in the dependencyManagement section of your project will direct all transitive dependencies for commons-logging to import version 99-empty (a bogus jar), thus nicely addressing the commons-logging exclusion problem. The classes for commons-logging will be provided by jcl-over-slf4j.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>99-empty</version>
</dependency>
... other declarations...
</dependencies>
</dependencyManagement>
<!-- Do not forget to declare a dependency on jcl-over-slf4j in the -->
<!-- dependencies section. Note that the dependency on commons-logging -->
<!-- will be imported transitively. You don't have to declare it yourself. -->
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.6.6</version>
</dependency>
... other dependency declarations
</dependencies>
Sample Logging:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Foo {
// Avoid static references to log objects from code that might be deployed in a shared classpath.
// Declaring a logger as static prevents the declaring class (and associated classloaders) from being garbage
// collected in J2EE containers that use a shared classloader. This will result in PermGen errors
// if you redeploy your application enough times.
// http://wiki.apache.org/commons/Logging/StaticLog
// Also, the argument that instance log objects are "expensive" is no longer valid in modern JVMs unless
// tens of thousands of classes are created.
// http://www.slf4j.org/faq.html#declared_static
private final Logger log = LoggerFactory.getLogger(Foo.class);
public void simpleProcessWithExceptions(Bar bar) {
log.info("Starting Process ... ");
preProcessBar(bar);
// Use log statements to describe your processing states generously. Unless you have a BigData
// based persistence to audit behavior, log files are your best friend
log.debug("After pre-processing Bar: {}, bar);
try {
log.info("Pre processing bar");
doSomething();
callDatabaseMethod();
}
catch (SomeCheckedException e) {
// Slf4j automatically converts e into a readable stacktrace
log.error("An error occured in {}", e));
throw new WrappedRuntimeException(e);
}
postProcessBar(bar);
log.debug("After post-processing Bar: {}, bar);
log.info("Finished Process ... ");
}
public static void youShouldntHaveAStaticMethod(Bar bar) {
// Creating a new log within the static method is an appropriate solution
Log log = LoggerFactory.getLogger(Foo.class);
log.warn(...);
}
}
Who uses slf4j?
All projects in Spring, JBoss, Apache, Mule, and many open-source libraries have already migrated to slf4j, establishing it as the defacto logging api standard.
What is the best implementation for slf4j?
Logback. There are several reasons to switch from log4j to Logback.
References
1. A video Presentation
2. Logger Javadoc
Post a Comment