Logback

Logback Change Log Level at Runtime Example

1. Introduction

In this post, we feature a comprehensive Example on Logback Change Log Level. Logback is one of the most widely used logging frameworks in the Java community. Most applications set the logger level to INFO in the production environment, but sometimes we need more detailed logging messages to troubleshoot issues and would like to change the logger lever at runtime. In this example, I will demonstrate how to change logger level in two ways:

  1. Update the logger level with LoggerContext.
  2. Enable the scan option in the logback.xml, so it will detect and apply the change automatically.

2. Technologies Used

The example code in this article was built and run using:

  • Java 1.8.101
  • Maven 3.3.9
  • Logback 1.2.3
  • Eclipse Oxygen

3. Maven Java Application

There are many ways to create a Maven Java application. The easiest way for me is via Eclipse. Please click here for detailed steps.

3.1 Manage Dependencies

Pom.xml manages the project dependencies.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>jcg.zheng.demo</groupId>
	<artifactId>logback-changelevel-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Mary Zheng demo for logback change level</name>

	<properties>
		<maven.compiler.target>1.8</maven.compiler.target>
		<maven.compiler.source>1.8</maven.compiler.source>
	</properties>

	<dependencies>	
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-access</artifactId>
			<version>1.2.3</version>
		</dependency>

		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.2.3</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-core</artifactId>
			<version>1.2.3</version>
		</dependency>

	</dependencies>
</project>

3.2 Java Application

Create a java application to update the logger level at runtime.

ChangeLogLevelDemo.java

package jcg.zheng.demo;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

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

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;

public class ChangeLogLevelDemo {

	private final Logger lOG = LoggerFactory.getLogger(this.getClass());
	private final static List VALID_LEVELS = Arrays.asList("TRACE", "DEBUG", "INFO", "WARN", "ERROR");

	private static Scanner scanner;

	public static void main(String[] args) {
		ChangeLogLevelDemo demo = new ChangeLogLevelDemo();
		scanner = new Scanner(System.in);
		demo.step("some log message");
		String updateLogLevel = null;
		do {
			System.out.println("Enter Logback Logger Level - TRACE, DEBUG, INFO, WARN, ERROR! ");
			System.out.println("q to quit, anything else to repeat this message: ");

			updateLogLevel = scanner.nextLine();
			if (VALID_LEVELS.contains(updateLogLevel)) {
				setLogLevel(updateLogLevel, "jcg.zheng.demo");

				demo.step("log message after level change");
			}

		} while (!updateLogLevel.equalsIgnoreCase("q"));

		scanner.close();

	}

	public void step(String logmessage) {

		if (lOG.isTraceEnabled()) {
			lOG.trace("Start step for {}", logmessage);
		}

		if (lOG.isDebugEnabled()) {
			lOG.debug("Start step for {}", logmessage);
		}

		if (lOG.isInfoEnabled()) {
			lOG.info("Start step {}", logmessage);
		}

		if (lOG.isWarnEnabled()) {
			lOG.warn("Start step {}", logmessage);
		}

		if (lOG.isErrorEnabled()) {
			lOG.error("Start step {}", logmessage);
		}
	}

	private static void setLogLevel(String logLevel, String packageName) {
		LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

		ch.qos.logback.classic.Logger logger = loggerContext.getLogger(packageName);
		System.out.println(packageName + " current logger level: " + logger.getLevel());
		System.out.println(" You entered: " + logLevel);

		logger.setLevel(Level.toLevel(logLevel));
	}
}

Note:

  • Line 31: Invoke setLogLevel to change logger level
  • Line 66: Obtain LoggerContext from LoggerFactory.getILoggerFactory()
  • Line  72: update the logger level via the setLevel method

3.3 Logback Configuration

Create a logback.xml with the scan option enabled.  It automatically detects the configuration file change and applies accordingly.

logback.xml

<!-- demo the debug value difference -->
<configuration debug="true" scan="true"
	scanPeriod="10 seconds">

	<appender name="consoleAppender"
		class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<charset>UTF-8</charset>
			<Pattern>%d %-4relative [%thread] %-5level %logger{35} - %msg%n
			</Pattern>
		</encoder>
	</appender>

	<logger name="jcg.zheng.demo" level="info" additivity="false">
		<appender-ref ref="consoleAppender" />
	</logger>

	<root level="error">
		<appender-ref ref="consoleAppender" />
	</root>
</configuration>

4. Demo

In this step, I will demonstrate how to update the logger level at runtime:

  1. Start ChangeLogLevelDemo as a Java application.
  2. Enter the “ERROR” level.
  3. Watch the console outputting the messages.
  4. Repeat steps 2 and 3 for other logger levels – DEBUG, WARN, TRACE.
  5. Updatelogback.xml logger level from “INFO” to “DEBUG”.
  6. Wait 10 seconds
  7. Watch the console logging messages.

Application console Log

Console Log

16:33:27,972 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
16:33:27,972 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
16:33:27,972 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/C:/gitworkspace/logback-clevel-demo/target/classes/logback.xml]
16:33:28,088 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - Will scan for changes in [file:/C:/gitworkspace/logback-clevel-demo/target/classes/logback.xml] 
16:33:28,088 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - Setting ReconfigureOnChangeTask scanning period to 10 seconds
16:33:28,090 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
16:33:28,094 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [consoleAppender]
16:33:28,101 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
16:33:28,138 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [jcg.zheng.demo] to ERROR
16:33:28,138 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting additivity of logger [jcg.zheng.demo] to false
16:33:28,138 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [consoleAppender] to Logger[jcg.zheng.demo]
16:33:28,139 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to ERROR
16:33:28,139 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [consoleAppender] to Logger[ROOT]
16:33:28,139 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
16:33:28,140 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@2eafffde - Registering current configuration as safe fallback point
2018-08-15 16:33:28,147 209  [main] ERROR jcg.zheng.demo.ChangeLogLevelDemo - Start step some log message
Enter Logback Logger Level - TRACE, DEBUG, INFO, WARN, ERROR! 
q to quit, anything else to repeat this message: 
ERROR
jcg.zheng.demo current logger level: ERROR
 You entered: ERROR
2018-08-15 16:33:34,863 6925 [main] ERROR jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
Enter Logback Logger Level - TRACE, DEBUG, INFO, WARN, ERROR! 
q to quit, anything else to repeat this message: 
DEBUG
jcg.zheng.demo current logger level: ERROR
 You entered: DEBUG
2018-08-15 16:35:16,786 108848 [main] DEBUG jcg.zheng.demo.ChangeLogLevelDemo - Start step for log message after level change
2018-08-15 16:35:16,787 108849 [main] INFO  jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
2018-08-15 16:35:16,787 108849 [main] WARN  jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
2018-08-15 16:35:16,787 108849 [main] ERROR jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
Enter Logback Logger Level - TRACE, DEBUG, INFO, WARN, ERROR! 
q to quit, anything else to repeat this message: 
WARN
jcg.zheng.demo current logger level: DEBUG
 You entered: WARN
2018-08-15 16:35:20,597 112659 [main] WARN  jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
2018-08-15 16:35:20,597 112659 [main] ERROR jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
Enter Logback Logger Level - TRACE, DEBUG, INFO, WARN, ERROR! 
q to quit, anything else to repeat this message: 
TRACE
jcg.zheng.demo current logger level: WARN
 You entered: TRACE
2018-08-15 16:35:26,435 118497 [main] TRACE jcg.zheng.demo.ChangeLogLevelDemo - Start step for log message after level change
2018-08-15 16:35:26,435 118497 [main] DEBUG jcg.zheng.demo.ChangeLogLevelDemo - Start step for log message after level change
2018-08-15 16:35:26,435 118497 [main] INFO  jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
2018-08-15 16:35:26,435 118497 [main] WARN  jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
2018-08-15 16:35:26,436 118498 [main] ERROR jcg.zheng.demo.ChangeLogLevelDemo - Start step log message after level change
Enter Logback Logger Level - TRACE, DEBUG, INFO, WARN, ERROR! 
q to quit, anything else to repeat this message: 
ttt
Enter Logback Logger Level - TRACE, DEBUG, INFO, WARN, ERROR! 
q to quit, anything else to repeat this message: 
16:36:08,082 |-INFO in ReconfigureOnChangeTask(born:1534368808085) - Detected change in configuration files.
16:36:08,082 |-INFO in ReconfigureOnChangeTask(born:1534368808085) - Will reset and reconfigure context named [default]
16:36:08,082 |-INFO in ReconfigureOnChangeTask(born:1534368808085) - Detected change in configuration files.
16:36:08,082 |-INFO in ReconfigureOnChangeTask(born:1534368808085) - Will reset and reconfigure context named [default]
16:36:08,085 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - Will scan for changes in [file:/C:/gitworkspace/logback-clevel-demo/target/classes/logback.xml] 
16:36:08,085 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - Setting ReconfigureOnChangeTask scanning period to 10 seconds
16:36:08,086 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
16:36:08,086 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [consoleAppender]
16:36:08,086 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
16:36:08,087 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [jcg.zheng.demo] to INFO
16:36:08,087 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting additivity of logger [jcg.zheng.demo] to false
16:36:08,087 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [consoleAppender] to Logger[jcg.zheng.demo]
16:36:08,087 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to ERROR
16:36:08,087 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [consoleAppender] to Logger[ROOT]
16:36:08,087 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
16:36:08,087 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@76d42a65 - Registering current configuration as safe fallback point

5. Summary

In this article, I demonstrated how to change the logger level at runtime, one via LoggerContext, the other via the configuration file.

6. Download the Source Code

This example consists of a Java application to demonstrate how to update the Logback logger level at Runtime.

Download
You can download the full source code of this example here: Logback Change Log Level at Runtime Example

Mary Zheng

Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Steven
Steven
3 years ago

Does this work when you build a jar-file and the logback.xml is inside the jar?

Back to top button