CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apache-logging-log4j--log4j-api

The logging API of the Log4j project providing a comprehensive and flexible logging framework for Java applications.

Pending
Overview
Eval results
Files

performance-features.mddocs/

Parameterized Logging & Performance

High-performance logging features including parameterized messages with {} placeholders, supplier-based lazy evaluation, and fluent LogBuilder API for complex log events.

Capabilities

Parameterized Messages

Efficient logging using {} placeholders that avoid string concatenation when logging is disabled.

public interface Logger {
    // Parameterized logging for all levels
    void trace(String message, Object... params);
    void debug(String message, Object... params);
    void info(String message, Object... params);
    void warn(String message, Object... params);
    void error(String message, Object... params);
    void fatal(String message, Object... params);
    
    // Parameterized with throwable
    void trace(String message, Throwable throwable, Object... params);
    void debug(String message, Throwable throwable, Object... params);
    void info(String message, Throwable throwable, Object... params);
    void warn(String message, Throwable throwable, Object... params);
    void error(String message, Throwable throwable, Object... params);
    void fatal(String message, Throwable throwable, Object... params);
    
    // Generic parameterized logging
    void log(Level level, String message, Object... params);
    void log(Level level, String message, Throwable throwable, Object... params);
}

Usage Examples:

private static final Logger logger = LogManager.getLogger();

public void demonstrateParameterizedLogging() {
    String username = "alice";
    int userId = 12345;
    long processingTime = 150;
    
    // Efficient - no string concatenation if INFO is disabled
    logger.info("User {} (ID: {}) logged in", username, userId);
    
    // Multiple parameters
    logger.debug("Processing completed for user {} in {}ms with {} items", 
                username, processingTime, getItemCount());
    
    // With exception
    try {
        processUser(userId);
    } catch (Exception e) {
        logger.error("Failed to process user {} ({})", username, userId, e);
    }
    
    // Arrays and objects are automatically formatted
    String[] roles = {"admin", "user"};
    logger.info("User {} has roles: {}", username, roles);
    
    // Complex objects use toString()
    UserProfile profile = getUserProfile(userId);
    logger.debug("Loaded profile: {}", profile);
}

// Performance comparison
public void performanceExample() {
    String data = "expensive data";
    
    // BAD - string concatenation always happens
    logger.debug("Processing data: " + expensiveCalculation() + " for user " + data);
    
    // GOOD - parameters only evaluated if DEBUG is enabled
    logger.debug("Processing data: {} for user {}", expensiveCalculation(), data);
    
    // EVEN BETTER - explicit level check for very expensive operations
    if (logger.isDebugEnabled()) {
        logger.debug("Very expensive debug: {}", veryExpensiveOperation());
    }
}

Supplier-Based Lazy Evaluation

Use suppliers for expensive message generation that should only occur when logging is enabled.

public interface Logger {
    // Supplier-based logging for all levels
    void trace(Supplier<?> messageSupplier);
    void debug(Supplier<?> messageSupplier);
    void info(Supplier<?> messageSupplier);
    void warn(Supplier<?> messageSupplier);
    void error(Supplier<?> messageSupplier);
    void fatal(Supplier<?> messageSupplier);
    
    // Supplier with throwable
    void trace(Supplier<?> messageSupplier, Throwable throwable);
    void debug(Supplier<?> messageSupplier, Throwable throwable);
    void info(Supplier<?> messageSupplier, Throwable throwable);
    void warn(Supplier<?> messageSupplier, Throwable throwable);
    void error(Supplier<?> messageSupplier, Throwable throwable);
    void fatal(Supplier<?> messageSupplier, Throwable throwable);
    
    // Generic supplier logging
    void log(Level level, Supplier<?> messageSupplier);
    void log(Level level, Supplier<?> messageSupplier, Throwable throwable);
}

/**
 * Functional interface for lazy message evaluation
 */
public interface Supplier<T> {
    T get();
}

/**
 * Supplier specifically for Message objects
 */
public interface MessageSupplier extends Supplier<Message> {
    Message get();
}

Usage Examples:

private static final Logger logger = LogManager.getLogger();

public void demonstrateSupplierLogging() {
    // Lambda supplier - only executed if DEBUG is enabled
    logger.debug(() -> "Expensive calculation result: " + performExpensiveCalculation());
    
    // Method reference supplier
    logger.trace(this::generateDetailedDiagnostics);
    
    // Complex supplier with multiple operations
    logger.debug(() -> {
        Map<String, Object> context = gatherContextData();
        return "Context: " + formatContext(context);
    });
    
    // Supplier with exception
    Exception ex = new RuntimeException("test");
    logger.error(() -> "Error processing request: " + getCurrentRequest(), ex);
    
    // MessageSupplier for custom messages
    logger.info(() -> new ObjectMessage(createStatusReport()));
}

private String performExpensiveCalculation() {
    // Simulate expensive operation
    return "calculated value";
}

private String generateDetailedDiagnostics() {
    // Complex diagnostic generation
    return "detailed diagnostics";
}

LogBuilder Fluent API

Fluent interface for constructing complex log events with multiple attributes.

/**
 * Fluent API for constructing log events
 */
public interface LogBuilder {
    /** Add a marker to the log event */
    LogBuilder withMarker(Marker marker);
    
    /** Add a throwable to the log event */
    LogBuilder withThrowable(Throwable throwable);
    
    /** Calculate and include caller location information */
    LogBuilder withLocation();
    
    /** Set explicit caller location */
    LogBuilder withLocation(StackTraceElement location);
    
    // Log methods with various parameter combinations
    void log(String message);
    void log(String message, Object p0);
    void log(String message, Object p0, Object p1);
    void log(String message, Object p0, Object p1, Object p2);
    // ... overloads for up to 10 parameters
    void log(String message, Object... params);
    void log(Message message);
    void log(Object message);
    void log(Supplier<Message> messageSupplier);
    
    /** No-operation LogBuilder for disabled levels */
    LogBuilder NOOP = new NoOpLogBuilder();
}

public interface Logger {
    /** Get LogBuilders for each level */
    LogBuilder atTrace();
    LogBuilder atDebug();
    LogBuilder atInfo();
    LogBuilder atWarn();
    LogBuilder atError();
    LogBuilder atFatal();
    LogBuilder atLevel(Level level);
}

Usage Examples:

private static final Logger logger = LogManager.getLogger();
private static final Marker SECURITY_MARKER = MarkerManager.getMarker("SECURITY");

public void demonstrateLogBuilder() {
    // Simple fluent logging
    logger.atInfo()
          .log("User logged in successfully");
    
    // Complex log event with multiple attributes
    logger.atError()
          .withMarker(SECURITY_MARKER)
          .withThrowable(exception)
          .withLocation()
          .log("Security violation detected for user {}", username);
    
    // Conditional building
    LogBuilder builder = logger.atDebug();
    if (includeLocation) {
        builder = builder.withLocation();
    }
    if (marker != null) {
        builder = builder.withMarker(marker);
    }
    builder.log("Debug message with conditional attributes");
    
    // Method chaining with different message types
    logger.atWarn()
          .withMarker(performanceMarker)
          .log(() -> new ObjectMessage(performanceMetrics));
    
    // Using with try-catch
    try {
        processRequest();
    } catch (Exception e) {
        logger.atError()
              .withThrowable(e)
              .withMarker(SECURITY_MARKER)
              .log("Request processing failed for user {}", getCurrentUser());
    }
}

// Performance note: LogBuilder for disabled levels returns NOOP
public void performanceNote() {
    // If TRACE is disabled, this returns LogBuilder.NOOP which ignores all operations
    LogBuilder builder = logger.atTrace(); // Returns NOOP if TRACE disabled
    builder.withMarker(marker)             // No-op
           .withLocation()                 // No-op
           .log("Expensive trace message"); // No-op
}

Flow Tracing

Methods for tracing method entry and exit points with automatic parameter capture.

public interface Logger {
    /** Trace method entry */
    void traceEntry();
    
    /** Trace method entry with parameters */
    void traceEntry(String format, Object... params);
    
    /** Trace method entry with message */
    void traceEntry(Message message);
    
    /** Trace method exit */
    void traceExit();
    
    /** Trace method exit with return value */
    <T> T traceExit(T result);
    
    /** Trace method exit with message */
    void traceExit(Message message);
    
    /** Trace method exit with entry message and return value */
    <T> T traceExit(Message message, T result);
    
    /** Log and return caught exception */
    <T extends Throwable> T catching(T throwable);
    
    /** Log and throw exception */
    <T extends Throwable> T throwing(T throwable);
}

Usage Examples:

private static final Logger logger = LogManager.getLogger();

public String processUser(String userId, String action) {
    // Trace entry with parameters
    logger.traceEntry("userId={}, action={}", userId, action);
    
    try {
        // Method implementation
        String result = performAction(userId, action);
        
        // Trace exit with return value
        return logger.traceExit(result);
        
    } catch (Exception e) {
        // Log and re-throw exception
        throw logger.throwing(e);
    }
}

public void handleException() {
    try {
        riskyOperation();
    } catch (Exception e) {
        // Log caught exception and continue
        logger.catching(e);
        // Handle exception...
    }
}

// Automatic method tracing pattern
public User findUser(Long id) {
    logger.traceEntry("id={}", id);
    
    try {
        User user = userRepository.findById(id);
        if (user == null) {
            throw new UserNotFoundException("User not found: " + id);
        }
        return logger.traceExit(user);
    } catch (Exception e) {
        throw logger.throwing(e);
    }
}

Level Checking Performance

Efficient level checking to avoid expensive operations when logging is disabled.

public interface Logger {
    // Level checking methods
    boolean isTraceEnabled();
    boolean isDebugEnabled();
    boolean isInfoEnabled();
    boolean isWarnEnabled();
    boolean isErrorEnabled();
    boolean isFatalEnabled();
    boolean isEnabled(Level level);
    
    // Level checking with markers
    boolean isTraceEnabled(Marker marker);
    boolean isDebugEnabled(Marker marker);
    boolean isInfoEnabled(Marker marker);
    boolean isWarnEnabled(Marker marker);
    boolean isErrorEnabled(Marker marker);
    boolean isFatalEnabled(Marker marker);
    boolean isEnabled(Level level, Marker marker);
}

Usage Examples:

private static final Logger logger = LogManager.getLogger();

public void efficientLogging() {
    // Guard expensive operations
    if (logger.isDebugEnabled()) {
        String expensiveData = generateExpensiveDebugData();
        logger.debug("Debug data: {}", expensiveData);
    }
    
    // Multiple expensive parameters
    if (logger.isTraceEnabled()) {
        logger.trace("Trace: {} {} {}", 
                    expensiveOp1(), expensiveOp2(), expensiveOp3());
    }
    
    // Level checking with markers
    Marker performanceMarker = MarkerManager.getMarker("PERFORMANCE");
    if (logger.isInfoEnabled(performanceMarker)) {
        logger.info(performanceMarker, "Performance metrics: {}", 
                   collectPerformanceMetrics());
    }
    
    // Dynamic level checking
    Level dynamicLevel = getDynamicLevel();
    if (logger.isEnabled(dynamicLevel)) {
        logger.log(dynamicLevel, "Dynamic message: {}", getDynamicData());
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-apache-logging-log4j--log4j-api

docs

core-logging.md

index.md

markers.md

message-system.md

performance-features.md

spi.md

status-system.md

thread-context.md

tile.json