SLF4J 2 provider that bridges SLF4J 2 logging calls to the Apache Log4j API
—
SLF4J 2.x fluent interface for building complex log events with structured data, lazy evaluation, and method chaining. This API enables modern logging patterns with key-value pairs, conditional logging, and deferred message construction.
Create fluent logging event builders for each log level.
/**
* Create a fluent logging event builder at TRACE level
* @return LoggingEventBuilder for TRACE level
*/
LoggingEventBuilder atTrace();
/**
* Create a fluent logging event builder at DEBUG level
* @return LoggingEventBuilder for DEBUG level
*/
LoggingEventBuilder atDebug();
/**
* Create a fluent logging event builder at INFO level
* @return LoggingEventBuilder for INFO level
*/
LoggingEventBuilder atInfo();
/**
* Create a fluent logging event builder at WARN level
* @return LoggingEventBuilder for WARN level
*/
LoggingEventBuilder atWarn();
/**
* Create a fluent logging event builder at ERROR level
* @return LoggingEventBuilder for ERROR level
*/
LoggingEventBuilder atError();Usage Examples:
// Create event builders
LoggingEventBuilder infoEvent = logger.atInfo();
LoggingEventBuilder errorEvent = logger.atError();
// Builders are only created if the level is enabled
if (logger.isDebugEnabled()) {
LoggingEventBuilder debugEvent = logger.atDebug();
}Configure basic properties of the log event.
/**
* Set the exception cause for this log event
* @param cause The throwable cause
* @return This event builder for chaining
*/
LoggingEventBuilder setCause(Throwable cause);
/**
* Add a marker to this log event
* @param marker The marker to add
* @return This event builder for chaining
*/
LoggingEventBuilder addMarker(Marker marker);
/**
* Set the log message
* @param message The message string
* @return This event builder for chaining
*/
LoggingEventBuilder setMessage(String message);
/**
* Set the log message using a supplier (lazy evaluation)
* @param messageSupplier Supplier that provides the message
* @return This event builder for chaining
*/
LoggingEventBuilder setMessage(Supplier<String> messageSupplier);Usage Examples:
// Basic event configuration
logger.atInfo()
.setMessage("User login successful")
.log();
// With marker and exception
Marker securityMarker = MarkerFactory.getMarker("SECURITY");
logger.atError()
.addMarker(securityMarker)
.setCause(exception)
.setMessage("Authentication failed")
.log();
// Lazy message evaluation
logger.atDebug()
.setMessage(() -> "Expensive computation result: " + computeExpensiveValue())
.log();Add arguments for parameterized messages with type safety.
/**
* Add an argument for parameterized message
* @param p The argument object
* @return This event builder for chaining
*/
LoggingEventBuilder addArgument(Object p);
/**
* Add a lazy-evaluated argument using a supplier
* @param objectSupplier Supplier that provides the argument
* @return This event builder for chaining
*/
LoggingEventBuilder addArgument(Supplier<?> objectSupplier);Usage Examples:
// Parameterized message with arguments
logger.atInfo()
.setMessage("User {} logged in from {}")
.addArgument(username)
.addArgument(ipAddress)
.log();
// Lazy argument evaluation
logger.atDebug()
.setMessage("Processing item {} with result {}")
.addArgument(itemId)
.addArgument(() -> performExpensiveCalculation(itemId))
.log();
// Multiple arguments
logger.atInfo()
.setMessage("Transfer of ${} from {} to {} completed")
.addArgument(amount)
.addArgument(fromAccount)
.addArgument(toAccount)
.log();Add structured data as key-value pairs for modern observability platforms.
/**
* Add a key-value pair to the log event
* @param key The key name
* @param value The value object
* @return This event builder for chaining
*/
LoggingEventBuilder addKeyValue(String key, Object value);
/**
* Add a key-value pair with lazy-evaluated value
* @param key The key name
* @param valueSupplier Supplier that provides the value
* @return This event builder for chaining
*/
LoggingEventBuilder addKeyValue(String key, Supplier<Object> valueSupplier);Usage Examples:
// Structured logging with key-value pairs
logger.atInfo()
.setMessage("API request processed")
.addKeyValue("userId", userId)
.addKeyValue("endpoint", "/api/users")
.addKeyValue("method", "GET")
.addKeyValue("responseTime", responseTime)
.addKeyValue("statusCode", 200)
.log();
// Lazy key-value evaluation
logger.atDebug()
.setMessage("Cache operation completed")
.addKeyValue("operation", "get")
.addKeyValue("key", cacheKey)
.addKeyValue("hit", () -> cache.containsKey(cacheKey))
.addKeyValue("size", () -> cache.size())
.log();
// Complex structured data
logger.atWarn()
.setMessage("Rate limit exceeded")
.addKeyValue("clientId", clientId)
.addKeyValue("requestsPerMinute", requestCount)
.addKeyValue("limit", rateLimitThreshold)
.addKeyValue("windowStart", windowStart.toString())
.addKeyValue("action", "throttle")
.log();Execute the configured log event.
/**
* Execute the log event with configured settings
*/
void log();
/**
* Set message and execute the log event
* @param message The log message
*/
void log(String message);
/**
* Set message with one argument and execute
* @param message The log message with placeholder
* @param arg The argument
*/
void log(String message, Object arg);
/**
* Set message with two arguments and execute
* @param message The log message with placeholders
* @param arg0 The first argument
* @param arg1 The second argument
*/
void log(String message, Object arg0, Object arg1);
/**
* Set message with multiple arguments and execute
* @param message The log message with placeholders
* @param args The arguments
*/
void log(String message, Object... args);
/**
* Set lazy message and execute
* @param messageSupplier Supplier that provides the message
*/
void log(Supplier<String> messageSupplier);Usage Examples:
// Build and execute separately
LoggingEventBuilder event = logger.atInfo()
.addKeyValue("operation", "user_creation")
.addKeyValue("userId", newUserId);
if (isSuccessful) {
event.setMessage("User created successfully").log();
} else {
event.setMessage("User creation failed").log();
}
// Set message and execute in one call
logger.atInfo()
.addKeyValue("requestId", requestId)
.addKeyValue("duration", duration)
.log("Request completed");
// Multiple arguments in log call
logger.atInfo()
.addKeyValue("operation", "data_sync")
.log("Synchronized {} records in {} ms", recordCount, duration);// Only log if specific conditions are met
if (logger.isDebugEnabled()) {
logger.atDebug()
.addKeyValue("threadName", Thread.currentThread().getName())
.addKeyValue("memoryUsage", Runtime.getRuntime().totalMemory())
.addKeyValue("activeConnections", connectionPool.getActiveCount())
.setMessage("System state snapshot")
.log();
}// Order processing event
logger.atInfo()
.addMarker(MarkerFactory.getMarker("BUSINESS_EVENT"))
.setMessage("Order processed")
.addKeyValue("orderId", order.getId())
.addKeyValue("customerId", order.getCustomerId())
.addKeyValue("amount", order.getTotalAmount())
.addKeyValue("currency", order.getCurrency())
.addKeyValue("items", order.getItems().size())
.addKeyValue("processingTime", processingTime)
.addKeyValue("paymentMethod", order.getPaymentMethod())
.log();// Rich error context
logger.atError()
.addMarker(MarkerFactory.getMarker("PAYMENT_ERROR"))
.setCause(paymentException)
.setMessage("Payment processing failed")
.addKeyValue("transactionId", transactionId)
.addKeyValue("amount", paymentAmount)
.addKeyValue("currency", currency)
.addKeyValue("paymentProvider", provider)
.addKeyValue("customerId", customerId)
.addKeyValue("retryAttempt", retryCount)
.addKeyValue("errorCode", paymentException.getErrorCode())
.log();// Performance event with timing
long startTime = System.currentTimeMillis();
try {
// perform operation
performDatabaseOperation();
logger.atInfo()
.addMarker(MarkerFactory.getMarker("PERFORMANCE"))
.setMessage("Database operation completed")
.addKeyValue("operation", "select")
.addKeyValue("table", "users")
.addKeyValue("duration", System.currentTimeMillis() - startTime)
.addKeyValue("recordCount", resultCount)
.log();
} catch (Exception e) {
logger.atError()
.addMarker(MarkerFactory.getMarker("PERFORMANCE"))
.setCause(e)
.setMessage("Database operation failed")
.addKeyValue("operation", "select")
.addKeyValue("table", "users")
.addKeyValue("duration", System.currentTimeMillis() - startTime)
.log();
}// Expensive operations only executed if logging level is enabled
logger.atDebug()
.setMessage(() -> "Complex state: " + generateComplexStateDescription())
.addKeyValue("timestamp", () -> Instant.now().toString())
.addKeyValue("threadDump", () -> generateThreadDump())
.addKeyValue("memoryStats", () -> getDetailedMemoryStats())
.log();For advanced framework integration, control the caller boundary for accurate location information.
/**
* Set the caller boundary for accurate location information
* @param fqcn Fully qualified class name of the caller boundary
*/
void setCallerBoundary(String fqcn);Usage Example:
import org.slf4j.Logger;
import org.slf4j.spi.CallerBoundaryAware;
import org.slf4j.spi.LoggingEventBuilder;
import java.util.Map;
// Framework wrapper example
public class LoggingWrapper {
private static final String FQCN = LoggingWrapper.class.getName();
private final Logger logger;
public void logBusinessEvent(String event, Map<String, Object> context) {
LoggingEventBuilder builder = logger.atInfo();
if (builder instanceof CallerBoundaryAware) {
((CallerBoundaryAware) builder).setCallerBoundary(FQCN);
}
builder.setMessage(event);
context.forEach(builder::addKeyValue);
builder.log();
}
}The structured key-value pairs integrate seamlessly with modern observability platforms:
// APM/Observability friendly logging
logger.atInfo()
.addKeyValue("trace.id", traceId)
.addKeyValue("span.id", spanId)
.addKeyValue("service.name", "user-service")
.addKeyValue("service.version", "1.2.3")
.addKeyValue("environment", "production")
.setMessage("Service operation completed")
.log();Install with Tessl CLI
npx tessl i tessl/maven-org-apache-logging-log4j--log4j-slf4j2-impl