or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdlogger-context-management.mdservlet-integration.mdweb-specific-features.md

web-specific-features.mddocs/

0

# Web-Specific Features

1

2

Web-aware logging components including servlet context lookups for configuration variables, servlet appenders for direct logging to container logs, and thread context utilities for capturing request information. These features enable Log4j to integrate deeply with web application environments.

3

4

## Capabilities

5

6

### WebLookup

7

8

Log4j lookup plugin that provides access to servlet context information within log configurations. Enables dynamic configuration values based on web application context.

9

10

```java { .api }

11

/**

12

* Log4j lookup for accessing servlet context information in configurations.

13

* Supports servlet context attributes, init parameters, and container metadata.

14

*/

15

@Plugin(name = "web", category = "Lookup")

16

public class WebLookup extends AbstractLookup {

17

18

/**

19

* Resolves web-related lookup keys to their corresponding values.

20

* Accesses current ServletContext via WebLoggerContextUtils.

21

*

22

* @param event LogEvent triggering the lookup (unused)

23

* @param key Lookup key specifying what information to retrieve

24

* @return String value corresponding to the key, or null if not found

25

*/

26

public String lookup(LogEvent event, String key);

27

}

28

```

29

30

**Supported Lookup Keys:**

31

32

```java { .api }

33

public class WebLookup extends AbstractLookup {

34

/** Prefix for servlet context attributes */

35

private static final String ATTR_PREFIX = "attr.";

36

37

/** Prefix for servlet init parameters */

38

private static final String INIT_PARAM_PREFIX = "initParam.";

39

}

40

```

41

42

**Available Lookup Values:**

43

44

- **`attr.{name}`** - ServletContext attribute value by name

45

- **`initParam.{name}`** - ServletContext init parameter by name

46

- **`rootDir`** - Web application root directory path

47

- **`contextPath`** - ServletContext path (e.g., "/myapp")

48

- **`contextPathName`** - Context path name without slashes

49

- **`servletContextName`** - ServletContext display name

50

- **`serverInfo`** - Server container information

51

- **`effectiveMajorVersion`** - Effective servlet API major version

52

- **`effectiveMinorVersion`** - Effective servlet API minor version

53

- **`majorVersion`** - Servlet API major version

54

- **`minorVersion`** - Servlet API minor version

55

- **Direct attribute/parameter names** - Falls back to direct ServletContext lookup

56

57

**Usage in Log4j Configuration:**

58

59

```xml

60

<Configuration>

61

<Properties>

62

<Property name="logDir">${web:rootDir}/logs</Property>

63

<Property name="appName">${web:servletContextName}</Property>

64

<Property name="version">${web:attr.appVersion}</Property>

65

</Properties>

66

67

<Appenders>

68

<File name="AppLog" fileName="${logDir}/${appName}.log">

69

<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%level] %logger{36} - %msg%n"/>

70

</File>

71

</Appenders>

72

73

<Loggers>

74

<Root level="info">

75

<AppenderRef ref="AppLog"/>

76

</Root>

77

</Loggers>

78

</Configuration>

79

```

80

81

**Error Handling:**

82

83

The WebLookup can throw exceptions in certain scenarios:

84

85

```java

86

// If rootDir cannot be resolved (e.g., in unexploded WAR)

87

throw new IllegalStateException(

88

"Failed to resolve web:rootDir -- servlet container unable to translate virtual path " +

89

" to real path (probably not deployed as exploded"

90

);

91

```

92

93

**Common Exceptions:**

94

- **`IllegalStateException`**: Thrown when web:rootDir cannot be resolved (usually in non-exploded WAR deployments)

95

- Returns `null` for unknown lookup keys or when ServletContext is not available

96

97

### ServletAppender

98

99

Log4j appender that writes log events directly to the servlet container's logging system using `ServletContext.log()`. Integrates Log4j output with container-managed logs.

100

101

```java { .api }

102

/**

103

* Log4j appender that logs using ServletContext's log method.

104

* Integrates with servlet container logging infrastructure.

105

*/

106

@Plugin(name = "Servlet", category = "Core", elementType = "appender", printObject = true)

107

public final class ServletAppender extends AbstractAppender {

108

109

/**

110

* Appends a log event to the servlet context log.

111

* Uses ServletContext.log() with optional throwable support.

112

*

113

* @param event LogEvent to append to servlet context log

114

*/

115

public void append(LogEvent event);

116

117

/**

118

* Creates a new ServletAppender builder for configuration.

119

*

120

* @return Builder instance for ServletAppender configuration

121

*/

122

public static <B extends Builder<B>> B newBuilder();

123

124

/**

125

* Creates ServletAppender instance (deprecated - use newBuilder()).

126

*

127

* @param layout Layout for formatting log events (must extend StringLayout)

128

* @param filter Filter for event filtering (optional)

129

* @param name Appender name (required)

130

* @param ignoreExceptions Whether to ignore exceptions during appending

131

* @return ServletAppender instance or null if invalid configuration

132

* @deprecated Use newBuilder() instead

133

*/

134

@Deprecated

135

public static ServletAppender createAppender(

136

Layout<? extends Serializable> layout,

137

Filter filter,

138

String name,

139

boolean ignoreExceptions);

140

}

141

```

142

143

**ServletAppender Builder:**

144

145

```java { .api }

146

/**

147

* Builder for ServletAppender configuration.

148

* Extends AbstractAppender.Builder with servlet-specific options.

149

*/

150

public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>

151

implements org.apache.logging.log4j.core.util.Builder<ServletAppender> {

152

153

/**

154

* Builds the ServletAppender with current configuration.

155

* Validates ServletContext availability and layout requirements.

156

*

157

* @return ServletAppender instance or null if validation fails

158

*/

159

public ServletAppender build();

160

161

/**

162

* Gets whether throwables are logged with servlet context.

163

*

164

* @return true if throwables logged via ServletContext.log(String, Throwable)

165

*/

166

public boolean isLogThrowables();

167

168

/**

169

* Sets whether to log throwables with servlet context.

170

* Controls whether to use ServletContext.log(String) or log(String, Throwable).

171

*

172

* @param logThrowables true to log throwables with servlet context

173

*/

174

public void setLogThrowables(boolean logThrowables);

175

}

176

```

177

178

**Configuration in Log4j XML:**

179

180

```xml

181

<Configuration>

182

<Appenders>

183

<Servlet name="ServletLog" logThrowables="true">

184

<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%level] %logger{36} - %msg%n"/>

185

</Servlet>

186

</Appenders>

187

188

<Loggers>

189

<Logger name="com.example.web" level="debug">

190

<AppenderRef ref="ServletLog"/>

191

</Logger>

192

<Root level="info">

193

<AppenderRef ref="ServletLog"/>

194

</Root>

195

</Loggers>

196

</Configuration>

197

```

198

199

**Usage Notes:**

200

- Requires StringLayout (PatternLayout, SimpleLayout, etc.)

201

- Only available when ServletContext is accessible

202

- Integrates with container's native logging (Tomcat catalina.out, etc.)

203

- `logThrowables` parameter controls exception logging behavior

204

205

### ServletRequestThreadContext

206

207

Utility class for capturing servlet request information in Log4j's ThreadContext. Enables automatic inclusion of request details in log messages.

208

209

```java { .api }

210

/**

211

* Utility for adding servlet request information to ThreadContext.

212

* Captures request metadata for inclusion in log messages.

213

*/

214

public class ServletRequestThreadContext {

215

216

/**

217

* Adds servlet request information to ThreadContext.

218

* Captures remote address, host, and port with specified key prefix.

219

*

220

* @param key Prefix for ThreadContext keys

221

* @param servletRequest ServletRequest to capture information from

222

*/

223

public static void put(String key, ServletRequest servletRequest);

224

225

/**

226

* Adds HTTP servlet request information to ThreadContext.

227

* Delegates to ServletRequest version - HTTP-specific data handled elsewhere.

228

*

229

* @param key Prefix for ThreadContext keys

230

* @param servletRequest HttpServletRequest to capture information from

231

*/

232

public static void put(String key, HttpServletRequest servletRequest);

233

234

/**

235

* Adds field-value pair to ThreadContext with key prefix.

236

* Helper method for structured request data capture.

237

*

238

* @param key Base key for ThreadContext

239

* @param field Field name to append to key

240

* @param value Field value to store

241

*/

242

public static void put(String key, String field, Object value);

243

244

/**

245

* Adds key-value pair directly to ThreadContext.

246

* Direct wrapper around ThreadContext.put().

247

*

248

* @param key ThreadContext key

249

* @param value ThreadContext value

250

*/

251

public static void put(String key, String value);

252

}

253

```

254

255

**Captured Request Information:**

256

257

When calling `put(String key, ServletRequest servletRequest)`, the following ThreadContext entries are created:

258

- **`{key}.RemoteAddr`** - `request.getRemoteAddr()`

259

- **`{key}.RemoteHost`** - `request.getRemoteHost()`

260

- **`{key}.RemotePort`** - `request.getRemotePort()`

261

262

**Usage in Servlet Filter:**

263

264

```java

265

public class RequestLoggingFilter implements Filter {

266

267

@Override

268

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

269

throws IOException, ServletException {

270

271

// Capture request information in ThreadContext

272

ServletRequestThreadContext.put("request", request);

273

274

if (request instanceof HttpServletRequest) {

275

HttpServletRequest httpRequest = (HttpServletRequest) request;

276

ServletRequestThreadContext.put("request", "Method", httpRequest.getMethod());

277

ServletRequestThreadContext.put("request", "URI", httpRequest.getRequestURI());

278

ServletRequestThreadContext.put("request", "QueryString", httpRequest.getQueryString());

279

}

280

281

try {

282

chain.doFilter(request, response);

283

} finally {

284

// ThreadContext automatically cleared by Log4jServletFilter

285

}

286

}

287

}

288

```

289

290

**Log4j Configuration with Request Data:**

291

292

```xml

293

<Configuration>

294

<Appenders>

295

<Console name="Console">

296

<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%level] %logger{36} - %msg [%X{request.RemoteAddr}] [%X{request.Method} %X{request.URI}]%n"/>

297

</Console>

298

</Appenders>

299

300

<Loggers>

301

<Root level="info">

302

<AppenderRef ref="Console"/>

303

</Root>

304

</Loggers>

305

</Configuration>

306

```

307

308

## Integration Examples

309

310

### Combined Web Features Usage

311

312

```java

313

@WebFilter("/*")

314

public class LoggingFilter implements Filter {

315

316

@Override

317

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

318

throws IOException, ServletException {

319

320

// Capture request context

321

ServletRequestThreadContext.put("req", request);

322

323

if (request instanceof HttpServletRequest) {

324

HttpServletRequest httpReq = (HttpServletRequest) request;

325

ServletRequestThreadContext.put("req", "method", httpReq.getMethod());

326

ServletRequestThreadContext.put("req", "uri", httpReq.getRequestURI());

327

ServletRequestThreadContext.put("req", "userAgent", httpReq.getHeader("User-Agent"));

328

}

329

330

Logger logger = LogManager.getLogger();

331

logger.info("Processing request");

332

333

try {

334

chain.doFilter(request, response);

335

logger.info("Request completed successfully");

336

} catch (Exception e) {

337

logger.error("Request failed", e);

338

throw e;

339

}

340

}

341

}

342

```

343

344

### Dynamic Configuration with Web Lookups

345

346

```xml

347

<Configuration>

348

<Properties>

349

<Property name="app.name">${web:servletContextName}</Property>

350

<Property name="app.version">${web:attr.version}</Property>

351

<Property name="log.path">${web:rootDir}/WEB-INF/logs</Property>

352

<Property name="container.info">${web:serverInfo}</Property>

353

</Properties>

354

355

<Appenders>

356

<File name="AppFile" fileName="${log.path}/${app.name}-${app.version}.log">

357

<PatternLayout pattern="%d [%level] %logger - %msg [%X{req.RemoteAddr}] [%X{req.method} %X{req.uri}]%n"/>

358

</File>

359

360

<Servlet name="ContainerLog" logThrowables="true">

361

<PatternLayout pattern="[${app.name}] %d [%level] %logger - %msg%n"/>

362

</Servlet>

363

</Appenders>

364

365

<Loggers>

366

<Logger name="com.example" level="debug">

367

<AppenderRef ref="AppFile"/>

368

<AppenderRef ref="ContainerLog"/>

369

</Logger>

370

<Root level="info">

371

<AppenderRef ref="ContainerLog"/>

372

</Root>

373

</Loggers>

374

</Configuration>

375

```

376

377

This configuration demonstrates:

378

- Dynamic file paths using web application root directory

379

- Application name and version from servlet context

380

- Request information in log patterns

381

- Dual output to both file and container logs