jderieck
jderieck

Reputation: 61

slf4j / logback - different loglevel for certain threads

I recently changed our application from log4j to logback / slf4j. Everything is working very nice, however I want to implement something specific.

The application I'm working on is a web application. In our production environment the log-level is on INFO. From time to time tickets come in for our service team to handle. It would be nice that, when our service team is reproducing the tickets, they can put the log-level on TRACE for just their test-request. This way the log files are not poluted with all other requests coming in at that time.

We already use the header "X-TracingContext-Active=true" to write certain extra data to the logging. My idea was to increase the loglevel to TRACE when the header is 'true' for just that request (thread).

Is there a way to do this without the need to create my own logging implementation or having to write this logic in each class?

EDIT: The X-TracingActive-Context header is now captured at the beginning of each request. This value is stored in a helper class in a ThreadLocal variable. I was thinking to override the isInfoEnabled, isDebugEnabled,... methods so it first reads the variable from the helper class. But I have no idea how I can override this method without implementing my own log framework. The Logger class of logback is final.

Any ideas?

Upvotes: 5

Views: 1431

Answers (2)

jderieck
jderieck

Reputation: 61

The reply of doublep got me thinking. I already tried the Filter mechanism of logback but that was not sufficient. Apperently there are 2 types of filters in logback: Filter & TurboFilter. The last one was the solution to my problem.

In the logback.xml I configured a TurboFilter:

<!-- Turbo Filters -->
<turboFilter class="com.company.application.core.util.LoggingTurboFilter" />

LoggingTurboFilter class:

import org.slf4j.Marker;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.spi.FilterReply;

public class LoggingTurboFilter extends TurboFilter {

    @Override
    public FilterReply decide(Marker marker, Logger logger, Level level,
            String format, Object[] params, Throwable t) {

        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }

        if(CurrentLogLevelProvider.getTraceActive()){
            return FilterReply.ACCEPT;
        } else {
            return FilterReply.NEUTRAL;
        }
    }

    @Override
    public void start() {
        super.start();
    }
}

Now I can override per request the log level.

Upvotes: 1

user319799
user319799

Reputation:

While not quite what you want (and not trivial to implement), you could set level to TRACE for everything and filter out "wrong" threads. Performance can/will be quite awful though, but if you bump log level only for the duration of these special requests and reset it back afterwards, it shouldn't be that bad.

Upvotes: 1

Related Questions