0
# Bridge Handler
1
2
The Log4jBridgeHandler provides an alternative to LogManager replacement, especially useful for webapps running on containers where the LogManager cannot or should not be used. It acts as a JUL Handler that bridges log events from JUL to Log4j.
3
4
## Installation
5
6
### Declarative Configuration
7
8
Configure in JUL's `logging.properties`:
9
10
```properties
11
# Set the handler
12
handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler
13
14
# Enable level propagation (recommended)
15
org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true
16
17
# Optional: Add suffix to logger names
18
org.apache.logging.log4j.jul.Log4jBridgeHandler.suffixToAppend = _JUL
19
20
# Optional: Enable debug output
21
org.apache.logging.log4j.jul.Log4jBridgeHandler.sysoutDebug = false
22
```
23
24
### Programmatic Installation
25
26
```java
27
import org.apache.logging.log4j.jul.Log4jBridgeHandler;
28
29
// Install with configuration
30
Log4jBridgeHandler.install(
31
true, // removeHandlersForRootLogger - remove existing handlers
32
"_JUL", // suffixToAppend - suffix for logger names (optional)
33
true // propagateLevels - auto-propagate Log4j levels to JUL
34
);
35
```
36
37
### Manual Installation
38
39
```java
40
// Create and configure handler
41
Log4jBridgeHandler handler = new Log4jBridgeHandler(
42
false, // debugOutput
43
"_JUL", // suffixToAppend
44
true // propagateLevels
45
);
46
47
// Add to root logger
48
java.util.logging.Logger rootLogger = java.util.logging.Logger.getLogger("");
49
rootLogger.addHandler(handler);
50
```
51
52
## Usage
53
54
Once installed, all JUL log events are automatically bridged to Log4j:
55
56
```java
57
// Standard JUL logging - automatically bridged to Log4j
58
java.util.logging.Logger logger = java.util.logging.Logger.getLogger("com.example");
59
60
logger.severe("Critical error occurred");
61
logger.warning("Warning message");
62
logger.info("Information message");
63
logger.fine("Debug message");
64
logger.finest("Trace message");
65
66
// Parameterized messages
67
logger.log(java.util.logging.Level.INFO, "Processing {0} records in {1}ms",
68
new Object[]{count, duration});
69
70
// Exception logging
71
try {
72
riskyOperation();
73
} catch (Exception e) {
74
logger.log(java.util.logging.Level.SEVERE, "Operation failed", e);
75
}
76
```
77
78
## Configuration Options
79
80
### Suffix Appending
81
82
Add a suffix to JUL logger names to identify bridged messages:
83
84
```properties
85
org.apache.logging.log4j.jul.Log4jBridgeHandler.suffixToAppend = _JUL
86
```
87
88
This converts logger `com.example.Service` to `com.example.Service._JUL` in Log4j.
89
90
### Level Propagation
91
92
Automatically synchronize Log4j log levels with JUL:
93
94
```properties
95
org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true
96
```
97
98
When enabled:
99
- Log4j configuration changes trigger JUL level updates
100
- Eliminates the need to maintain duplicate level configurations
101
- Prevents JUL from filtering messages that Log4j should see
102
103
### Debug Output
104
105
Enable diagnostic output for troubleshooting:
106
107
```properties
108
org.apache.logging.log4j.jul.Log4jBridgeHandler.sysoutDebug = true
109
```
110
111
## API Reference
112
113
### Log4jBridgeHandler Class
114
115
```java { .api }
116
public class Log4jBridgeHandler extends java.util.logging.Handler implements PropertyChangeListener {
117
/**
118
* Creates handler reading configuration from JUL's LogManager.
119
* Reads properties: sysoutDebug, appendSuffix, propagateLevels.
120
*/
121
public Log4jBridgeHandler();
122
123
/**
124
* Creates handler with explicit configuration.
125
*
126
* @param debugOutput enable debug output to System.out
127
* @param suffixToAppend suffix for JUL logger names (null for none)
128
* @param propagateLevels enable automatic level propagation from Log4j to JUL
129
*/
130
public Log4jBridgeHandler(boolean debugOutput, String suffixToAppend, boolean propagateLevels);
131
132
/**
133
* Programmatically installs handler on JUL root logger.
134
*
135
* @param removeHandlersForRootLogger remove existing handlers from root logger
136
* @param suffixToAppend suffix for JUL logger names (null for none)
137
* @param propagateLevels enable automatic level propagation
138
*/
139
public static void install(boolean removeHandlersForRootLogger, String suffixToAppend, boolean propagateLevels);
140
141
/**
142
* Publishes JUL LogRecord to Log4j.
143
* Converts levels, handles messages, and propagates exceptions.
144
*
145
* @param record the JUL LogRecord to publish (null records are ignored)
146
*/
147
public void publish(LogRecord record);
148
149
/**
150
* No-op flush implementation.
151
*/
152
public void flush();
153
154
/**
155
* Cleanup handler resources and remove property change listeners.
156
*/
157
public void close();
158
}
159
```
160
161
## Level Propagation Details
162
163
When level propagation is enabled, the handler:
164
165
1. **Monitors Log4j Configuration**: Listens for Log4j configuration changes
166
2. **Updates JUL Levels**: Automatically sets JUL logger levels to match Log4j
167
3. **Maintains References**: Keeps hard references to JUL loggers to prevent garbage collection
168
4. **Cleans Up Unused**: Resets JUL levels for loggers not configured in Log4j
169
170
### Propagation Process
171
172
```java
173
// When Log4j configuration changes:
174
for (LoggerConfig log4jConfig : log4jConfiguration.getLoggers().values()) {
175
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger(log4jConfig.getName());
176
java.util.logging.Level julLevel = LevelTranslator.toJavaLevel(log4jConfig.getLevel());
177
julLogger.setLevel(julLevel);
178
}
179
```
180
181
## Level Translation
182
183
The bridge handler uses `LevelTranslator` for bidirectional level conversion:
184
185
- JUL SEVERE → Log4j ERROR
186
- JUL WARNING → Log4j WARN
187
- JUL INFO → Log4j INFO
188
- JUL CONFIG → Log4j CONFIG (custom level)
189
- JUL FINE → Log4j DEBUG
190
- JUL FINER → Log4j TRACE
191
- JUL FINEST → Log4j FINEST (custom level)
192
193
## Performance Considerations
194
195
### Handler Overhead
196
- **Message Formatting**: Uses JUL's SimpleFormatter for message formatting
197
- **Level Conversion**: Minimal overhead for level translation
198
- **Logger Lookup**: Cached Log4j logger instances for performance
199
200
### Level Filtering
201
- **JUL Pre-filtering**: Only log events passing JUL's level filter reach the handler
202
- **Dual Filtering**: Messages filtered by both JUL and Log4j levels
203
- **Optimization**: Use level propagation to align filtering
204
205
### Extended Logger Support
206
- **Enhanced Performance**: Uses ExtendedLogger.logIfEnabled() when available
207
- **Location Information**: Preserves caller location through FQCN
208
- **Fallback Handling**: Falls back to standard Logger.log() if ExtendedLogger fails
209
210
## Restrictions and Limitations
211
212
1. **Location Information**: Manually provided source location in JUL methods (entering(), exiting(), logp(), etc.) is not preserved
213
2. **Level Configuration**: Requires level configuration in both JUL and Log4j unless using level propagation
214
3. **Performance**: Additional overhead compared to LogManager approach
215
4. **Handler Chain**: Only processes log events that pass JUL's handler chain
216
217
## Webapp Integration
218
219
For Tomcat webapps, create `WEB-INF/classes/logging.properties`:
220
221
```properties
222
# Complete JUL configuration for this webapp only
223
.level = INFO
224
handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler
225
226
# Configure bridge handler
227
org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true
228
org.apache.logging.log4j.jul.Log4jBridgeHandler.suffixToAppend = _WEBAPP
229
230
# Optional: specific logger levels
231
com.example.level = DEBUG
232
```
233
234
## Error Handling
235
236
The bridge handler gracefully handles various error conditions:
237
238
- **Null Records**: Silently ignores null LogRecord instances
239
- **ExtendedLogger Failures**: Falls back to standard logging if ExtendedLogger throws NoClassDefFoundError
240
- **Logger Name Handling**: Uses fallback name for null logger names
241
- **Configuration Errors**: Continues operation with default settings if configuration fails
242
243
## Thread Safety
244
245
The Log4jBridgeHandler is fully thread-safe:
246
- **Synchronized Level Propagation**: Level propagation setup is synchronized
247
- **Property Change Handling**: Thread-safe property change listener registration
248
- **Logger References**: Thread-safe management of JUL logger references