0
# Logging System
1
2
The Logging System provides a simplified static logging facade with build-time optimization and multiple log levels for Quarkus applications.
3
4
## Static Logging Facade
5
6
### Log Class
7
8
```java { .api }
9
public final class Log {
10
11
// Level checking methods
12
/**
13
* Check if TRACE level is enabled.
14
* @return true if TRACE logging is enabled
15
*/
16
public static boolean isTraceEnabled();
17
18
/**
19
* Check if DEBUG level is enabled.
20
* @return true if DEBUG logging is enabled
21
*/
22
public static boolean isDebugEnabled();
23
24
/**
25
* Check if INFO level is enabled.
26
* @return true if INFO logging is enabled
27
*/
28
public static boolean isInfoEnabled();
29
30
/**
31
* Check if WARN level is enabled.
32
* @return true if WARN logging is enabled
33
*/
34
public static boolean isWarnEnabled();
35
36
/**
37
* Check if ERROR level is enabled.
38
* @return true if ERROR logging is enabled
39
*/
40
public static boolean isErrorEnabled();
41
42
/**
43
* Check if FATAL level is enabled.
44
* @return true if FATAL logging is enabled
45
*/
46
public static boolean isFatalEnabled();
47
48
/**
49
* Check if specific log level is enabled.
50
* @param level The log level to check
51
* @return true if the specified level is enabled
52
*/
53
public static boolean isEnabled(Logger.Level level);
54
55
// TRACE level logging
56
/**
57
* Log a message at TRACE level.
58
* @param message The message to log
59
*/
60
public static void trace(Object message);
61
62
/**
63
* Log a message at TRACE level with throwable.
64
* @param message The message to log
65
* @param t The throwable to log
66
*/
67
public static void trace(Object message, Throwable t);
68
69
/**
70
* Log a formatted message at TRACE level.
71
* @param format The message format string
72
* @param params The parameters for formatting
73
*/
74
public static void tracef(String format, Object... params);
75
76
/**
77
* Log a formatted message at TRACE level using MessageFormat.
78
* @param format The MessageFormat pattern
79
* @param params The parameters for formatting
80
*/
81
public static void tracev(String format, Object... params);
82
83
// DEBUG level logging
84
/**
85
* Log a message at DEBUG level.
86
* @param message The message to log
87
*/
88
public static void debug(Object message);
89
90
/**
91
* Log a message at DEBUG level with throwable.
92
* @param message The message to log
93
* @param t The throwable to log
94
*/
95
public static void debug(Object message, Throwable t);
96
97
/**
98
* Log a formatted message at DEBUG level.
99
* @param format The message format string
100
* @param params The parameters for formatting
101
*/
102
public static void debugf(String format, Object... params);
103
104
/**
105
* Log a formatted message at DEBUG level using MessageFormat.
106
* @param format The MessageFormat pattern
107
* @param params The parameters for formatting
108
*/
109
public static void debugv(String format, Object... params);
110
111
// INFO level logging
112
/**
113
* Log a message at INFO level.
114
* @param message The message to log
115
*/
116
public static void info(Object message);
117
118
/**
119
* Log a message at INFO level with throwable.
120
* @param message The message to log
121
* @param t The throwable to log
122
*/
123
public static void info(Object message, Throwable t);
124
125
/**
126
* Log a formatted message at INFO level.
127
* @param format The message format string
128
* @param params The parameters for formatting
129
*/
130
public static void infof(String format, Object... params);
131
132
/**
133
* Log a formatted message at INFO level using MessageFormat.
134
* @param format The MessageFormat pattern
135
* @param params The parameters for formatting
136
*/
137
public static void infov(String format, Object... params);
138
139
// WARN level logging
140
/**
141
* Log a message at WARN level.
142
* @param message The message to log
143
*/
144
public static void warn(Object message);
145
146
/**
147
* Log a message at WARN level with throwable.
148
* @param message The message to log
149
* @param t The throwable to log
150
*/
151
public static void warn(Object message, Throwable t);
152
153
/**
154
* Log a formatted message at WARN level.
155
* @param format The message format string
156
* @param params The parameters for formatting
157
*/
158
public static void warnf(String format, Object... params);
159
160
/**
161
* Log a formatted message at WARN level using MessageFormat.
162
* @param format The MessageFormat pattern
163
* @param params The parameters for formatting
164
*/
165
public static void warnv(String format, Object... params);
166
167
// ERROR level logging
168
/**
169
* Log a message at ERROR level.
170
* @param message The message to log
171
*/
172
public static void error(Object message);
173
174
/**
175
* Log a message at ERROR level with throwable.
176
* @param message The message to log
177
* @param t The throwable to log
178
*/
179
public static void error(Object message, Throwable t);
180
181
/**
182
* Log a formatted message at ERROR level.
183
* @param format The message format string
184
* @param params The parameters for formatting
185
*/
186
public static void errorf(String format, Object... params);
187
188
/**
189
* Log a formatted message at ERROR level using MessageFormat.
190
* @param format The MessageFormat pattern
191
* @param params The parameters for formatting
192
*/
193
public static void errorv(String format, Object... params);
194
195
// FATAL level logging
196
/**
197
* Log a message at FATAL level.
198
* @param message The message to log
199
*/
200
public static void fatal(Object message);
201
202
/**
203
* Log a message at FATAL level with throwable.
204
* @param message The message to log
205
* @param t The throwable to log
206
*/
207
public static void fatal(Object message, Throwable t);
208
209
/**
210
* Log a formatted message at FATAL level.
211
* @param format The message format string
212
* @param params The parameters for formatting
213
*/
214
public static void fatalf(String format, Object... params);
215
216
/**
217
* Log a formatted message at FATAL level using MessageFormat.
218
* @param format The MessageFormat pattern
219
* @param params The parameters for formatting
220
*/
221
public static void fatalv(String format, Object... params);
222
223
// Generic logging methods
224
/**
225
* Log a message at the specified level.
226
* @param level The log level
227
* @param message The message to log
228
*/
229
public static void log(Logger.Level level, Object message);
230
231
/**
232
* Log a message at the specified level with throwable.
233
* @param level The log level
234
* @param message The message to log
235
* @param t The throwable to log
236
*/
237
public static void log(Logger.Level level, Object message, Throwable t);
238
239
/**
240
* Log a formatted message at the specified level.
241
* @param level The log level
242
* @param format The message format string
243
* @param params The parameters for formatting
244
*/
245
public static void logf(Logger.Level level, String format, Object... params);
246
247
/**
248
* Log a formatted message at the specified level using MessageFormat.
249
* @param level The log level
250
* @param format The MessageFormat pattern
251
* @param params The parameters for formatting
252
*/
253
public static void logv(Logger.Level level, String format, Object... params);
254
}
255
```
256
257
## Usage Examples
258
259
### Basic Logging
260
261
```java
262
import io.quarkus.logging.Log;
263
import jakarta.enterprise.context.ApplicationScoped;
264
265
@ApplicationScoped
266
public class UserService {
267
268
public User findUser(Long id) {
269
Log.info("Finding user with ID: " + id);
270
271
try {
272
User user = userRepository.findById(id);
273
if (user != null) {
274
Log.debug("Found user: " + user.getName());
275
return user;
276
} else {
277
Log.warn("User not found with ID: " + id);
278
return null;
279
}
280
} catch (Exception e) {
281
Log.error("Error finding user with ID: " + id, e);
282
throw new UserNotFoundException("Failed to find user", e);
283
}
284
}
285
286
public void deleteUser(Long id) {
287
Log.info("Attempting to delete user with ID: " + id);
288
289
try {
290
userRepository.deleteById(id);
291
Log.info("Successfully deleted user with ID: " + id);
292
} catch (Exception e) {
293
Log.fatal("Critical error deleting user with ID: " + id, e);
294
throw new RuntimeException("Failed to delete user", e);
295
}
296
}
297
}
298
```
299
300
### Formatted Logging
301
302
```java
303
import io.quarkus.logging.Log;
304
import jakarta.enterprise.context.ApplicationScoped;
305
306
@ApplicationScoped
307
public class OrderService {
308
309
public void processOrder(Order order) {
310
// Using printf-style formatting
311
Log.infof("Processing order %d for customer %s with total $%.2f",
312
order.getId(), order.getCustomerName(), order.getTotal());
313
314
try {
315
validateOrder(order);
316
Log.debugf("Order %d validation successful", order.getId());
317
318
chargePayment(order);
319
Log.infof("Payment charged successfully for order %d: $%.2f",
320
order.getId(), order.getTotal());
321
322
fulfillOrder(order);
323
Log.infof("Order %d fulfilled successfully", order.getId());
324
325
} catch (ValidationException e) {
326
Log.warnf("Order %d validation failed: %s", order.getId(), e.getMessage());
327
throw e;
328
} catch (PaymentException e) {
329
Log.errorf("Payment failed for order %d: %s", order.getId(), e.getMessage());
330
throw e;
331
} catch (Exception e) {
332
Log.fatalf("Critical error processing order %d", order.getId(), e);
333
throw new RuntimeException("Order processing failed", e);
334
}
335
}
336
337
private void validateOrder(Order order) {
338
Log.tracef("Validating order %d with %d items", order.getId(), order.getItems().size());
339
// Validation logic
340
}
341
342
private void chargePayment(Order order) {
343
Log.debugf("Charging payment for order %d using method %s",
344
order.getId(), order.getPaymentMethod());
345
// Payment logic
346
}
347
348
private void fulfillOrder(Order order) {
349
Log.debugf("Fulfilling order %d to address: %s",
350
order.getId(), order.getShippingAddress());
351
// Fulfillment logic
352
}
353
}
354
```
355
356
### MessageFormat-style Logging
357
358
```java
359
import io.quarkus.logging.Log;
360
import jakarta.enterprise.context.ApplicationScoped;
361
362
@ApplicationScoped
363
public class ReportService {
364
365
public void generateReport(String reportType, Date startDate, Date endDate) {
366
// Using MessageFormat-style formatting
367
Log.infov("Generating {0} report from {1,date,short} to {2,date,short}",
368
reportType, startDate, endDate);
369
370
try {
371
int recordCount = countRecords(startDate, endDate);
372
Log.debugv("Found {0,number,integer} records for report {1}",
373
recordCount, reportType);
374
375
if (recordCount == 0) {
376
Log.warnv("No data found for {0} report between {1,date} and {2,date}",
377
reportType, startDate, endDate);
378
return;
379
}
380
381
generateReportFile(reportType, startDate, endDate, recordCount);
382
Log.infov("Successfully generated {0} report with {1,number,integer} records",
383
reportType, recordCount);
384
385
} catch (Exception e) {
386
Log.errorv("Failed to generate {0} report: {1}", reportType, e.getMessage(), e);
387
throw new ReportGenerationException("Report generation failed", e);
388
}
389
}
390
391
private int countRecords(Date startDate, Date endDate) {
392
// Count records logic
393
return 0;
394
}
395
396
private void generateReportFile(String reportType, Date startDate, Date endDate, int recordCount) {
397
// Report generation logic
398
}
399
}
400
```
401
402
### Conditional Logging
403
404
```java
405
import io.quarkus.logging.Log;
406
import jakarta.enterprise.context.ApplicationScoped;
407
408
@ApplicationScoped
409
public class DataProcessor {
410
411
public void processLargeDataset(List<DataRecord> records) {
412
Log.infof("Starting processing of %d records", records.size());
413
414
int processedCount = 0;
415
int errorCount = 0;
416
417
for (DataRecord record : records) {
418
try {
419
// Only log debug info if debug is enabled (performance optimization)
420
if (Log.isDebugEnabled()) {
421
Log.debugf("Processing record ID: %s, type: %s",
422
record.getId(), record.getType());
423
}
424
425
processRecord(record);
426
processedCount++;
427
428
// Log progress every 1000 records
429
if (processedCount % 1000 == 0) {
430
Log.infof("Processed %d/%d records", processedCount, records.size());
431
}
432
433
} catch (Exception e) {
434
errorCount++;
435
436
// Only log full stack trace for trace level
437
if (Log.isTraceEnabled()) {
438
Log.trace("Detailed error processing record: " + record.getId(), e);
439
} else {
440
Log.warnf("Error processing record %s: %s", record.getId(), e.getMessage());
441
}
442
443
// Stop processing if too many errors
444
if (errorCount > 100) {
445
Log.errorf("Too many errors (%d), stopping processing", errorCount);
446
break;
447
}
448
}
449
}
450
451
Log.infof("Processing completed. Processed: %d, Errors: %d", processedCount, errorCount);
452
}
453
454
private void processRecord(DataRecord record) {
455
// Record processing logic
456
457
// Trace level for very detailed logging
458
if (Log.isTraceEnabled()) {
459
Log.tracef("Record %s validation: passed=%b, score=%.2f",
460
record.getId(), record.isValid(), record.getQualityScore());
461
}
462
}
463
}
464
```
465
466
### Generic Level Logging
467
468
```java
469
import io.quarkus.logging.Log;
470
import org.jboss.logging.Logger;
471
import jakarta.enterprise.context.ApplicationScoped;
472
473
@ApplicationScoped
474
public class ConfigurableLogger {
475
476
public void logMessage(String message, String levelName) {
477
Logger.Level level = parseLogLevel(levelName);
478
479
if (Log.isEnabled(level)) {
480
Log.log(level, message);
481
}
482
}
483
484
public void logFormattedMessage(String levelName, String format, Object... params) {
485
Logger.Level level = parseLogLevel(levelName);
486
487
if (Log.isEnabled(level)) {
488
Log.logf(level, format, params);
489
}
490
}
491
492
public void logWithException(String levelName, String message, Throwable throwable) {
493
Logger.Level level = parseLogLevel(levelName);
494
495
if (Log.isEnabled(level)) {
496
Log.log(level, message, throwable);
497
}
498
}
499
500
private Logger.Level parseLogLevel(String levelName) {
501
try {
502
return Logger.Level.valueOf(levelName.toUpperCase());
503
} catch (IllegalArgumentException e) {
504
Log.warnf("Invalid log level '%s', defaulting to INFO", levelName);
505
return Logger.Level.INFO;
506
}
507
}
508
}
509
```
510
511
### Application Lifecycle Logging
512
513
```java
514
import io.quarkus.logging.Log;
515
import io.quarkus.runtime.StartupEvent;
516
import io.quarkus.runtime.ShutdownEvent;
517
import jakarta.enterprise.context.ApplicationScoped;
518
import jakarta.enterprise.event.Observes;
519
520
@ApplicationScoped
521
public class ApplicationLifecycleLogger {
522
523
void onStart(@Observes StartupEvent event) {
524
Log.info("=== Application Starting ===");
525
Log.infof("Java version: %s", System.getProperty("java.version"));
526
Log.infof("OS: %s %s", System.getProperty("os.name"), System.getProperty("os.version"));
527
Log.infof("Memory: Max=%dMB, Total=%dMB, Free=%dMB",
528
Runtime.getRuntime().maxMemory() / 1024 / 1024,
529
Runtime.getRuntime().totalMemory() / 1024 / 1024,
530
Runtime.getRuntime().freeMemory() / 1024 / 1024);
531
Log.info("=== Application Started ===");
532
}
533
534
void onStop(@Observes ShutdownEvent event) {
535
Log.info("=== Application Shutting Down ===");
536
537
if (event.isStandardShutdown()) {
538
Log.info("Standard shutdown initiated");
539
} else {
540
Log.warn("Non-standard shutdown (signal received)");
541
}
542
543
// Log final statistics
544
Runtime runtime = Runtime.getRuntime();
545
Log.infof("Final memory usage: Used=%dMB, Free=%dMB",
546
(runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024,
547
runtime.freeMemory() / 1024 / 1024);
548
549
Log.info("=== Application Shutdown Complete ===");
550
}
551
}
552
```
553
554
### Error Handling with Logging
555
556
```java
557
import io.quarkus.logging.Log;
558
import jakarta.enterprise.context.ApplicationScoped;
559
560
@ApplicationScoped
561
public class FileProcessor {
562
563
public void processFile(String filename) {
564
Log.infof("Starting file processing: %s", filename);
565
566
try {
567
validateFile(filename);
568
parseFile(filename);
569
processContent(filename);
570
Log.infof("Successfully processed file: %s", filename);
571
572
} catch (FileNotFoundException e) {
573
Log.errorf("File not found: %s", filename, e);
574
throw new ProcessingException("File not found: " + filename, e);
575
576
} catch (SecurityException e) {
577
Log.errorf("Access denied to file: %s", filename, e);
578
throw new ProcessingException("Access denied: " + filename, e);
579
580
} catch (IOException e) {
581
Log.errorf("IO error processing file: %s - %s", filename, e.getMessage(), e);
582
throw new ProcessingException("IO error: " + filename, e);
583
584
} catch (Exception e) {
585
Log.fatalf("Unexpected error processing file: %s", filename, e);
586
throw new ProcessingException("Unexpected error: " + filename, e);
587
}
588
}
589
590
private void validateFile(String filename) throws IOException {
591
Log.debugf("Validating file: %s", filename);
592
// Validation logic
593
}
594
595
private void parseFile(String filename) throws IOException {
596
Log.debugf("Parsing file: %s", filename);
597
// Parsing logic
598
}
599
600
private void processContent(String filename) {
601
Log.debugf("Processing content from file: %s", filename);
602
// Content processing logic
603
}
604
}
605
```
606
607
## Best Practices
608
609
### Performance Optimization
610
611
1. **Use level checking** for expensive log message construction:
612
```java
613
if (Log.isDebugEnabled()) {
614
Log.debug("Expensive operation result: " + expensiveCalculation());
615
}
616
```
617
618
2. **Use formatted logging** instead of string concatenation:
619
```java
620
// Good
621
Log.infof("User %s logged in at %s", username, timestamp);
622
623
// Avoid
624
Log.info("User " + username + " logged in at " + timestamp);
625
```
626
627
3. **Avoid logging in hot paths** unless necessary
628
629
### Log Level Guidelines
630
631
- **TRACE**: Very detailed information, typically only of interest when diagnosing problems
632
- **DEBUG**: Debug information, useful during development and troubleshooting
633
- **INFO**: Informational messages that highlight the progress of the application
634
- **WARN**: Potentially harmful situations that the application can handle
635
- **ERROR**: Error events but the application can continue running
636
- **FATAL**: Very severe error events that will likely lead to application termination
637
638
### Configuration
639
640
Configure logging levels in `application.properties`:
641
```properties
642
# Root logger level
643
quarkus.log.level=INFO
644
645
# Package-specific levels
646
quarkus.log.category."com.mycompany.service".level=DEBUG
647
quarkus.log.category."io.quarkus.hibernate".level=WARN
648
649
# Console logging format
650
quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n
651
652
# File logging
653
quarkus.log.file.enable=true
654
quarkus.log.file.path=application.log
655
quarkus.log.file.level=DEBUG
656
```