Change Logback Log Level Programmatically at Runtime via a REST API in Spring Boot

In this tutorial, we will show you how to change Logback log level programmatically at runtime via a REST API in Spring Boot.

The required Logback dependencies for this example are Logback Core, Logback Classic, SLF4J. However, these Logback dependencies are available by default if our Spring Boot project uses spring-boot-starter-web dependency.

Follow the steps below to complete this example:

  1. Spring Boot expects the logback.xml configuration file to be placed under the resources folder of the application. The configuration in the logback.xml file should be as follows:

  2. <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
    	<property name="LOG_FILE" value="LogFile" />
    	<appender name="FILE"
    		class="ch.qos.logback.core.rolling.RollingFileAppender">
    		<file>/logs/application.log</file>
    		<rollingPolicy
    			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    			<!-- daily rollover -->
    			<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
    			<!-- keep 30 days' worth of history capped at 3GB total size -->
    			<maxHistory>30</maxHistory>
    			<totalSizeCap>3GB</totalSizeCap>
    		</rollingPolicy>
    		<triggeringPolicy
    			class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
    			<maxFileSize>5GB</maxFileSize>
    		</triggeringPolicy>
    	</appender>
    	<logger name="com.example.logback.service.transaction.impl"
    		level="debug" additivity="false">
    		<appender-ref ref="FILE" />
    	</logger>
    	<root level="info">
    		<appender-ref ref="FILE" />
    	</root>
    </configuration>

  3. Create an interface named LoggingService with a method to change the log level:

  4. package com.example.logback.service;
    
    public interface LoggingService {
       void changeLogLevel(String level, String packageName);
    }

  5. Create an implementation class named LoggingServiceImpl for the LoggingService interface:

  6. package com.example.logback.service.impl;
    
    import java.util.Arrays;
    import java.util.List;
    import org.slf4j.LoggerFactory;
    import ch.qos.logback.classic.Level;
    import ch.qos.logback.classic.LoggerContext;
    import com.example.logback.service.LoggingService;
    
    public class LoggingServiceImpl implements LoggingService {
    
       @Override
       public void changeLogLevel(String level, String packageName) throws Exception {
    	List<String> validLevels = Arrays.asList("TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF");
    	if (!validLevels.contains(level.toUpperCase())) {
    	     throw new Exception("Invalid Log level");
    	}
    	LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    
    	ch.qos.logback.classic.Logger classicLogger = loggerContext.getLogger(packageName);
    	System.out.println(packageName + " current logger level: " + classicLogger.getLevel());
    	System.out.println(" You entered: " + level);
    
    	classicLogger.setLevel(Level.toLevel(level));
       }
    
    }

  7. Create a controller with a REST API endpoint that allows changing the logging level for the application package, as shown in the example below:

  8. package com.example.logback.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.bind.annotation.PutMapping;
    import com.example.logback.service.LoggingService;
    
    @RestController
    @RequestMapping(path = "/logging")
    public class LoggingController {
    
       @Autowired
       private LoggingService loggingService;
    
       @PutMapping(path = "/change-log-level")
       public void changeLogLevel(@RequestParam(name = "level", defaultValue = "info") String level,
    			@RequestParam(name = "packageName", 
                            defaultValue = "com.example.service.impl.TransactionServiceImpl") 
                            String packageName) {
           try {
    	     loggingService.changeLogLevel(level, packageName);
           } catch (Exception e) {
    	     e.printStackTrace();
           }
       }
    }

  9. To test the API, you can run your application and make a PUT request, as shown in the example below: