0
# Logger Injection
1
2
CDI-based logger injection with support for custom logger names and automatic bean-specific logger creation. Quarkus Arc provides seamless integration with JBoss Logging through CDI qualifiers.
3
4
## Capabilities
5
6
### LoggerName Qualifier
7
8
CDI qualifier annotation for injecting loggers with custom names.
9
10
```java { .api }
11
/**
12
* CDI qualifier for injecting loggers with custom names.
13
*/
14
@Qualifier
15
@Retention(RetentionPolicy.RUNTIME)
16
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
17
public @interface LoggerName {
18
/**
19
* The logger name must not be empty.
20
* @return the logger name
21
*/
22
@Nonbinding
23
String value();
24
25
/**
26
* Supports inline instantiation of this qualifier.
27
*/
28
public static final class Literal extends AnnotationLiteral<LoggerName> implements LoggerName {
29
private static final long serialVersionUID = 1L;
30
private final String value;
31
32
public Literal(String value);
33
public String value();
34
}
35
}
36
```
37
38
**Usage Examples:**
39
40
```java
41
import jakarta.enterprise.context.ApplicationScoped;
42
import jakarta.inject.Inject;
43
import io.quarkus.arc.log.LoggerName;
44
import org.jboss.logging.Logger;
45
46
@ApplicationScoped
47
public class UserService {
48
49
// Default logger - uses the class name as logger name
50
@Inject
51
Logger defaultLogger;
52
53
// Custom named logger
54
@Inject
55
@LoggerName("user.operations")
56
Logger operationsLogger;
57
58
// Another custom logger for security events
59
@Inject
60
@LoggerName("security.audit")
61
Logger securityLogger;
62
63
public void createUser(String username) {
64
defaultLogger.info("Creating user: " + username);
65
operationsLogger.debug("User creation operation started");
66
securityLogger.info("New user account created: " + username);
67
}
68
69
public void deleteUser(String username) {
70
defaultLogger.warn("Deleting user: " + username);
71
securityLogger.warn("User account deleted: " + username);
72
}
73
}
74
```
75
76
### Method Parameter Injection
77
78
Inject loggers as method parameters in producer methods or other CDI methods.
79
80
```java
81
import jakarta.enterprise.context.ApplicationScoped;
82
import jakarta.enterprise.inject.Produces;
83
import io.quarkus.arc.log.LoggerName;
84
import org.jboss.logging.Logger;
85
86
@ApplicationScoped
87
public class ServiceFactory {
88
89
@Produces
90
@ApplicationScoped
91
public DatabaseService createDatabaseService(
92
@LoggerName("database.operations") Logger dbLogger) {
93
return new DatabaseService(dbLogger);
94
}
95
96
@Produces
97
@ApplicationScoped
98
public CacheService createCacheService(
99
@LoggerName("cache.operations") Logger cacheLogger) {
100
return new CacheService(cacheLogger);
101
}
102
}
103
104
class DatabaseService {
105
private final Logger logger;
106
107
public DatabaseService(Logger logger) {
108
this.logger = logger;
109
}
110
111
public void performQuery(String sql) {
112
logger.debug("Executing query: " + sql);
113
// Database operation
114
logger.info("Query executed successfully");
115
}
116
}
117
118
class CacheService {
119
private final Logger logger;
120
121
public CacheService(Logger logger) {
122
this.logger = logger;
123
}
124
125
public void put(String key, Object value) {
126
logger.trace("Caching value for key: " + key);
127
// Cache operation
128
}
129
}
130
```
131
132
### Programmatic Logger Creation
133
134
Use the LoggerName.Literal class for programmatic logger creation.
135
136
```java
137
import jakarta.enterprise.context.ApplicationScoped;
138
import jakarta.inject.Inject;
139
import jakarta.enterprise.inject.Instance;
140
import io.quarkus.arc.log.LoggerName;
141
import org.jboss.logging.Logger;
142
143
@ApplicationScoped
144
public class DynamicLoggingService {
145
146
@Inject
147
Instance<Logger> loggerInstance;
148
149
public void logWithDynamicName(String loggerName, String message) {
150
// Create logger with dynamic name
151
Logger logger = loggerInstance
152
.select(new LoggerName.Literal(loggerName))
153
.get();
154
155
logger.info(message);
156
}
157
158
public void processModules(String[] modules) {
159
for (String module : modules) {
160
Logger moduleLogger = loggerInstance
161
.select(new LoggerName.Literal("module." + module))
162
.get();
163
164
moduleLogger.info("Processing module: " + module);
165
}
166
}
167
}
168
```
169
170
### Logger Categories and Hierarchies
171
172
Organize loggers using hierarchical naming patterns.
173
174
```java
175
import jakarta.enterprise.context.ApplicationScoped;
176
import jakarta.inject.Inject;
177
import io.quarkus.arc.log.LoggerName;
178
import org.jboss.logging.Logger;
179
180
@ApplicationScoped
181
public class OrderProcessingService {
182
183
// Main service logger
184
@Inject
185
@LoggerName("orders")
186
Logger ordersLogger;
187
188
// Validation subsystem
189
@Inject
190
@LoggerName("orders.validation")
191
Logger validationLogger;
192
193
// Payment subsystem
194
@Inject
195
@LoggerName("orders.payment")
196
Logger paymentLogger;
197
198
// Inventory subsystem
199
@Inject
200
@LoggerName("orders.inventory")
201
Logger inventoryLogger;
202
203
// Notification subsystem
204
@Inject
205
@LoggerName("orders.notifications")
206
Logger notificationLogger;
207
208
public void processOrder(Order order) {
209
ordersLogger.info("Processing order: " + order.getId());
210
211
try {
212
validateOrder(order);
213
processPayment(order);
214
updateInventory(order);
215
sendNotifications(order);
216
217
ordersLogger.info("Order processing completed: " + order.getId());
218
} catch (Exception e) {
219
ordersLogger.error("Order processing failed: " + order.getId(), e);
220
throw e;
221
}
222
}
223
224
private void validateOrder(Order order) {
225
validationLogger.debug("Validating order: " + order.getId());
226
// Validation logic
227
validationLogger.info("Order validation passed: " + order.getId());
228
}
229
230
private void processPayment(Order order) {
231
paymentLogger.debug("Processing payment for order: " + order.getId());
232
// Payment logic
233
paymentLogger.info("Payment processed: " + order.getId());
234
}
235
236
private void updateInventory(Order order) {
237
inventoryLogger.debug("Updating inventory for order: " + order.getId());
238
// Inventory logic
239
inventoryLogger.info("Inventory updated: " + order.getId());
240
}
241
242
private void sendNotifications(Order order) {
243
notificationLogger.debug("Sending notifications for order: " + order.getId());
244
// Notification logic
245
notificationLogger.info("Notifications sent: " + order.getId());
246
}
247
}
248
249
class Order {
250
private String id;
251
// Other order fields
252
253
public String getId() { return id; }
254
public void setId(String id) { this.id = id; }
255
}
256
```
257
258
### Producer Method Integration
259
260
Create loggers in producer methods for dependency injection into non-CDI objects.
261
262
```java
263
import jakarta.enterprise.context.ApplicationScoped;
264
import jakarta.enterprise.inject.Produces;
265
import jakarta.enterprise.inject.spi.InjectionPoint;
266
import io.quarkus.arc.log.LoggerName;
267
import org.jboss.logging.Logger;
268
269
@ApplicationScoped
270
public class LoggerProducer {
271
272
@Produces
273
public Logger createClassLogger(InjectionPoint injectionPoint) {
274
// Create logger based on the injection point's class
275
return Logger.getLogger(injectionPoint.getMember().getDeclaringClass());
276
}
277
278
@Produces
279
@LoggerName("custom")
280
public Logger createCustomLogger() {
281
return Logger.getLogger("custom.application.logger");
282
}
283
}
284
285
// Usage in services
286
@ApplicationScoped
287
public class ProductService {
288
289
@Inject
290
Logger logger; // Will be created using class name
291
292
@Inject
293
@LoggerName("custom")
294
Logger customLogger;
295
296
public void manageProduct(String productId) {
297
logger.info("Managing product: " + productId);
298
customLogger.debug("Custom logging for product: " + productId);
299
}
300
}
301
```
302
303
### Integration with Configuration
304
305
Combine logger injection with configuration for dynamic logging behavior.
306
307
```java
308
import jakarta.enterprise.context.ApplicationScoped;
309
import jakarta.inject.Inject;
310
import org.eclipse.microprofile.config.inject.ConfigProperty;
311
import io.quarkus.arc.log.LoggerName;
312
import org.jboss.logging.Logger;
313
314
@ApplicationScoped
315
public class ConfigurableLoggingService {
316
317
@Inject
318
@LoggerName("app.performance")
319
Logger performanceLogger;
320
321
@Inject
322
@LoggerName("app.business")
323
Logger businessLogger;
324
325
@ConfigProperty(name = "logging.performance.enabled", defaultValue = "false")
326
boolean performanceLoggingEnabled;
327
328
@ConfigProperty(name = "logging.detailed", defaultValue = "false")
329
boolean detailedLogging;
330
331
public void performBusinessOperation(String operation) {
332
long startTime = System.currentTimeMillis();
333
334
if (detailedLogging) {
335
businessLogger.info("Starting business operation: " + operation);
336
}
337
338
try {
339
// Business logic here
340
Thread.sleep(100); // Simulate work
341
342
businessLogger.info("Completed business operation: " + operation);
343
} catch (Exception e) {
344
businessLogger.error("Business operation failed: " + operation, e);
345
throw new RuntimeException(e);
346
} finally {
347
if (performanceLoggingEnabled) {
348
long duration = System.currentTimeMillis() - startTime;
349
performanceLogger.info("Operation '" + operation + "' took " + duration + "ms");
350
}
351
}
352
}
353
}
354
```
355
356
## Logger Configuration
357
358
Configure logger levels and output through standard Quarkus logging configuration:
359
360
### Application Properties
361
362
```properties
363
# Root logger configuration
364
quarkus.log.level=INFO
365
quarkus.log.console.enable=true
366
367
# Custom logger categories
368
quarkus.log.category."user.operations".level=DEBUG
369
quarkus.log.category."security.audit".level=INFO
370
quarkus.log.category."orders".level=INFO
371
quarkus.log.category."orders.validation".level=DEBUG
372
quarkus.log.category."orders.payment".level=WARN
373
374
# Performance logging
375
quarkus.log.category."app.performance".level=INFO
376
377
# File output for specific categories
378
quarkus.log.category."security.audit".handlers=SECURITY_FILE
379
quarkus.log.handler.file.SECURITY_FILE.enable=true
380
quarkus.log.handler.file.SECURITY_FILE.path=security-audit.log
381
quarkus.log.handler.file.SECURITY_FILE.format=%d{yyyy-MM-dd HH:mm:ss} %-5p [%c] %s%e%n
382
```
383
384
### Runtime Configuration
385
386
```properties
387
# Enable/disable performance logging at runtime
388
logging.performance.enabled=true
389
logging.detailed=false
390
```
391
392
## Best Practices
393
394
### Naming Conventions
395
396
```java
397
// Use hierarchical naming for related loggers
398
@LoggerName("app.module.component") // Good
399
@LoggerName("RandomLoggerName") // Avoid
400
401
// Examples of good logger names
402
@LoggerName("security.authentication")
403
@LoggerName("performance.database")
404
@LoggerName("integration.external-api")
405
@LoggerName("business.order-processing")
406
```
407
408
### Logger Organization
409
410
```java
411
@ApplicationScoped
412
public class WellOrganizedService {
413
414
// Main service logger
415
@Inject
416
Logger serviceLogger;
417
418
// Specialized loggers for different concerns
419
@Inject
420
@LoggerName("performance.metrics")
421
Logger metricsLogger;
422
423
@Inject
424
@LoggerName("security.access")
425
Logger securityLogger;
426
427
@Inject
428
@LoggerName("integration.third-party")
429
Logger integrationLogger;
430
}
431
```
432
433
### Error Handling
434
435
```java
436
@ApplicationScoped
437
public class ErrorHandlingExample {
438
439
@Inject
440
@LoggerName("errors.business")
441
Logger errorLogger;
442
443
public void handleBusinessOperation() {
444
try {
445
// Business logic
446
} catch (BusinessException e) {
447
errorLogger.warn("Business rule violation", e);
448
// Handle gracefully
449
} catch (Exception e) {
450
errorLogger.error("Unexpected error in business operation", e);
451
throw e;
452
}
453
}
454
}
455
```