or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/maven-org-apache-logging-log4j--log4j-to-slf4j

Log4j API to SLF4J adapter that bridges Log4j API calls to SLF4J implementations

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.apache.logging.log4j/log4j-to-slf4j@2.25.x

To install, run

npx @tessl/cli install tessl/maven-org-apache-logging-log4j--log4j-to-slf4j@2.25.0

index.mddocs/

Log4j to SLF4J Adapter

A bridge/adapter library that forwards Log4j API calls to SLF4J implementations, enabling applications using the Log4j API to redirect their logging output through SLF4J while maintaining all Log4j API functionality and features.

Package Information

  • Package Name: log4j-to-slf4j
  • Group ID: org.apache.logging.log4j
  • Language: Java
  • Installation: Add Maven dependency:
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-to-slf4j</artifactId>
    <version>2.25.1</version>
</dependency>

Core Imports

Standard Log4j API imports work transparently:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;

Basic Usage

The adapter works transparently - use standard Log4j API calls:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class Example {
    private static final Logger logger = LogManager.getLogger(Example.class);
    
    public void demonstrateLogging() {
        // Standard Log4j logging - automatically forwards to SLF4J
        logger.info("This is an info message");
        logger.error("Error occurred", new RuntimeException("test"));
        
        // Thread context (MDC) support
        ThreadContext.put("userId", "12345");
        logger.info("User action performed");
        ThreadContext.clear();
        
        // Fluent logging API
        logger.atInfo()
              .withMarker(MarkerManager.getMarker("AUDIT"))
              .log("Audit event: {}", "user_login");
    }
}

Architecture

This library implements the Log4j Provider SPI to transparently bridge Log4j API calls to SLF4J:

  • Provider Registration: Automatically discovered via Java ServiceLoader mechanism
  • Logger Context: Creates SLF4J-backed loggers that implement Log4j's ExtendedLogger interface
  • Level Mapping: Translates Log4j levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL) to SLF4J levels
  • Marker Translation: Converts Log4j Markers to SLF4J Markers with hierarchy preservation
  • Thread Context Bridge: Maps Log4j ThreadContext operations to SLF4J MDC
  • Location-Aware Logging: Leverages SLF4J LocationAwareLogger when available for better performance

Capabilities

Provider Integration

Core provider that registers with Log4j's logging system to intercept and forward API calls.

public class SLF4JProvider extends org.apache.logging.log4j.spi.Provider {
    public SLF4JProvider();
    public LoggerContextFactory getLoggerContextFactory();
    public ThreadContextMap getThreadContextMapInstance();
}

The provider is automatically discovered and has priority 15, allowing higher-priority providers to override it.

Logger Context Factory

Factory responsible for creating and managing the SLF4J logger context.

public class SLF4JLoggerContextFactory implements LoggerContextFactory {
    public SLF4JLoggerContextFactory();
    public LoggerContext getContext(String fqcn, ClassLoader loader, Object externalContext, boolean currentContext);
    public LoggerContext getContext(String fqcn, ClassLoader loader, Object externalContext, boolean currentContext, URI configLocation, String name);
    public void removeContext(LoggerContext context);
    public boolean isClassLoaderDependent();
}

The factory validates configuration to prevent conflicts with slf4j-impl jars and returns a singleton context.

Logger Context

Context that creates and manages SLF4J-backed logger instances.

public class SLF4JLoggerContext implements LoggerContext {
    public Object getExternalContext();
    public ExtendedLogger getLogger(String name);
    public ExtendedLogger getLogger(String name, MessageFactory messageFactory);
    public boolean hasLogger(String name);
    public boolean hasLogger(String name, MessageFactory messageFactory);
    public boolean hasLogger(String name, Class<? extends MessageFactory> messageFactoryClass);
}

SLF4J Logger Implementation

Main logger implementation that forwards Log4j API calls to underlying SLF4J loggers.

public class SLF4JLogger extends AbstractLogger {
    public static final long serialVersionUID = 1L;
    
    public SLF4JLogger(String name, MessageFactory messageFactory, org.slf4j.Logger logger);
    public SLF4JLogger(String name, org.slf4j.Logger logger);
    
    // Level management
    public Level getLevel();
    public org.slf4j.Logger getLogger();
    
    // Level checking methods
    public boolean isEnabled(Level level, Marker marker, Message data, Throwable t);
    public boolean isEnabled(Level level, Marker marker, CharSequence data, Throwable t);
    public boolean isEnabled(Level level, Marker marker, Object data, Throwable t);
    public boolean isEnabled(Level level, Marker marker, String data);
    public boolean isEnabled(Level level, Marker marker, String data, Object... p1);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8);
    public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9);
    public boolean isEnabled(Level level, Marker marker, String data, Throwable t);
    
    // Core logging method
    public void logMessage(String fqcn, Level level, Marker marker, Message message, Throwable t);
    
    // Fluent API builders
    public LogBuilder always();
    public LogBuilder atTrace();
    public LogBuilder atDebug();
    public LogBuilder atInfo();
    public LogBuilder atWarn();
    public LogBuilder atError();
    public LogBuilder atFatal();
    public LogBuilder atLevel(Level level);
}

Fluent Log Builder

Builder pattern implementation for constructing log statements fluently.

public class SLF4JLogBuilder implements LogBuilder {
    public SLF4JLogBuilder(SLF4JLogger logger, Level level);
    public SLF4JLogBuilder();
    
    // Builder configuration
    public LogBuilder reset(SLF4JLogger logger, Level level);
    public LogBuilder withMarker(Marker marker);
    public LogBuilder withThrowable(Throwable throwable);
    
    // State management
    public boolean isInUse();
    
    // Location methods (ignored as SLF4J doesn't support explicit location)
    public LogBuilder withLocation();
    public LogBuilder withLocation(StackTraceElement location);
    
    // Logging methods (various overloads for different message types)
    public void log();
    public void log(Message message);
    public void log(CharSequence message);
    public void log(Object message);
    public void log(String message);
    public void log(String message, Object... params);
    public void log(String message, Supplier<?>... params);
    public void log(String message, Object p0);
    public void log(String message, Object p0, Object p1);
    public void log(String message, Object p0, Object p1, Object p2);
    public void log(String message, Object p0, Object p1, Object p2, Object p3);
    public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4);
    public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5);
    public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6);
    public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7);
    public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8);
    public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9);
    public void log(Supplier<Message> messageSupplier);
    public Message logAndGet(Supplier<Message> messageSupplier);
}

Thread Context Map (MDC Bridge)

Implementation that bridges Log4j ThreadContext operations to SLF4J MDC.

public class MDCContextMap implements CleanableThreadContextMap {
    // Basic operations
    public void put(String key, String value);
    public void putAll(Map<String, String> map);
    public String get(String key);
    public void remove(String key);
    public void removeAll(Iterable<String> keys);
    public void clear();
    
    // Query operations
    public boolean containsKey(String key);
    public boolean isEmpty();
    
    // Map access
    public Map<String, String> getCopy();
    public Map<String, String> getImmutableMapOrNull();
    
    // Log4j compatibility
    public StringMap getReadOnlyContextData();
}

OSGi Bundle Activator

Activator for OSGi environments to properly initialize the SLF4J provider.

public class Activator extends ProviderActivator {
    public Activator();
}

Types

Level Mapping

Log4j levels are mapped to SLF4J levels as follows:

  • TRACE → SLF4J TRACE
  • DEBUG → SLF4J DEBUG
  • INFO → SLF4J INFO
  • WARN → SLF4J WARN
  • ERROR → SLF4J ERROR
  • FATAL → SLF4J TRACE (atFatal() returns Level.TRACE, though this appears inconsistent with other level handling)

Marker Conversion

Log4j Markers are converted to SLF4J Markers while preserving:

  • Marker names and hierarchies
  • Parent-child relationships
  • Null marker handling

Performance Features

  • ThreadLocal LogBuilder Reuse: Reduces object allocation overhead
  • Lazy Level Checking: Optimized for frameworks supporting turbo filters (Logback)
  • Location-Aware Optimization: Uses LocationAwareLogger when available
  • Efficient Marker Conversion: Minimal conversion overhead with proper caching

Configuration Notes

Conflict Prevention

The library automatically detects and prevents conflicts with slf4j-impl jars by checking for org.slf4j.helpers.Log4jLoggerFactory on the classpath and throwing an IllegalStateException if found.

SLF4J Compatibility

Supports both SLF4J 1.x and 2.x versions with version range [1.7,3) in OSGi environments.

Service Loading

The provider is automatically discovered via the Java ServiceLoader mechanism using the service file: META-INF/services/org.apache.logging.log4j.spi.Provider