or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

appenders-layouts.mdconfiguration.mdcore-logging.mddiagnostic-contexts.mdindex.mdlevel-management.md

diagnostic-contexts.mddocs/

0

# Diagnostic Contexts

1

2

Mapped Diagnostic Context (MDC) and Nested Diagnostic Context (NDC) for adding contextual information to log messages. Both contexts bridge to SLF4J's MDC mechanism for thread-local diagnostic data.

3

4

## Capabilities

5

6

### Mapped Diagnostic Context (MDC)

7

8

Thread-local key-value storage for contextual information that can be included in log messages. All operations delegate to SLF4J's MDC.

9

10

```java { .api }

11

/**

12

* Put a key-value pair in the MDC

13

* @param key The key

14

* @param value The value as String

15

*/

16

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

17

18

/**

19

* Put a key-value pair in the MDC (Object converted to String)

20

* @param key The key

21

* @param value The value as Object (converted to String via toString())

22

*/

23

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

24

25

/**

26

* Get value by key from MDC

27

* @param key The key to lookup

28

* @return The value or null if not found

29

*/

30

public static Object get(String key);

31

32

/**

33

* Remove key-value pair from MDC

34

* @param key The key to remove

35

*/

36

public static void remove(String key);

37

38

/**

39

* Clear all MDC data for current thread

40

*/

41

public static void clear();

42

43

/**

44

* Get MDC context as Hashtable (deprecated)

45

* @return Copy of MDC context as Hashtable

46

* @deprecated This method may be removed in future versions

47

*/

48

@Deprecated

49

public static Hashtable<String, String> getContext();

50

```

51

52

**Usage Examples:**

53

54

```java

55

import org.apache.log4j.MDC;

56

import org.apache.log4j.Logger;

57

58

Logger logger = Logger.getLogger(MyClass.class);

59

60

// Set context information

61

MDC.put("userId", "12345");

62

MDC.put("sessionId", "abc-def-ghi");

63

MDC.put("requestId", UUID.randomUUID().toString());

64

65

// Log messages will include MDC context (if configured in SLF4J implementation)

66

logger.info("Processing user request");

67

68

// Can put different types (converted to String)

69

MDC.put("timestamp", System.currentTimeMillis());

70

MDC.put("userRole", UserRole.ADMIN);

71

72

// Retrieve values

73

String userId = (String) MDC.get("userId");

74

String sessionId = (String) MDC.get("sessionId");

75

76

// Remove specific key

77

MDC.remove("requestId");

78

79

// Clear all context for thread

80

MDC.clear();

81

82

// Example in web application filter

83

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

84

try {

85

// Set context for request

86

MDC.put("requestId", generateRequestId());

87

MDC.put("remoteAddr", request.getRemoteAddr());

88

89

chain.doFilter(request, response);

90

} finally {

91

// Always clean up

92

MDC.clear();

93

}

94

}

95

```

96

97

### Nested Diagnostic Context (NDC)

98

99

Stack-based diagnostic context for hierarchical information. Implemented using SLF4J's MDC with numbered keys.

100

101

```java { .api }

102

/**

103

* NDC key prefix used for MDC storage

104

*/

105

public static final String PREFIX = "NDC";

106

107

/**

108

* Push a message onto the NDC stack

109

* @param message Message to push

110

*/

111

public static void push(String message);

112

113

/**

114

* Pop the top message from NDC stack

115

* @return The popped message or empty string if stack is empty

116

*/

117

public static String pop();

118

119

/**

120

* Peek at the top message without removing it

121

* @return The top message or empty string if stack is empty

122

*/

123

public static String peek();

124

125

/**

126

* Get current depth of NDC stack

127

* @return Stack depth

128

*/

129

public static int getDepth();

130

131

/**

132

* Clear all NDC data for current thread

133

*/

134

public static void clear();

135

136

/**

137

* Get NDC string (always returns null in this implementation)

138

* @return null

139

*/

140

public static String get();

141

142

/**

143

* Remove all NDC data (same as clear())

144

*/

145

public static void remove();

146

147

/**

148

* Clone NDC stack (always returns null in this implementation)

149

* @return null

150

*/

151

public static Stack<?> cloneStack();

152

153

/**

154

* Inherit NDC stack from another thread (no-op in this implementation)

155

* @param stack Stack to inherit from

156

*/

157

public static void inherit(Stack<?> stack);

158

159

/**

160

* Set maximum NDC depth (no-op in this implementation)

161

* @param maxDepth Maximum depth

162

*/

163

public static void setMaxDepth(int maxDepth);

164

```

165

166

**Usage Examples:**

167

168

```java

169

import org.apache.log4j.NDC;

170

import org.apache.log4j.Logger;

171

172

Logger logger = Logger.getLogger(MyClass.class);

173

174

// Build nested context

175

NDC.push("UserService");

176

logger.info("Starting user operation"); // Context: [UserService]

177

178

NDC.push("validateUser");

179

logger.debug("Validating user credentials"); // Context: [UserService, validateUser]

180

181

NDC.push("checkDatabase");

182

logger.debug("Querying user database"); // Context: [UserService, validateUser, checkDatabase]

183

184

// Check depth

185

int depth = NDC.getDepth(); // 3

186

187

// Peek without removing

188

String current = NDC.peek(); // "checkDatabase"

189

190

// Pop as operations complete

191

String finished = NDC.pop(); // "checkDatabase", depth now 2

192

logger.debug("Database check completed"); // Context: [UserService, validateUser]

193

194

NDC.pop(); // "validateUser", depth now 1

195

logger.info("User validation completed"); // Context: [UserService]

196

197

NDC.pop(); // "UserService", depth now 0

198

logger.info("User operation completed"); // Context: []

199

200

// Clear all context

201

NDC.clear();

202

203

// Example in method call hierarchy

204

public void processOrder(Order order) {

205

NDC.push("processOrder(" + order.getId() + ")");

206

try {

207

logger.info("Processing order");

208

validateOrder(order);

209

saveOrder(order);

210

notifyCustomer(order);

211

} finally {

212

NDC.pop();

213

}

214

}

215

216

private void validateOrder(Order order) {

217

NDC.push("validateOrder");

218

try {

219

logger.debug("Validating order data");

220

// validation logic

221

} finally {

222

NDC.pop();

223

}

224

}

225

```

226

227

### Context Best Practices

228

229

Guidelines for effective use of diagnostic contexts.

230

231

**MDC Best Practices:**

232

233

```java

234

// Use try-finally to ensure cleanup

235

public void handleRequest(HttpServletRequest request) {

236

try {

237

MDC.put("requestId", generateRequestId());

238

MDC.put("userId", getCurrentUserId());

239

240

// Process request

241

processRequest(request);

242

243

} finally {

244

// Always clean up to prevent memory leaks

245

MDC.clear();

246

}

247

}

248

249

// Use meaningful, consistent key names

250

MDC.put("user.id", userId);

251

MDC.put("session.id", sessionId);

252

MDC.put("request.method", request.getMethod());

253

MDC.put("request.uri", request.getRequestURI());

254

```

255

256

**NDC Best Practices:**

257

258

```java

259

// Use try-finally pattern for NDC as well

260

public void complexOperation() {

261

NDC.push("complexOperation");

262

try {

263

logger.info("Starting complex operation");

264

265

subOperation1();

266

subOperation2();

267

268

logger.info("Complex operation completed");

269

} finally {

270

NDC.pop();

271

}

272

}

273

274

// Use descriptive context names

275

NDC.push("OrderService.processPayment");

276

NDC.push("PaymentGateway.authorizeCard");

277

NDC.push("BankAPI.validateAccount");

278

```

279

280

**Combined Usage:**

281

282

```java

283

// MDC for request-wide context, NDC for call hierarchy

284

public void processUserRequest(String userId, String operation) {

285

try {

286

// Set request context with MDC

287

MDC.put("userId", userId);

288

MDC.put("operation", operation);

289

MDC.put("timestamp", Instant.now().toString());

290

291

// Track call hierarchy with NDC

292

NDC.push("processUserRequest");

293

294

logger.info("Processing user request");

295

performOperation(operation);

296

297

} finally {

298

NDC.clear();

299

MDC.clear();

300

}

301

}

302

```