CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-arc

Build time CDI dependency injection framework for Quarkus applications with conditional bean support and context management

Pending
Overview
Eval results
Files

logger-injection.mddocs/

Logger Injection

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.

Capabilities

LoggerName Qualifier

CDI qualifier annotation for injecting loggers with custom names.

/**
 * CDI qualifier for injecting loggers with custom names.
 */
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
public @interface LoggerName {
    /**
     * The logger name must not be empty.
     * @return the logger name
     */
    @Nonbinding
    String value();

    /**
     * Supports inline instantiation of this qualifier.
     */
    public static final class Literal extends AnnotationLiteral<LoggerName> implements LoggerName {
        private static final long serialVersionUID = 1L;
        private final String value;

        public Literal(String value);
        public String value();
    }
}

Usage Examples:

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import io.quarkus.arc.log.LoggerName;
import org.jboss.logging.Logger;

@ApplicationScoped
public class UserService {
    
    // Default logger - uses the class name as logger name
    @Inject
    Logger defaultLogger;
    
    // Custom named logger
    @Inject
    @LoggerName("user.operations")
    Logger operationsLogger;
    
    // Another custom logger for security events
    @Inject
    @LoggerName("security.audit")
    Logger securityLogger;
    
    public void createUser(String username) {
        defaultLogger.info("Creating user: " + username);
        operationsLogger.debug("User creation operation started");
        securityLogger.info("New user account created: " + username);
    }
    
    public void deleteUser(String username) {
        defaultLogger.warn("Deleting user: " + username);
        securityLogger.warn("User account deleted: " + username);
    }
}

Method Parameter Injection

Inject loggers as method parameters in producer methods or other CDI methods.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import io.quarkus.arc.log.LoggerName;
import org.jboss.logging.Logger;

@ApplicationScoped
public class ServiceFactory {
    
    @Produces
    @ApplicationScoped
    public DatabaseService createDatabaseService(
            @LoggerName("database.operations") Logger dbLogger) {
        return new DatabaseService(dbLogger);
    }
    
    @Produces
    @ApplicationScoped
    public CacheService createCacheService(
            @LoggerName("cache.operations") Logger cacheLogger) {
        return new CacheService(cacheLogger);
    }
}

class DatabaseService {
    private final Logger logger;
    
    public DatabaseService(Logger logger) {
        this.logger = logger;
    }
    
    public void performQuery(String sql) {
        logger.debug("Executing query: " + sql);
        // Database operation
        logger.info("Query executed successfully");
    }
}

class CacheService {
    private final Logger logger;
    
    public CacheService(Logger logger) {
        this.logger = logger;
    }
    
    public void put(String key, Object value) {
        logger.trace("Caching value for key: " + key);
        // Cache operation
    }
}

Programmatic Logger Creation

Use the LoggerName.Literal class for programmatic logger creation.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.enterprise.inject.Instance;
import io.quarkus.arc.log.LoggerName;
import org.jboss.logging.Logger;

@ApplicationScoped
public class DynamicLoggingService {
    
    @Inject
    Instance<Logger> loggerInstance;
    
    public void logWithDynamicName(String loggerName, String message) {
        // Create logger with dynamic name
        Logger logger = loggerInstance
                .select(new LoggerName.Literal(loggerName))
                .get();
        
        logger.info(message);
    }
    
    public void processModules(String[] modules) {
        for (String module : modules) {
            Logger moduleLogger = loggerInstance
                    .select(new LoggerName.Literal("module." + module))
                    .get();
            
            moduleLogger.info("Processing module: " + module);
        }
    }
}

Logger Categories and Hierarchies

Organize loggers using hierarchical naming patterns.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import io.quarkus.arc.log.LoggerName;
import org.jboss.logging.Logger;

@ApplicationScoped
public class OrderProcessingService {
    
    // Main service logger
    @Inject
    @LoggerName("orders")
    Logger ordersLogger;
    
    // Validation subsystem
    @Inject
    @LoggerName("orders.validation")
    Logger validationLogger;
    
    // Payment subsystem
    @Inject
    @LoggerName("orders.payment")
    Logger paymentLogger;
    
    // Inventory subsystem
    @Inject
    @LoggerName("orders.inventory")
    Logger inventoryLogger;
    
    // Notification subsystem
    @Inject
    @LoggerName("orders.notifications")
    Logger notificationLogger;
    
    public void processOrder(Order order) {
        ordersLogger.info("Processing order: " + order.getId());
        
        try {
            validateOrder(order);
            processPayment(order);
            updateInventory(order);
            sendNotifications(order);
            
            ordersLogger.info("Order processing completed: " + order.getId());
        } catch (Exception e) {
            ordersLogger.error("Order processing failed: " + order.getId(), e);
            throw e;
        }
    }
    
    private void validateOrder(Order order) {
        validationLogger.debug("Validating order: " + order.getId());
        // Validation logic
        validationLogger.info("Order validation passed: " + order.getId());
    }
    
    private void processPayment(Order order) {
        paymentLogger.debug("Processing payment for order: " + order.getId());
        // Payment logic
        paymentLogger.info("Payment processed: " + order.getId());
    }
    
    private void updateInventory(Order order) {
        inventoryLogger.debug("Updating inventory for order: " + order.getId());
        // Inventory logic
        inventoryLogger.info("Inventory updated: " + order.getId());
    }
    
    private void sendNotifications(Order order) {
        notificationLogger.debug("Sending notifications for order: " + order.getId());
        // Notification logic
        notificationLogger.info("Notifications sent: " + order.getId());
    }
}

class Order {
    private String id;
    // Other order fields
    
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
}

Producer Method Integration

Create loggers in producer methods for dependency injection into non-CDI objects.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.enterprise.inject.spi.InjectionPoint;
import io.quarkus.arc.log.LoggerName;
import org.jboss.logging.Logger;

@ApplicationScoped
public class LoggerProducer {
    
    @Produces
    public Logger createClassLogger(InjectionPoint injectionPoint) {
        // Create logger based on the injection point's class
        return Logger.getLogger(injectionPoint.getMember().getDeclaringClass());
    }
    
    @Produces
    @LoggerName("custom")
    public Logger createCustomLogger() {
        return Logger.getLogger("custom.application.logger");
    }
}

// Usage in services
@ApplicationScoped
public class ProductService {
    
    @Inject
    Logger logger; // Will be created using class name
    
    @Inject
    @LoggerName("custom") 
    Logger customLogger;
    
    public void manageProduct(String productId) {
        logger.info("Managing product: " + productId);
        customLogger.debug("Custom logging for product: " + productId);
    }
}

Integration with Configuration

Combine logger injection with configuration for dynamic logging behavior.

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import io.quarkus.arc.log.LoggerName;
import org.jboss.logging.Logger;

@ApplicationScoped
public class ConfigurableLoggingService {
    
    @Inject
    @LoggerName("app.performance")
    Logger performanceLogger;
    
    @Inject
    @LoggerName("app.business")
    Logger businessLogger;
    
    @ConfigProperty(name = "logging.performance.enabled", defaultValue = "false")
    boolean performanceLoggingEnabled;
    
    @ConfigProperty(name = "logging.detailed", defaultValue = "false")
    boolean detailedLogging;
    
    public void performBusinessOperation(String operation) {
        long startTime = System.currentTimeMillis();
        
        if (detailedLogging) {
            businessLogger.info("Starting business operation: " + operation);
        }
        
        try {
            // Business logic here
            Thread.sleep(100); // Simulate work
            
            businessLogger.info("Completed business operation: " + operation);
        } catch (Exception e) {
            businessLogger.error("Business operation failed: " + operation, e);
            throw new RuntimeException(e);
        } finally {
            if (performanceLoggingEnabled) {
                long duration = System.currentTimeMillis() - startTime;
                performanceLogger.info("Operation '" + operation + "' took " + duration + "ms");
            }
        }
    }
}

Logger Configuration

Configure logger levels and output through standard Quarkus logging configuration:

Application Properties

# Root logger configuration
quarkus.log.level=INFO
quarkus.log.console.enable=true

# Custom logger categories
quarkus.log.category."user.operations".level=DEBUG
quarkus.log.category."security.audit".level=INFO
quarkus.log.category."orders".level=INFO
quarkus.log.category."orders.validation".level=DEBUG
quarkus.log.category."orders.payment".level=WARN

# Performance logging
quarkus.log.category."app.performance".level=INFO

# File output for specific categories
quarkus.log.category."security.audit".handlers=SECURITY_FILE
quarkus.log.handler.file.SECURITY_FILE.enable=true
quarkus.log.handler.file.SECURITY_FILE.path=security-audit.log
quarkus.log.handler.file.SECURITY_FILE.format=%d{yyyy-MM-dd HH:mm:ss} %-5p [%c] %s%e%n

Runtime Configuration

# Enable/disable performance logging at runtime
logging.performance.enabled=true
logging.detailed=false

Best Practices

Naming Conventions

// Use hierarchical naming for related loggers
@LoggerName("app.module.component")     // Good
@LoggerName("RandomLoggerName")         // Avoid

// Examples of good logger names
@LoggerName("security.authentication")
@LoggerName("performance.database")  
@LoggerName("integration.external-api")
@LoggerName("business.order-processing")

Logger Organization

@ApplicationScoped
public class WellOrganizedService {
    
    // Main service logger
    @Inject
    Logger serviceLogger;
    
    // Specialized loggers for different concerns
    @Inject
    @LoggerName("performance.metrics")
    Logger metricsLogger;
    
    @Inject
    @LoggerName("security.access")
    Logger securityLogger;
    
    @Inject
    @LoggerName("integration.third-party")
    Logger integrationLogger;
}

Error Handling

@ApplicationScoped
public class ErrorHandlingExample {
    
    @Inject
    @LoggerName("errors.business")
    Logger errorLogger;
    
    public void handleBusinessOperation() {
        try {
            // Business logic
        } catch (BusinessException e) {
            errorLogger.warn("Business rule violation", e);
            // Handle gracefully
        } catch (Exception e) {
            errorLogger.error("Unexpected error in business operation", e);
            throw e;
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-quarkus--quarkus-arc

docs

bean-container.md

bean-invocation.md

build-profiles.md

build-properties.md

index.md

interceptor-integration.md

logger-injection.md

runtime-lookup.md

tile.json