[logback-user] Implementing MDC with ServerSocketReceiver

Joaquim Jose joaquimjosedasilva at gmail.com
Tue Jul 30 17:47:16 CEST 2019


Hi,

I'm trying to implement a TCP server which logs to different appenders
depending on the message content. I'm using ServerSocketReceiver and
SiftingAppender strategy based on MDC value.

Here's my snippet:

siftingAppender.setAppenderFactory((Context context1, String
discriminatingValue) -> {

    Appender appender;
    if (DISCRIMINATOR_DEFAULT_VALUE.equals(discriminatingValue)) {
        ConsoleAppender<ILoggingEvent> consoleAppender = new
ConsoleAppender<>();
        consoleAppender.setContext(context);
        consoleAppender.setEncoder(consoleOnlyEncoder(context));
        consoleAppender.setName("MY_CONSOLE_APPENDER");
        consoleAppender.start();
        appender = consoleAppender;
    } else {
        RollingFileAppender rollingFileAppender =
rollingFileAppender("MY_ROLLING_APPENDER",
                "myPrefix." + discriminatingValue + ".%d{yyyy-MM-dd_HH-mm}.log",
                context);

        AsyncAppender asyncAppender =
asyncAppender(rollingFileAppender, context);

        appender = asyncAppender;
    }

    return appender;
});



Let's say that my MDC discriminator key is "filename". My first challenge
with this approach is that the MDC value is not serialized and sent to
server. So, I changed the message format to "filename={},msg{}" and I
created a Turbo Filter, which would check if the rawMessage is equal to
this expression and, if so, It would log using the MDC discriminator.
Here's the snippet:

private static void addMDCInterceptorTurboFilter(LoggerContext context) {
    String regex =
DISCRIMINATOR_KEY.concat("={},").concat(MESSAGE_KEY).concat("={}"); //
"filename={},msg={}"

    TurboFilter mdcInterceptorFilter = new TurboFilter() {
        @Override
        public FilterReply decide(Marker marker,
ch.qos.logback.classic.Logger logger, Level level,
                                  String rawMessage, Object[] params,
Throwable t) {

            if (params != null && regex.equals(rawMessage)) {
                MDC.put(DISCRIMINATOR_KEY, (String) params[0]);
                logger.log(marker, this.getClass().getName(),
Level.toLocationAwareLoggerInteger(level),
                        (String) params[1], null, null);
                MDC.remove(DISCRIMINATOR_KEY);

                return FilterReply.DENY;
            }

            return FilterReply.NEUTRAL;
        }
    };
    context.addTurboFilter(mdcInterceptorFilter);
    mdcInterceptorFilter.setName("MY_MDC_INTERCEPTOR_FILTER");
    mdcInterceptorFilter.start();
}


My challenge in the above approach is that neither the *rawMessage* nor
*params* are populated at this time. So I can't set the MDC properly.
Another approach that I tried was to set the filter to the SiftingAppender and
set the MDC there, but it didn't work either. Here's the snippet:

private Filter<ILoggingEvent> addMDCInterceptorFilter(String
keyDiscriminator, String messageKey) {
    String regex =
keyDiscriminator.concat("={},").concat(messageKey).concat("={}");
    Filter<ILoggingEvent> filter = new Filter<ILoggingEvent>() {
        @Override
        public FilterReply decide(ILoggingEvent event) {
            if (regex.equals(event.getMessage())) {
                MDC.put(keyDiscriminator, (String)event.getArgumentArray()[0]);
            } else {
                MDC.remove(keyDiscriminator);
            }

            return FilterReply.NEUTRAL;
        }
    };
    filter.start();
    return filter;
}


Could you guys guide me how to accomplish this scenario ? Please find the
full source for sake of completeness.

Thanks,

import ch.qos.logback.classic.AsyncAppender;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.net.server.ServerSocketReceiver;
import ch.qos.logback.classic.sift.MDCBasedDiscriminator;
import ch.qos.logback.classic.sift.SiftingAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.RollingPolicy;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import ch.qos.logback.core.spi.FilterReply;
import ch.qos.logback.core.util.StatusPrinter;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.slf4j.Marker;

import java.nio.charset.Charset;

public class MySocketServer {

    private static final String DISCRIMINATOR_KEY = "filename";
    private static final String DISCRIMINATOR_DEFAULT_VALUE = "unknown";
    private static final String MESSAGE_KEY = "msg";

    public static void main(String[] args) throws InterruptedException {
        LoggerContext context = (LoggerContext)
LoggerFactory.getILoggerFactory();
        StatusPrinter.print(context);

        addMDCInterceptorTurboFilter(context);

        newServerSocketReceiver(context);
        addAppenders(context);

        Thread.sleep(Long.MAX_VALUE);
    }

    private static void newServerSocketReceiver(LoggerContext context) {
        ServerSocketReceiver serverSocketReceiver = new ServerSocketReceiver();
        serverSocketReceiver.setContext(context);
        serverSocketReceiver.setPort(6000);
        serverSocketReceiver.setAddress("localhost");
        serverSocketReceiver.start();
    }

    private static void addAppenders(LoggerContext context) {
        SiftingAppender siftingAppender = siftingAppender(context);

        ch.qos.logback.classic.Logger logger =
context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
        logger.detachAndStopAllAppenders();
        logger.addAppender(siftingAppender);
    }

    private static SiftingAppender siftingAppender(LoggerContext context) {
        SiftingAppender siftingAppender = new SiftingAppender();
        siftingAppender.setContext(context);
        siftingAppender.setName("MY_SIFT_APPENDER");
        siftingAppender.setDiscriminator(getMdcBasedDiscriminator(context));

        siftingAppender.setAppenderFactory((Context context1, String
discriminatingValue) -> {

            Appender appender;
            if (DISCRIMINATOR_DEFAULT_VALUE.equals(discriminatingValue)) {
                ConsoleAppender<ILoggingEvent> consoleAppender = new
ConsoleAppender<>();
                consoleAppender.setContext(context);
                consoleAppender.setEncoder(consoleOnlyEncoder(context));
                consoleAppender.setName("MY_CONSOLE_APPENDER");
                consoleAppender.start();
                appender = consoleAppender;
            } else {
                RollingFileAppender rollingFileAppender =
rollingFileAppender("MY_ROLLING_APPENDER",
                        "myPrefix." + discriminatingValue +
".%d{yyyy-MM-dd_HH-mm}.log",
                        context);

                AsyncAppender asyncAppender =
asyncAppender(rollingFileAppender, context);

                appender = asyncAppender;
            }

            return appender;
        });

        siftingAppender.start();
        return siftingAppender;
    }

    private static AsyncAppender asyncAppender(Appender appender,
LoggerContext context) {
        AsyncAppender asyncAppender = new AsyncAppender();
        asyncAppender.setContext(context);
        asyncAppender.setName("MY_ASYNC_BACKUP_APPENDER");
        asyncAppender.setQueueSize(512);
        asyncAppender.addAppender(appender);
        asyncAppender.start();
        return asyncAppender;
    }

    private static MDCBasedDiscriminator
getMdcBasedDiscriminator(LoggerContext context) {
        MDCBasedDiscriminator discriminator = new MDCBasedDiscriminator();
        discriminator.setContext(context);
        discriminator.setKey(DISCRIMINATOR_KEY);
        discriminator.setDefaultValue(DISCRIMINATOR_DEFAULT_VALUE);
        discriminator.start();
        return discriminator;
    }

    private static RollingFileAppender rollingFileAppender(String name,
                                                    String fileNamePattern,
                                                    LoggerContext context) {
        RollingFileAppender rollingFileAppender = new RollingFileAppender();
        rollingFileAppender.setContext(context);
        rollingFileAppender.setRollingPolicy(timeBasedRollingPolicy(rollingFileAppender,
fileNamePattern, context));
        rollingFileAppender.setEncoder(messageOnlyEncoder(context));
        rollingFileAppender.setName(name);
        rollingFileAppender.start();
        return rollingFileAppender;
    }

    private static RollingPolicy
timeBasedRollingPolicy(RollingFileAppender rollingFileAppender,
                                                 String fileNamePattern,
                                                 LoggerContext context) {
        final TimeBasedRollingPolicy timeBasedRollingPolicy = new
TimeBasedRollingPolicy();
        timeBasedRollingPolicy.setContext(context);
        timeBasedRollingPolicy.setFileNamePattern(fileNamePattern);
        timeBasedRollingPolicy.setParent(rollingFileAppender);
        timeBasedRollingPolicy.start();
        return timeBasedRollingPolicy;
    }

    private static Encoder messageOnlyEncoder(LoggerContext context) {
        final PatternLayoutEncoder patternLayoutEncoder = new
PatternLayoutEncoder();
        patternLayoutEncoder.setPattern("%mdc %msg%n");
        patternLayoutEncoder.setCharset(Charset.forName("utf-8"));
        patternLayoutEncoder.setContext(context);
        patternLayoutEncoder.start();
        return patternLayoutEncoder;
    }

    private static Encoder consoleOnlyEncoder(LoggerContext context) {
        final PatternLayoutEncoder patternLayoutEncoder = new
PatternLayoutEncoder();
        patternLayoutEncoder.setPattern("%-4relative [%thread]
%-5level %logger{35} - %msg %n");
        patternLayoutEncoder.setCharset(Charset.forName("utf-8"));
        patternLayoutEncoder.setContext(context);
        patternLayoutEncoder.start();
        return patternLayoutEncoder;
    }

    private static void addMDCInterceptorTurboFilter(LoggerContext context) {
        String regex =
DISCRIMINATOR_KEY.concat("={},").concat(MESSAGE_KEY).concat("={}"); //
"filename={},msg={}"

        TurboFilter mdcInterceptorFilter = new TurboFilter() {
            @Override
            public FilterReply decide(Marker marker,
ch.qos.logback.classic.Logger logger, Level level,
                                      String rawMessage, Object[]
params, Throwable t) {

                if (params != null && regex.equals(rawMessage)) {
                    MDC.put(DISCRIMINATOR_KEY, (String) params[0]);
                    logger.log(marker, this.getClass().getName(),
Level.toLocationAwareLoggerInteger(level),
                            (String) params[1], null, null);
                    MDC.remove(DISCRIMINATOR_KEY);

                    return FilterReply.DENY;
                }

                return FilterReply.NEUTRAL;
            }
        };
        context.addTurboFilter(mdcInterceptorFilter);
        mdcInterceptorFilter.setName("MY_MDC_INTERCEPTOR_FILTER");
        mdcInterceptorFilter.start();
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.qos.ch/pipermail/logback-user/attachments/20190730/dd5d8376/attachment-0001.html>


More information about the logback-user mailing list