Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically setup slf4j logger with SLF4JBridgeHandler

I'm trying to setup slf4j to intercept all logging statements and then programmatically add the handlers based on certain conditions. My code is:

private void init()
{
    SLF4JBridgeHandler.removeHandlersForRootLogger();
    SLF4JBridgeHandler.install();

    if(condition1)
        appendHandler(console, Level.DEBUG);
    if(condition2)
        appendHandler(logfile1, Level.INFO);
    ...
}

How do I write the code for appendHandler method? I've just spent a few hours trying to read through documentation and cannot find a solution. There are lots of references on how to do it in configuration files but not in code.

Also am I correct in that this code intercepts all logging statements for all the different logging frameworks?

like image 749
Stephane Grenier Avatar asked Mar 20 '17 19:03

Stephane Grenier


People also ask

Which Logger is used by SLF4J?

SLF4J supports popular logging frameworks, namely log4j, java. util. logging, Simple logging and NOP. The logback project supports SLF4J natively.

Can we use Log4j2 with SLF4J?

If you used Log4j2 with SLF4J, the only thing you need is replacing Log4j2 JAR files (or maven dependencies) by JDK logger Binding. You do not want to touch any source files in order to replace your logger.

Can we use SLF4J instead of log4j?

Unlike log4j, SLF4J (Simple Logging Facade for Java) is not an implementation of logging framework, it is an abstraction for all those logging frameworks in Java similar to log4J. Therefore, you cannot compare both. However, it is always difficult to prefer one between the two.

What is SLF4J default logger?

The SLF4J or the Simple Logging Facade for Java is an abstraction layer for various Java logging frameworks, like Log4j 2 or Logback. This allows for plugging different logging frameworks at deployment time without the need for code changes.


1 Answers

Also am I correct in that this code intercepts all logging statements for all the different logging frameworks?

SLF4JBridgeHandler is a java.util.logging (JUL) logging bridge, which will "intercept" the JUL logging statements and route them to the SLF4J.

Other bridges available are jcl-over-slf4j (Jakarta Commons Logging => SL4J) and log4j-over-slf4j (Log4J => SL4J) (as well as their SLF4J => X counterparts).

Depending on which logging frameworks are used in your code (either directly or indirectly), you may want to include some or all of these, to capture all the logging statements, as detailed here.

SL4J legacy bridges

How do I write the code for appendHandler method?

Using SLF4J (e.g. Logback) as your primary logging framework

Once you have setup your bridges, you can then configure your SLF4J implementation in a usual way.

Below is an example of how to do this for Logback:

//Install the JUL Bridge
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();

//Obtain an instance of LoggerContext
LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory();

//Create a new FileAppender
FileAppender<ILoggingEvent> file = new FileAppender<ILoggingEvent>();
file.setName("FileLogger");
file.setFile("error.log");
file.setContext(context);
file.setAppend(true);

//Filter out anything < WARN
ThresholdFilter warningFilter = new ThresholdFilter();
warningFilter.setLevel("WARN");
warningFilter.setContext(context);
warningFilter.start();
file.addFilter(warningFilter);

//Message Encoder
PatternLayoutEncoder ple = new PatternLayoutEncoder();
ple.setContext(context);
ple.setPattern("%date %level [%thread] %logger{10} %msg%n");
ple.start();
file.setEncoder(ple);

file.start();

//Get ROOT logger, and add appender to it
Logger root = context.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.DEBUG);
root.addAppender(file);

Using JUL as the primary logging framework

If what you want is to use JUL (java.util.logging) as your primary logging framework, you do not need to register the SLF4JBridgeHandler at all.

Just configure JUL handlers as usual, and add the slf4j-jdk14 (i.e. SLF4J => JUL) bridge to your list of dependencies.

//Create a new Handler
Handler fh = new FileHandler("error.log");
fh.setLevel(Level.WARNING);

//Register it with the ROOT logger
Logger.getLogger("").addHandler(fh);

//Log some messages
Logger.getLogger("scratchpad").info("Info !");
Logger.getLogger("scratchpad").warning("Warning !");
Logger.getLogger("scratchpad").severe("Severe !");

//Log some messages via SL4J 
LoggerFactory.getLogger("scratchpad").error("sl4j message");

This way any SL4J log statements will be redirected to the appropriate JUL handlers (you may also want to add jcl-over-slf4j and log4j-over-sl4j in the mix too).

like image 100
zeppelin Avatar answered Sep 24 '22 08:09

zeppelin