Logback Change Log Level at Runtime Example (original) (raw)

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:

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

4.0.0 jcg.zheng.demo logback-changelevel-demo 0.0.1-SNAPSHOT Mary Zheng demo for logback change level

<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>

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:

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

<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>

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.

Photo of 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.