Logback – different log file for each thread

logback-different-log-for-each-thread

In this tutorial, we will show you how to use Logback Mapped Diagnostic Context (MDC) and SiftingAppender to create a separate log file for each thread.

P.S Tested with Logback 1.1.2, should work in earlier version.

Note
More info, refer to this Logback MDC documentation

1. logback.xml example

A logback.xml file to show you how to declare and configure SiftingAppender and MDC.

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<property name="USER_HOME" value="C:\\logs\\analyzer" />

	<appender name="FILE-THREAD" class="ch.qos.logback.classic.sift.SiftingAppender">

		<!-- This is MDC value -->
		<!-- We will assign a value to 'logFileName' via Java code -->
		<discriminator>
			<key>logFileName</key>
			<defaultValue>head0</defaultValue>
		</discriminator>

		<sift>

		  <!-- A standard RollingFileAppender, the log file is based on 'logFileName' at runtime  -->
		  <appender name="FILE-${logFileName}"
			class="ch.qos.logback.core.rolling.RollingFileAppender">
			<file>${USER_HOME}/${logFileName}.log</file>

			<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
				<Pattern>
					%d{yyyy-MM-dd HH:mm:ss} %mdc [%thread] %level %logger{35} - %msg%n
				</Pattern>
			</encoder>

			<rollingPolicy
				class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
				<FileNamePattern>${USER_HOME}/${logFileName}.%i.log.zip
				</FileNamePattern>
				<MinIndex>1</MinIndex>
				<MaxIndex>10</MaxIndex>
			</rollingPolicy>

			<triggeringPolicy
				class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
				<MaxFileSize>10MB</MaxFileSize>
			</triggeringPolicy>

		  </appender>

		</sift>
	</appender>

	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<layout class="ch.qos.logback.classic.PatternLayout">
			<Pattern>
				%-5level %logger{36} - %msg%n
			</Pattern>
		</layout>
	</appender>

	<logger name="com.mkyong.analyzer.core" level="debug"
		additivity="false">
		<appender-ref ref="FILE-THREAD" />
		<appender-ref ref="STDOUT" />
	</logger>

	<root level="error">
		<appender-ref ref="STDOUT" />
	</root>

</configuration>

2. Java Threads Example

A simple thread example, declared the ‘logFileName’ value via MDC.put

Head.java

package com.mkyong.analyzer.core;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class Head implements Runnable {

	static Logger logger = LoggerFactory.getLogger(Head.class);

	private String name;
	
	@Override
	public void run() {

		MDC.put('logFileName', getName());

		logger.debug("hello");

		//remember remove this
		MDC.remove('logFileName');

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

Start 10 threads


	int count = 1;
	while(count<=10){
		Head head = new Head();
		head.setName("head-" + count);
		threadPools.execute(head);
		count++;
	}

Output : 10 separate log files for 10 threads.

logback-different-log-for-each-thread
Note
With this MDC feature, you can even log output to a separate log file for each login user, each URI request, each remote host and etc.

References

  1. Logback MDC documentation

19 comments on “Logback – different log file for each thread

  1. Hi , Can you please tell me if I have multiple modules – module A and Module B in a project and inside module A- src/main/resources I have logback.xml file. How can I use this logback.xml for Module B? I have tried adding dependency of Module A into module B pom. It didn’t worked and giving me – “Logging system failed to initialize configuration from null”. I request to kindly help me

  2. Works beautifully. I had unit tests that needed separate logging to files for assertions. This solved it – thank you.

    Just a bit confused that your examples sometimes delimit strings with single quotes – eg: MDC.put(‘logFileName’, getName());

    Surely this would never compile?

  3. Hey Mykong thanks for that implementation example… It really works and as you said the below one is very important:
    //remember remove this
    MDC.remove(‘logFileName’);

  4. Dear Friend,

    is it possible to add multiple descriminator and use to separate the files. Use case is, based on the client, need to put log file into separate folder.

Leave a Comment

Your email address will not be published. Required fields are marked *