# How to Programmatically Change SLF4J Log Levels at Runtime in Spring Boot

> Dynamically adjust SLF4J log levels in Spring Boot at runtime. Learn how to use the LoggingSystem to set logger levels programmatically for enhanced debugging and control.

- Repository: [Spring/spring-boot](https://github.com/spring-projects/spring-boot)
- Tags: how-to-guide
- Published: 2026-02-16

---

**You can change SLF4J log levels at runtime in Spring Boot by obtaining the active `LoggingSystem` instance and calling `setLogLevel(String loggerName, LogLevel level)` to update specific loggers or the root logger dynamically.**

Spring Boot provides a unified abstraction over popular logging frameworks like Logback and Log4J‑2, allowing you to programmatically adjust log levels without restarting your application. This capability is essential for troubleshooting production issues or enabling debug verbosity on demand.

## Understanding the LoggingSystem Abstraction

Spring Boot shields your code from the underlying logging implementation through the `org.springframework.boot.logging.LoggingSystem` interface. This abstraction lives in [`LoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/LoggingSystem.java) and declares the core operation `setLogLevel(String loggerName, LogLevel level)`, which concrete implementations override to manipulate the actual logging backend.

When your application starts, Spring Boot uses `LoggingSystem.get(ClassLoader)` to detect and instantiate the correct implementation. This method checks the `LoggingSystem.SYSTEM_PROPERTY` or delegates to `LoggingSystemFactory` implementations that scan the classpath. For example, `LogbackLoggingSystem.Factory` (found in [`LogbackLoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/LogbackLoggingSystem.java) lines 86‑92) and `Log4J2LoggingSystem.Factory` (in [`Log4J2LoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/Log4J2LoggingSystem.java) lines 22‑30) compete to provide the appropriate system based on available libraries.

## How setLogLevel Works Under the Hood

The `setLogLevel` method delegates to framework‑specific APIs that modify the logger configuration immediately. Both implementations ultimately affect the SLF4J `ILoggerFactory`, ensuring that any code using `org.slf4j.Logger` sees the updated level without requiring code changes.

### Logback Implementation

In [`LogbackLoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/LogbackLoggingSystem.java) (lines 400‑405), the `setLogLevel` method retrieves the Logback `Logger` from `LoggerContext` and calls `setLevel(ch.qos.logback.classic.Level)`:

```java
// From LogbackLoggingSystem.java
@Override
public void setLogLevel(String loggerName, LogLevel level) {
    ch.qos.logback.classic.Logger logger = getLogger(loggerName);
    logger.setLevel(translateLogLevel(level)); // Maps LogLevel to ch.qos.logback.classic.Level
}

```

### Log4J2 Implementation

In [`Log4J2LoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/Log4J2LoggingSystem.java) (lines 52‑66), the implementation updates the `LoggerConfig` within the `LoggerContext`:

```java
// From Log4J2LoggingSystem.java
@Override
public void setLogLevel(String loggerName, LogLevel level) {
    Level translatedLevel = translateLogLevel(level);
    LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    Configuration config = ctx.getConfiguration();
    LoggerConfig loggerConfig = config.getLoggerConfig(loggerName);
    loggerConfig.setLevel(translatedLevel);
    ctx.updateLoggers();
}

```

## Retrieving the Active LoggingSystem

You can obtain the `LoggingSystem` instance either statically or through dependency injection, depending on whether you are inside a Spring-managed component.

### Static Access

Use `LoggingSystem.get(ClassLoader)` when you need access outside of the Spring context or in static utility methods:

```java
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.LogLevel;

public class RuntimeLogConfigurator {
    
    public static void setDebugForPackage(String packageName) {
        LoggingSystem system = LoggingSystem.get(ClassLoader.getSystemClassLoader());
        system.setLogLevel(packageName, LogLevel.DEBUG);
    }
}

```

### Spring Bean Injection

Within a Spring Boot application, `LoggingSystem` is registered as a singleton bean. Inject it into your components for cleaner code:

```java
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.LogLevel;
import org.springframework.stereotype.Component;

@Component
public class DynamicLogManager {
    
    private final LoggingSystem loggingSystem;
    
    public DynamicLogManager(LoggingSystem loggingSystem) {
        this.loggingSystem = loggingSystem;
    }
    
    public void enableVerboseLogging(String loggerName) {
        loggingSystem.setLogLevel(loggerName, LogLevel.TRACE);
    }
    
    public void resetRootToInfo() {
        loggingSystem.setLogLevel(null, LogLevel.INFO);
    }
}

```

## Practical Code Examples

### Event-Driven Log Level Changes

You can combine the `LoggingSystem` with Spring's event infrastructure to react to external configuration changes. This example listens for a custom event to update levels dynamically:

```java
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.LogLevel;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class LogLevelChangeListener implements ApplicationListener<LogLevelChangeEvent> {
    
    private final LoggingSystem loggingSystem;
    
    public LogLevelChangeListener(LoggingSystem loggingSystem) {
        this.loggingSystem = loggingSystem;
    }
    
    @Override
    public void onApplicationEvent(LogLevelChangeEvent event) {
        loggingSystem.setLogLevel(event.getLoggerName(), event.getLevel());
    }
}

```

The custom event class:

```java
import org.springframework.boot.logging.LogLevel;
import org.springframework.context.ApplicationEvent;

public class LogLevelChangeEvent extends ApplicationEvent {
    private final String loggerName;
    private final LogLevel level;
    
    public LogLevelChangeEvent(Object source, String loggerName, LogLevel level) {
        super(source);
        this.loggerName = loggerName;
        this.level = level;
    }
    
    public String getLoggerName() { return loggerName; }
    public LogLevel getLevel() { return level; }
}

```

## Summary

- **Spring Boot's `LoggingSystem`** provides a framework-agnostic API to programmatically change SLF4J log levels at runtime without restarting the application.
- **Concrete implementations** in [`LogbackLoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/LogbackLoggingSystem.java) (lines 400‑405) and [`Log4J2LoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/Log4J2LoggingSystem.java) (lines 52‑66) translate `LogLevel` enums to framework-specific level objects.
- **Access patterns** include static retrieval via `LoggingSystem.get(ClassLoader)` or dependency injection as a Spring bean.
- **Pass `null`** as the logger name to `setLogLevel` to adjust the root logger level.

## Frequently Asked Questions

### How do I reset a logger to its default level using LoggingSystem?

The `LoggingSystem` API does not provide a direct "reset to default" method. To restore the initial configuration, you must know the original level and call `setLogLevel` again with that value. Alternatively, you can reinitialize the logging system entirely, though this is rarely recommended in production as it may cause temporary logging disruption.

### Can I use this approach with Java Util Logging (JUL) instead of Logback or Log4J2?

Yes, Spring Boot includes a `JavaLoggingSystem` implementation that delegates to `java.util.logging`. When `java.util.logging` is detected as the primary logging framework, `LoggingSystem.get()` returns this implementation, and `setLogLevel` updates the underlying `java.util.logging.Logger` instances accordingly.

### What happens if I call setLogLevel with an invalid logger name?

If you provide a logger name that does not exist, the underlying logging framework typically creates a placeholder logger with that name and assigns the specified level. This logger will then capture log events if code later obtains a logger with the same name. Passing `null` specifically targets the root logger in all implementations.

### Is it safe to change log levels frequently in a high-throughput production application?

Yes, the `setLogLevel` operation is lightweight and thread-safe in both Logback and Log4J2 implementations. The operation updates an atomic reference or volatile field internally, so frequent changes (e.g., triggered by monitoring alerts) do not significantly impact application performance. However, excessive logging at `TRACE` or `DEBUG` levels can cause I/O bottlenecks, so levels should be managed judiciously.