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

status-system.mddocs/

Status & Error Handling

Internal status reporting system for Log4j configuration issues, initialization problems, and runtime diagnostics. Essential for troubleshooting logging setup.

Capabilities

StatusLogger

Internal logger for Log4j status messages and diagnostics.

/**
 * Logger for Log4j internal status messages
 */
public class StatusLogger implements Logger {
    /** Get the status logger instance */
    public static StatusLogger getLogger();
    
    // Implements all Logger interface methods for internal status logging
    @Override
    public void trace(String message);
    @Override
    public void debug(String message);
    @Override
    public void info(String message);
    @Override
    public void warn(String message);
    @Override
    public void error(String message);
    @Override
    public void fatal(String message);
    
    // Parameterized logging for status messages
    @Override
    public void info(String message, Object... params);
    @Override
    public void warn(String message, Object... params);
    @Override
    public void error(String message, Object... params);
    
    // Level checking
    @Override
    public boolean isInfoEnabled();
    @Override
    public boolean isWarnEnabled();
    @Override
    public boolean isErrorEnabled();
    @Override
    public boolean isDebugEnabled();
    @Override
    public boolean isTraceEnabled();
    
    // Status-specific methods
    /** Add a status listener */
    public void registerListener(StatusListener listener);
    
    /** Remove a status listener */
    public void removeListener(StatusListener listener);
    
    /** Get all registered listeners */
    public Iterable<StatusListener> getListeners();
    
    /** Clear all listeners */
    public void reset();
    
    /** Get status data entries */
    public List<StatusData> getStatusData();
    
    /** Clear status data */
    public void clear();
    
    /** Set status logger level */
    public void setLevel(Level level);
}

Usage Examples:

public void demonstrateStatusLogger() {
    // Get status logger instance
    StatusLogger statusLogger = StatusLogger.getLogger();
    
    // Status logger is used internally by Log4j, but can be accessed for diagnostics
    statusLogger.info("Custom status message");
    statusLogger.warn("Configuration issue detected");
    statusLogger.error("Failed to initialize appender");
    
    // Check status logger state
    if (statusLogger.isDebugEnabled()) {
        statusLogger.debug("Debug-level status information");
    }
    
    // Get historical status data
    List<StatusData> statusHistory = statusLogger.getStatusData();
    for (StatusData data : statusHistory) {
        System.out.printf("[%s] %s - %s%n", 
                         data.getLevel(), 
                         new Date(data.getTimestamp()), 
                         data.getMessage().getFormattedMessage());
    }
    
    // Clear status history
    statusLogger.clear();
}

// Custom component that uses status logging
public class CustomAppender {
    private static final StatusLogger STATUS_LOGGER = StatusLogger.getLogger();
    
    public void initialize() {
        STATUS_LOGGER.info("Initializing custom appender");
        
        try {
            // Initialization logic
            setupResources();
            STATUS_LOGGER.info("Custom appender initialized successfully");
        } catch (Exception e) {
            STATUS_LOGGER.error("Failed to initialize custom appender", e);
            throw new RuntimeException("Appender initialization failed", e);
        }
    }
    
    public void append(LogEvent event) {
        try {
            // Append logic
            writeLogEvent(event);
        } catch (Exception e) {
            STATUS_LOGGER.error("Failed to append log event", e);
        }
    }
    
    private void setupResources() {
        // Resource setup
    }
    
    private void writeLogEvent(Object event) {
        // Write logic
    }
}

StatusListener Interface

Interface for listening to Log4j internal status messages.

/**
 * Interface for listening to Log4j status messages
 */
public interface StatusListener {
    /** 
     * Handle a status message
     * @param data Status data containing level, message, timestamp, etc.
     */
    void log(StatusData data);
    
    /** 
     * Get the minimum level this listener wants to receive
     * @return Minimum status level
     */
    Level getStatusLevel();
    
    /** 
     * Close/cleanup the listener
     */
    void close() throws IOException;
}

Usage Examples:

// Custom status listener implementation
public class CustomStatusListener implements StatusListener {
    private final Level minimumLevel;
    private final PrintWriter writer;
    
    public CustomStatusListener(Level minimumLevel, String filename) throws IOException {
        this.minimumLevel = minimumLevel;
        this.writer = new PrintWriter(new FileWriter(filename, true));
    }
    
    @Override
    public void log(StatusData data) {
        // Only log if level is appropriate
        if (data.getLevel().isMoreSpecificThan(minimumLevel)) {
            writer.printf("[%s] %s [%s] %s - %s%n",
                         new Date(data.getTimestamp()),
                         data.getLevel(),
                         data.getThreadName(),
                         "StatusLogger",
                         data.getMessage().getFormattedMessage());
            
            if (data.getThrowable() != null) {
                data.getThrowable().printStackTrace(writer);
            }
            
            writer.flush();
        }
    }
    
    @Override
    public Level getStatusLevel() {
        return minimumLevel;
    }
    
    @Override
    public void close() throws IOException {
        writer.close();
    }
}

// Database status listener
public class DatabaseStatusListener implements StatusListener {
    private final DataSource dataSource;
    private final Level minimumLevel;
    
    public DatabaseStatusListener(DataSource dataSource, Level minimumLevel) {
        this.dataSource = dataSource;
        this.minimumLevel = minimumLevel;
    }
    
    @Override
    public void log(StatusData data) {
        if (data.getLevel().isMoreSpecificThan(minimumLevel)) {
            try (Connection conn = dataSource.getConnection();
                 PreparedStatement stmt = conn.prepareStatement(
                     "INSERT INTO log4j_status (timestamp, level, thread_name, message, throwable) VALUES (?, ?, ?, ?, ?)")) {
                
                stmt.setTimestamp(1, new Timestamp(data.getTimestamp()));
                stmt.setString(2, data.getLevel().toString());
                stmt.setString(3, data.getThreadName());
                stmt.setString(4, data.getMessage().getFormattedMessage());
                
                if (data.getThrowable() != null) {
                    StringWriter sw = new StringWriter();
                    data.getThrowable().printStackTrace(new PrintWriter(sw));
                    stmt.setString(5, sw.toString());
                } else {
                    stmt.setNull(5, Types.VARCHAR);
                }
                
                stmt.executeUpdate();
                
            } catch (SQLException e) {
                // Can't use StatusLogger here to avoid infinite recursion
                System.err.println("Failed to log status to database: " + e.getMessage());
            }
        }
    }
    
    @Override
    public Level getStatusLevel() {
        return minimumLevel;
    }
    
    @Override
    public void close() {
        // Database connections are managed by DataSource
    }
}

// Register and use status listeners
public class StatusListenerManagement {
    
    public void setupStatusListeners() throws IOException {
        StatusLogger statusLogger = StatusLogger.getLogger();
        
        // File-based status listener
        CustomStatusListener fileListener = new CustomStatusListener(Level.WARN, "log4j-status.log");
        statusLogger.registerListener(fileListener);
        
        // Console status listener for errors only
        StatusListener consoleListener = new StatusListener() {
            @Override
            public void log(StatusData data) {
                if (data.getLevel().isMoreSpecificThan(Level.ERROR)) {
                    System.err.printf("LOG4J ERROR: %s%n", data.getMessage().getFormattedMessage());
                    if (data.getThrowable() != null) {
                        data.getThrowable().printStackTrace(System.err);
                    }
                }
            }
            
            @Override
            public Level getStatusLevel() {
                return Level.ERROR;
            }
            
            @Override
            public void close() {
                // Nothing to close
            }
        };
        statusLogger.registerListener(consoleListener);
        
        // Shutdown hook to clean up listeners
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                fileListener.close();
            } catch (IOException e) {
                System.err.println("Error closing status listener: " + e.getMessage());
            }
        }));
    }
}

StatusConsoleListener

Built-in status listener that outputs to console/System.err.

/**
 * Built-in status listener that outputs to console
 */
public class StatusConsoleListener implements StatusListener {
    /** Create listener with default level (ERROR) */
    public StatusConsoleListener();
    
    /** Create listener with specific level */
    public StatusConsoleListener(Level level);
    
    /** Create listener with specific level and target stream */
    public StatusConsoleListener(Level level, PrintStream stream);
    
    @Override
    public void log(StatusData data);
    
    @Override
    public Level getStatusLevel();
    
    @Override
    public void close();
    
    /** Set the target print stream */
    public void setTarget(PrintStream target);
    
    /** Get the target print stream */
    public PrintStream getTarget();
}

Usage Examples:

public void demonstrateStatusConsoleListener() {
    StatusLogger statusLogger = StatusLogger.getLogger();
    
    // Default console listener (ERROR level to System.err)
    StatusConsoleListener defaultConsole = new StatusConsoleListener();
    statusLogger.registerListener(defaultConsole);
    
    // Console listener with custom level
    StatusConsoleListener warnConsole = new StatusConsoleListener(Level.WARN);
    statusLogger.registerListener(warnConsole);
    
    // Console listener with custom stream
    StatusConsoleListener customConsole = new StatusConsoleListener(Level.INFO, System.out);
    statusLogger.registerListener(customConsole);
    
    // Configure listener dynamically
    customConsole.setTarget(System.err);
    
    // Test status logging
    statusLogger.info("This will appear on custom console listener");
    statusLogger.warn("This will appear on both warn and default listeners");
    statusLogger.error("This will appear on all listeners");
}

// Application startup with status console listener
public class ApplicationStartup {
    
    public static void main(String[] args) {
        // Set up status console listener early in application startup
        StatusLogger statusLogger = StatusLogger.getLogger();
        StatusConsoleListener consoleListener = new StatusConsoleListener(Level.WARN);
        statusLogger.registerListener(consoleListener);
        
        // Now any Log4j initialization issues will be visible
        Logger appLogger = LogManager.getLogger(ApplicationStartup.class);
        appLogger.info("Application starting...");
        
        // Application logic...
    }
}

StatusData Interface

Interface representing individual status message data.

/**
 * Interface representing status message data
 */
public interface StatusData {
    /** Get the timestamp when status was created */
    long getTimestamp();
    
    /** Get the status level */
    Level getLevel();
    
    /** Get the status message */
    Message getMessage();
    
    /** Get the thread name where status was created */
    String getThreadName();
    
    /** Get associated throwable if any */
    Throwable getThrowable();
    
    /** Get stack trace element where status was created */
    StackTraceElement getStackTraceElement();
}

Usage Examples:

public void demonstrateStatusData() {
    StatusLogger statusLogger = StatusLogger.getLogger();
    
    // Create a custom status listener to examine StatusData
    StatusListener dataExaminer = new StatusListener() {
        @Override
        public void log(StatusData data) {
            // Examine all aspects of status data
            System.out.println("=== Status Data Analysis ===");
            System.out.println("Timestamp: " + new Date(data.getTimestamp()));
            System.out.println("Level: " + data.getLevel());
            System.out.println("Thread: " + data.getThreadName());
            System.out.println("Message: " + data.getMessage().getFormattedMessage());
            
            if (data.getThrowable() != null) {
                System.out.println("Exception: " + data.getThrowable().getClass().getSimpleName());
                System.out.println("Exception Message: " + data.getThrowable().getMessage());
            }
            
            if (data.getStackTraceElement() != null) {
                StackTraceElement ste = data.getStackTraceElement();
                System.out.printf("Location: %s.%s(%s:%d)%n", 
                                ste.getClassName(), 
                                ste.getMethodName(), 
                                ste.getFileName(), 
                                ste.getLineNumber());
            }
            System.out.println("========================");
        }
        
        @Override
        public Level getStatusLevel() {
            return Level.DEBUG;
        }
        
        @Override
        public void close() {
            // Nothing to close
        }
    };
    
    statusLogger.registerListener(dataExaminer);
    
    // Generate some status messages to examine
    statusLogger.info("Status info message");
    statusLogger.warn("Status warning message");
    statusLogger.error("Status error message", new RuntimeException("test exception"));
}

// Status data aggregator
public class StatusDataAggregator implements StatusListener {
    private final Map<Level, AtomicInteger> levelCounts = new ConcurrentHashMap<>();
    private final Map<String, AtomicInteger> threadCounts = new ConcurrentHashMap<>();
    private final AtomicLong totalMessages = new AtomicLong();
    
    @Override
    public void log(StatusData data) {
        totalMessages.incrementAndGet();
        
        // Count by level
        levelCounts.computeIfAbsent(data.getLevel(), k -> new AtomicInteger()).incrementAndGet();
        
        // Count by thread
        threadCounts.computeIfAbsent(data.getThreadName(), k -> new AtomicInteger()).incrementAndGet();
    }
    
    @Override
    public Level getStatusLevel() {
        return Level.TRACE; // Capture all levels
    }
    
    @Override
    public void close() {
        // Print summary
        System.out.println("=== Status Data Summary ===");
        System.out.println("Total Messages: " + totalMessages.get());
        
        System.out.println("By Level:");
        levelCounts.forEach((level, count) -> 
            System.out.println("  " + level + ": " + count.get()));
        
        System.out.println("By Thread:");
        threadCounts.forEach((thread, count) -> 
            System.out.println("  " + thread + ": " + count.get()));
    }
    
    public Map<Level, Integer> getLevelCounts() {
        return levelCounts.entrySet().stream()
                .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    e -> e.getValue().get()));
    }
    
    public Map<String, Integer> getThreadCounts() {
        return threadCounts.entrySet().stream()
                .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    e -> e.getValue().get()));
    }
}

Common Status Scenarios

Typical status messages and how to handle them for troubleshooting.

// Common status scenarios and troubleshooting
public class StatusTroubleshooting {
    private static final StatusLogger STATUS_LOGGER = StatusLogger.getLogger();
    
    // Configuration file not found
    public void handleConfigurationIssues() {
        STATUS_LOGGER.error("Configuration file not found: {}", "log4j2.xml");
        STATUS_LOGGER.warn("Using default configuration");
        
        // Appender initialization failure
        STATUS_LOGGER.error("Failed to initialize FileAppender", new IOException("Permission denied"));
        
        // Plugin loading issues
        STATUS_LOGGER.warn("Plugin class not found: {}", "com.example.CustomPlugin");
    }
}

Usage Examples:

// Comprehensive status monitoring setup
public class StatusMonitoringSetup {
    
    public static void setupComprehensiveStatusMonitoring() {
        StatusLogger statusLogger = StatusLogger.getLogger();
        
        // Set status logger to capture all levels
        statusLogger.setLevel(Level.TRACE);
        
        // Multi-target status listener
        StatusListener multiListener = new StatusListener() {
            private final List<StatusListener> listeners = Arrays.asList(
                new StatusConsoleListener(Level.ERROR, System.err),
                createFileListener(),
                createMetricsListener()
            );
            
            @Override
            public void log(StatusData data) {
                listeners.forEach(listener -> {
                    try {
                        if (data.getLevel().isMoreSpecificThan(listener.getStatusLevel())) {
                            listener.log(data);
                        }
                    } catch (Exception e) {
                        System.err.println("Error in status listener: " + e.getMessage());
                    }
                });
            }
            
            @Override
            public Level getStatusLevel() {
                return Level.TRACE; // Accept all levels
            }
            
            @Override
            public void close() throws IOException {
                for (StatusListener listener : listeners) {
                    try {
                        listener.close();
                    } catch (IOException e) {
                        System.err.println("Error closing status listener: " + e.getMessage());
                    }
                }
            }
        };
        
        statusLogger.registerListener(multiListener);
        
        // Shutdown hook for cleanup
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                multiListener.close();
            } catch (IOException e) {
                System.err.println("Error during status listener cleanup: " + e.getMessage());
            }
        }));
    }
    
    private static StatusListener createFileListener() {
        try {
            return new CustomStatusListener(Level.WARN, "log4j-status.log");
        } catch (IOException e) {
            System.err.println("Failed to create file status listener: " + e.getMessage());
            return new StatusConsoleListener(Level.WARN);
        }
    }
    
    private static StatusListener createMetricsListener() {
        return new StatusDataAggregator();
    }
}

// Application with proper status monitoring
public class MonitoredApplication {
    
    public static void main(String[] args) {
        // Set up status monitoring before any Log4j usage
        StatusMonitoringSetup.setupComprehensiveStatusMonitoring();
        
        // Now initialize logging - any issues will be captured
        Logger logger = LogManager.getLogger(MonitoredApplication.class);
        
        logger.info("Application started with comprehensive status monitoring");
        
        // Application logic...
        
        // Check status at the end
        StatusLogger.getLogger().getStatusData().forEach(data -> {
            if (data.getLevel().isMoreSpecificThan(Level.WARN)) {
                System.out.println("Warning/Error during execution: " + 
                                 data.getMessage().getFormattedMessage());
            }
        });
    }
}

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