Log4j API to SLF4J adapter that bridges Log4j API calls to SLF4J implementations
npx @tessl/cli install tessl/maven-org-apache-logging-log4j--log4j-to-slf4j@2.25.00
# Log4j to SLF4J Adapter
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: log4j-to-slf4j
7
- **Group ID**: org.apache.logging.log4j
8
- **Language**: Java
9
- **Installation**: Add Maven dependency:
10
11
```xml
12
<dependency>
13
<groupId>org.apache.logging.log4j</groupId>
14
<artifactId>log4j-to-slf4j</artifactId>
15
<version>2.25.1</version>
16
</dependency>
17
```
18
19
## Core Imports
20
21
Standard Log4j API imports work transparently:
22
23
```java
24
import org.apache.logging.log4j.LogManager;
25
import org.apache.logging.log4j.Logger;
26
import org.apache.logging.log4j.ThreadContext;
27
import org.apache.logging.log4j.Marker;
28
import org.apache.logging.log4j.MarkerManager;
29
```
30
31
## Basic Usage
32
33
The adapter works transparently - use standard Log4j API calls:
34
35
```java
36
import org.apache.logging.log4j.LogManager;
37
import org.apache.logging.log4j.Logger;
38
import org.apache.logging.log4j.ThreadContext;
39
40
public class Example {
41
private static final Logger logger = LogManager.getLogger(Example.class);
42
43
public void demonstrateLogging() {
44
// Standard Log4j logging - automatically forwards to SLF4J
45
logger.info("This is an info message");
46
logger.error("Error occurred", new RuntimeException("test"));
47
48
// Thread context (MDC) support
49
ThreadContext.put("userId", "12345");
50
logger.info("User action performed");
51
ThreadContext.clear();
52
53
// Fluent logging API
54
logger.atInfo()
55
.withMarker(MarkerManager.getMarker("AUDIT"))
56
.log("Audit event: {}", "user_login");
57
}
58
}
59
```
60
61
## Architecture
62
63
This library implements the Log4j Provider SPI to transparently bridge Log4j API calls to SLF4J:
64
65
- **Provider Registration**: Automatically discovered via Java ServiceLoader mechanism
66
- **Logger Context**: Creates SLF4J-backed loggers that implement Log4j's ExtendedLogger interface
67
- **Level Mapping**: Translates Log4j levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL) to SLF4J levels
68
- **Marker Translation**: Converts Log4j Markers to SLF4J Markers with hierarchy preservation
69
- **Thread Context Bridge**: Maps Log4j ThreadContext operations to SLF4J MDC
70
- **Location-Aware Logging**: Leverages SLF4J LocationAwareLogger when available for better performance
71
72
## Capabilities
73
74
### Provider Integration
75
76
Core provider that registers with Log4j's logging system to intercept and forward API calls.
77
78
```java { .api }
79
public class SLF4JProvider extends org.apache.logging.log4j.spi.Provider {
80
public SLF4JProvider();
81
public LoggerContextFactory getLoggerContextFactory();
82
public ThreadContextMap getThreadContextMapInstance();
83
}
84
```
85
86
The provider is automatically discovered and has priority 15, allowing higher-priority providers to override it.
87
88
### Logger Context Factory
89
90
Factory responsible for creating and managing the SLF4J logger context.
91
92
```java { .api }
93
public class SLF4JLoggerContextFactory implements LoggerContextFactory {
94
public SLF4JLoggerContextFactory();
95
public LoggerContext getContext(String fqcn, ClassLoader loader, Object externalContext, boolean currentContext);
96
public LoggerContext getContext(String fqcn, ClassLoader loader, Object externalContext, boolean currentContext, URI configLocation, String name);
97
public void removeContext(LoggerContext context);
98
public boolean isClassLoaderDependent();
99
}
100
```
101
102
The factory validates configuration to prevent conflicts with slf4j-impl jars and returns a singleton context.
103
104
### Logger Context
105
106
Context that creates and manages SLF4J-backed logger instances.
107
108
```java { .api }
109
public class SLF4JLoggerContext implements LoggerContext {
110
public Object getExternalContext();
111
public ExtendedLogger getLogger(String name);
112
public ExtendedLogger getLogger(String name, MessageFactory messageFactory);
113
public boolean hasLogger(String name);
114
public boolean hasLogger(String name, MessageFactory messageFactory);
115
public boolean hasLogger(String name, Class<? extends MessageFactory> messageFactoryClass);
116
}
117
```
118
119
### SLF4J Logger Implementation
120
121
Main logger implementation that forwards Log4j API calls to underlying SLF4J loggers.
122
123
```java { .api }
124
public class SLF4JLogger extends AbstractLogger {
125
public static final long serialVersionUID = 1L;
126
127
public SLF4JLogger(String name, MessageFactory messageFactory, org.slf4j.Logger logger);
128
public SLF4JLogger(String name, org.slf4j.Logger logger);
129
130
// Level management
131
public Level getLevel();
132
public org.slf4j.Logger getLogger();
133
134
// Level checking methods
135
public boolean isEnabled(Level level, Marker marker, Message data, Throwable t);
136
public boolean isEnabled(Level level, Marker marker, CharSequence data, Throwable t);
137
public boolean isEnabled(Level level, Marker marker, Object data, Throwable t);
138
public boolean isEnabled(Level level, Marker marker, String data);
139
public boolean isEnabled(Level level, Marker marker, String data, Object... p1);
140
public boolean isEnabled(Level level, Marker marker, String message, Object p0);
141
public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1);
142
public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2);
143
public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3);
144
public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4);
145
public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5);
146
public boolean isEnabled(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6);
147
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);
148
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);
149
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);
150
public boolean isEnabled(Level level, Marker marker, String data, Throwable t);
151
152
// Core logging method
153
public void logMessage(String fqcn, Level level, Marker marker, Message message, Throwable t);
154
155
// Fluent API builders
156
public LogBuilder always();
157
public LogBuilder atTrace();
158
public LogBuilder atDebug();
159
public LogBuilder atInfo();
160
public LogBuilder atWarn();
161
public LogBuilder atError();
162
public LogBuilder atFatal();
163
public LogBuilder atLevel(Level level);
164
}
165
```
166
167
### Fluent Log Builder
168
169
Builder pattern implementation for constructing log statements fluently.
170
171
```java { .api }
172
public class SLF4JLogBuilder implements LogBuilder {
173
public SLF4JLogBuilder(SLF4JLogger logger, Level level);
174
public SLF4JLogBuilder();
175
176
// Builder configuration
177
public LogBuilder reset(SLF4JLogger logger, Level level);
178
public LogBuilder withMarker(Marker marker);
179
public LogBuilder withThrowable(Throwable throwable);
180
181
// State management
182
public boolean isInUse();
183
184
// Location methods (ignored as SLF4J doesn't support explicit location)
185
public LogBuilder withLocation();
186
public LogBuilder withLocation(StackTraceElement location);
187
188
// Logging methods (various overloads for different message types)
189
public void log();
190
public void log(Message message);
191
public void log(CharSequence message);
192
public void log(Object message);
193
public void log(String message);
194
public void log(String message, Object... params);
195
public void log(String message, Supplier<?>... params);
196
public void log(String message, Object p0);
197
public void log(String message, Object p0, Object p1);
198
public void log(String message, Object p0, Object p1, Object p2);
199
public void log(String message, Object p0, Object p1, Object p2, Object p3);
200
public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4);
201
public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5);
202
public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6);
203
public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7);
204
public void log(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8);
205
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);
206
public void log(Supplier<Message> messageSupplier);
207
public Message logAndGet(Supplier<Message> messageSupplier);
208
}
209
```
210
211
### Thread Context Map (MDC Bridge)
212
213
Implementation that bridges Log4j ThreadContext operations to SLF4J MDC.
214
215
```java { .api }
216
public class MDCContextMap implements CleanableThreadContextMap {
217
// Basic operations
218
public void put(String key, String value);
219
public void putAll(Map<String, String> map);
220
public String get(String key);
221
public void remove(String key);
222
public void removeAll(Iterable<String> keys);
223
public void clear();
224
225
// Query operations
226
public boolean containsKey(String key);
227
public boolean isEmpty();
228
229
// Map access
230
public Map<String, String> getCopy();
231
public Map<String, String> getImmutableMapOrNull();
232
233
// Log4j compatibility
234
public StringMap getReadOnlyContextData();
235
}
236
```
237
238
### OSGi Bundle Activator
239
240
Activator for OSGi environments to properly initialize the SLF4J provider.
241
242
```java { .api }
243
public class Activator extends ProviderActivator {
244
public Activator();
245
}
246
```
247
248
## Types
249
250
### Level Mapping
251
252
Log4j levels are mapped to SLF4J levels as follows:
253
- `TRACE` → SLF4J TRACE
254
- `DEBUG` → SLF4J DEBUG
255
- `INFO` → SLF4J INFO
256
- `WARN` → SLF4J WARN
257
- `ERROR` → SLF4J ERROR
258
- `FATAL` → SLF4J TRACE (atFatal() returns Level.TRACE, though this appears inconsistent with other level handling)
259
260
### Marker Conversion
261
262
Log4j Markers are converted to SLF4J Markers while preserving:
263
- Marker names and hierarchies
264
- Parent-child relationships
265
- Null marker handling
266
267
### Performance Features
268
269
- **ThreadLocal LogBuilder Reuse**: Reduces object allocation overhead
270
- **Lazy Level Checking**: Optimized for frameworks supporting turbo filters (Logback)
271
- **Location-Aware Optimization**: Uses LocationAwareLogger when available
272
- **Efficient Marker Conversion**: Minimal conversion overhead with proper caching
273
274
## Configuration Notes
275
276
### Conflict Prevention
277
278
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.
279
280
### SLF4J Compatibility
281
282
Supports both SLF4J 1.x and 2.x versions with version range `[1.7,3)` in OSGi environments.
283
284
### Service Loading
285
286
The provider is automatically discovered via the Java ServiceLoader mechanism using the service file:
287
`META-INF/services/org.apache.logging.log4j.spi.Provider`