0
# Parameterized Logging & Performance
1
2
High-performance logging features including parameterized messages with {} placeholders, supplier-based lazy evaluation, and fluent LogBuilder API for complex log events.
3
4
## Capabilities
5
6
### Parameterized Messages
7
8
Efficient logging using {} placeholders that avoid string concatenation when logging is disabled.
9
10
```java { .api }
11
public interface Logger {
12
// Parameterized logging for all levels
13
void trace(String message, Object... params);
14
void debug(String message, Object... params);
15
void info(String message, Object... params);
16
void warn(String message, Object... params);
17
void error(String message, Object... params);
18
void fatal(String message, Object... params);
19
20
// Parameterized with throwable
21
void trace(String message, Throwable throwable, Object... params);
22
void debug(String message, Throwable throwable, Object... params);
23
void info(String message, Throwable throwable, Object... params);
24
void warn(String message, Throwable throwable, Object... params);
25
void error(String message, Throwable throwable, Object... params);
26
void fatal(String message, Throwable throwable, Object... params);
27
28
// Generic parameterized logging
29
void log(Level level, String message, Object... params);
30
void log(Level level, String message, Throwable throwable, Object... params);
31
}
32
```
33
34
**Usage Examples:**
35
36
```java
37
private static final Logger logger = LogManager.getLogger();
38
39
public void demonstrateParameterizedLogging() {
40
String username = "alice";
41
int userId = 12345;
42
long processingTime = 150;
43
44
// Efficient - no string concatenation if INFO is disabled
45
logger.info("User {} (ID: {}) logged in", username, userId);
46
47
// Multiple parameters
48
logger.debug("Processing completed for user {} in {}ms with {} items",
49
username, processingTime, getItemCount());
50
51
// With exception
52
try {
53
processUser(userId);
54
} catch (Exception e) {
55
logger.error("Failed to process user {} ({})", username, userId, e);
56
}
57
58
// Arrays and objects are automatically formatted
59
String[] roles = {"admin", "user"};
60
logger.info("User {} has roles: {}", username, roles);
61
62
// Complex objects use toString()
63
UserProfile profile = getUserProfile(userId);
64
logger.debug("Loaded profile: {}", profile);
65
}
66
67
// Performance comparison
68
public void performanceExample() {
69
String data = "expensive data";
70
71
// BAD - string concatenation always happens
72
logger.debug("Processing data: " + expensiveCalculation() + " for user " + data);
73
74
// GOOD - parameters only evaluated if DEBUG is enabled
75
logger.debug("Processing data: {} for user {}", expensiveCalculation(), data);
76
77
// EVEN BETTER - explicit level check for very expensive operations
78
if (logger.isDebugEnabled()) {
79
logger.debug("Very expensive debug: {}", veryExpensiveOperation());
80
}
81
}
82
```
83
84
### Supplier-Based Lazy Evaluation
85
86
Use suppliers for expensive message generation that should only occur when logging is enabled.
87
88
```java { .api }
89
public interface Logger {
90
// Supplier-based logging for all levels
91
void trace(Supplier<?> messageSupplier);
92
void debug(Supplier<?> messageSupplier);
93
void info(Supplier<?> messageSupplier);
94
void warn(Supplier<?> messageSupplier);
95
void error(Supplier<?> messageSupplier);
96
void fatal(Supplier<?> messageSupplier);
97
98
// Supplier with throwable
99
void trace(Supplier<?> messageSupplier, Throwable throwable);
100
void debug(Supplier<?> messageSupplier, Throwable throwable);
101
void info(Supplier<?> messageSupplier, Throwable throwable);
102
void warn(Supplier<?> messageSupplier, Throwable throwable);
103
void error(Supplier<?> messageSupplier, Throwable throwable);
104
void fatal(Supplier<?> messageSupplier, Throwable throwable);
105
106
// Generic supplier logging
107
void log(Level level, Supplier<?> messageSupplier);
108
void log(Level level, Supplier<?> messageSupplier, Throwable throwable);
109
}
110
111
/**
112
* Functional interface for lazy message evaluation
113
*/
114
public interface Supplier<T> {
115
T get();
116
}
117
118
/**
119
* Supplier specifically for Message objects
120
*/
121
public interface MessageSupplier extends Supplier<Message> {
122
Message get();
123
}
124
```
125
126
**Usage Examples:**
127
128
```java
129
private static final Logger logger = LogManager.getLogger();
130
131
public void demonstrateSupplierLogging() {
132
// Lambda supplier - only executed if DEBUG is enabled
133
logger.debug(() -> "Expensive calculation result: " + performExpensiveCalculation());
134
135
// Method reference supplier
136
logger.trace(this::generateDetailedDiagnostics);
137
138
// Complex supplier with multiple operations
139
logger.debug(() -> {
140
Map<String, Object> context = gatherContextData();
141
return "Context: " + formatContext(context);
142
});
143
144
// Supplier with exception
145
Exception ex = new RuntimeException("test");
146
logger.error(() -> "Error processing request: " + getCurrentRequest(), ex);
147
148
// MessageSupplier for custom messages
149
logger.info(() -> new ObjectMessage(createStatusReport()));
150
}
151
152
private String performExpensiveCalculation() {
153
// Simulate expensive operation
154
return "calculated value";
155
}
156
157
private String generateDetailedDiagnostics() {
158
// Complex diagnostic generation
159
return "detailed diagnostics";
160
}
161
```
162
163
### LogBuilder Fluent API
164
165
Fluent interface for constructing complex log events with multiple attributes.
166
167
```java { .api }
168
/**
169
* Fluent API for constructing log events
170
*/
171
public interface LogBuilder {
172
/** Add a marker to the log event */
173
LogBuilder withMarker(Marker marker);
174
175
/** Add a throwable to the log event */
176
LogBuilder withThrowable(Throwable throwable);
177
178
/** Calculate and include caller location information */
179
LogBuilder withLocation();
180
181
/** Set explicit caller location */
182
LogBuilder withLocation(StackTraceElement location);
183
184
// Log methods with various parameter combinations
185
void log(String message);
186
void log(String message, Object p0);
187
void log(String message, Object p0, Object p1);
188
void log(String message, Object p0, Object p1, Object p2);
189
// ... overloads for up to 10 parameters
190
void log(String message, Object... params);
191
void log(Message message);
192
void log(Object message);
193
void log(Supplier<Message> messageSupplier);
194
195
/** No-operation LogBuilder for disabled levels */
196
LogBuilder NOOP = new NoOpLogBuilder();
197
}
198
199
public interface Logger {
200
/** Get LogBuilders for each level */
201
LogBuilder atTrace();
202
LogBuilder atDebug();
203
LogBuilder atInfo();
204
LogBuilder atWarn();
205
LogBuilder atError();
206
LogBuilder atFatal();
207
LogBuilder atLevel(Level level);
208
}
209
```
210
211
**Usage Examples:**
212
213
```java
214
private static final Logger logger = LogManager.getLogger();
215
private static final Marker SECURITY_MARKER = MarkerManager.getMarker("SECURITY");
216
217
public void demonstrateLogBuilder() {
218
// Simple fluent logging
219
logger.atInfo()
220
.log("User logged in successfully");
221
222
// Complex log event with multiple attributes
223
logger.atError()
224
.withMarker(SECURITY_MARKER)
225
.withThrowable(exception)
226
.withLocation()
227
.log("Security violation detected for user {}", username);
228
229
// Conditional building
230
LogBuilder builder = logger.atDebug();
231
if (includeLocation) {
232
builder = builder.withLocation();
233
}
234
if (marker != null) {
235
builder = builder.withMarker(marker);
236
}
237
builder.log("Debug message with conditional attributes");
238
239
// Method chaining with different message types
240
logger.atWarn()
241
.withMarker(performanceMarker)
242
.log(() -> new ObjectMessage(performanceMetrics));
243
244
// Using with try-catch
245
try {
246
processRequest();
247
} catch (Exception e) {
248
logger.atError()
249
.withThrowable(e)
250
.withMarker(SECURITY_MARKER)
251
.log("Request processing failed for user {}", getCurrentUser());
252
}
253
}
254
255
// Performance note: LogBuilder for disabled levels returns NOOP
256
public void performanceNote() {
257
// If TRACE is disabled, this returns LogBuilder.NOOP which ignores all operations
258
LogBuilder builder = logger.atTrace(); // Returns NOOP if TRACE disabled
259
builder.withMarker(marker) // No-op
260
.withLocation() // No-op
261
.log("Expensive trace message"); // No-op
262
}
263
```
264
265
### Flow Tracing
266
267
Methods for tracing method entry and exit points with automatic parameter capture.
268
269
```java { .api }
270
public interface Logger {
271
/** Trace method entry */
272
void traceEntry();
273
274
/** Trace method entry with parameters */
275
void traceEntry(String format, Object... params);
276
277
/** Trace method entry with message */
278
void traceEntry(Message message);
279
280
/** Trace method exit */
281
void traceExit();
282
283
/** Trace method exit with return value */
284
<T> T traceExit(T result);
285
286
/** Trace method exit with message */
287
void traceExit(Message message);
288
289
/** Trace method exit with entry message and return value */
290
<T> T traceExit(Message message, T result);
291
292
/** Log and return caught exception */
293
<T extends Throwable> T catching(T throwable);
294
295
/** Log and throw exception */
296
<T extends Throwable> T throwing(T throwable);
297
}
298
```
299
300
**Usage Examples:**
301
302
```java
303
private static final Logger logger = LogManager.getLogger();
304
305
public String processUser(String userId, String action) {
306
// Trace entry with parameters
307
logger.traceEntry("userId={}, action={}", userId, action);
308
309
try {
310
// Method implementation
311
String result = performAction(userId, action);
312
313
// Trace exit with return value
314
return logger.traceExit(result);
315
316
} catch (Exception e) {
317
// Log and re-throw exception
318
throw logger.throwing(e);
319
}
320
}
321
322
public void handleException() {
323
try {
324
riskyOperation();
325
} catch (Exception e) {
326
// Log caught exception and continue
327
logger.catching(e);
328
// Handle exception...
329
}
330
}
331
332
// Automatic method tracing pattern
333
public User findUser(Long id) {
334
logger.traceEntry("id={}", id);
335
336
try {
337
User user = userRepository.findById(id);
338
if (user == null) {
339
throw new UserNotFoundException("User not found: " + id);
340
}
341
return logger.traceExit(user);
342
} catch (Exception e) {
343
throw logger.throwing(e);
344
}
345
}
346
```
347
348
### Level Checking Performance
349
350
Efficient level checking to avoid expensive operations when logging is disabled.
351
352
```java { .api }
353
public interface Logger {
354
// Level checking methods
355
boolean isTraceEnabled();
356
boolean isDebugEnabled();
357
boolean isInfoEnabled();
358
boolean isWarnEnabled();
359
boolean isErrorEnabled();
360
boolean isFatalEnabled();
361
boolean isEnabled(Level level);
362
363
// Level checking with markers
364
boolean isTraceEnabled(Marker marker);
365
boolean isDebugEnabled(Marker marker);
366
boolean isInfoEnabled(Marker marker);
367
boolean isWarnEnabled(Marker marker);
368
boolean isErrorEnabled(Marker marker);
369
boolean isFatalEnabled(Marker marker);
370
boolean isEnabled(Level level, Marker marker);
371
}
372
```
373
374
**Usage Examples:**
375
376
```java
377
private static final Logger logger = LogManager.getLogger();
378
379
public void efficientLogging() {
380
// Guard expensive operations
381
if (logger.isDebugEnabled()) {
382
String expensiveData = generateExpensiveDebugData();
383
logger.debug("Debug data: {}", expensiveData);
384
}
385
386
// Multiple expensive parameters
387
if (logger.isTraceEnabled()) {
388
logger.trace("Trace: {} {} {}",
389
expensiveOp1(), expensiveOp2(), expensiveOp3());
390
}
391
392
// Level checking with markers
393
Marker performanceMarker = MarkerManager.getMarker("PERFORMANCE");
394
if (logger.isInfoEnabled(performanceMarker)) {
395
logger.info(performanceMarker, "Performance metrics: {}",
396
collectPerformanceMetrics());
397
}
398
399
// Dynamic level checking
400
Level dynamicLevel = getDynamicLevel();
401
if (logger.isEnabled(dynamicLevel)) {
402
logger.log(dynamicLevel, "Dynamic message: {}", getDynamicData());
403
}
404
}
405
```