or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bridge-handler.mdindex.mdlevel-translation.mdlogger-adapters.mdlogmanager-integration.md

bridge-handler.mddocs/

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