CtrlK
BlogDocsLog inGet started
Tessl Logo

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

The Apache Log4j 1.x Compatibility API providing a bridge to Log4j 2.x implementations

Pending
Overview
Eval results
Files

spi.mddocs/

SPI and Extension Points

The Service Provider Interface (SPI) classes provide extension points for custom functionality including LoggerRepository, ErrorHandler, Filter, and other pluggable components for advanced logging system customization.

Core SPI Interfaces

LoggerRepository Interface

public interface LoggerRepository {
    // Logger management
    Logger getLogger(String name);
    Logger getLogger(String name, LoggerFactory factory);
    Logger getRootLogger();
    Logger exists(String name);
    
    // Repository state
    Enumeration getCurrentLoggers();
    Enumeration getCurrentCategories();
    
    // Configuration
    void shutdown();
    void resetConfiguration();
    boolean isDisabled(int level);
    void setThreshold(Level level);
    void setThreshold(String val);
    Level getThreshold();
    
    // Error handling
    void emitNoAppenderWarning(Category cat);
    
    // Hierarchy management  
    void setLoggerFactory(LoggerFactory factory);
    LoggerFactory getLoggerFactory();
}

Parameters:

  • name - String logger name
  • factory - LoggerFactory for logger creation
  • level - Integer level to check or Level to set
  • val - String threshold value
  • cat - Category for warning

Returns:

  • Logger instances
  • Enumeration of loggers/categories
  • boolean for disabled checks
  • Level current threshold
  • LoggerFactory current factory

LoggerFactory Interface

public interface LoggerFactory {
    // Create logger instance
    Logger makeNewLoggerInstance(String name);
}

Parameters:

  • name - String name for the new logger

Returns:

  • Logger newly created logger instance

ErrorHandler Interface

public interface ErrorHandler {
    // Error handling methods
    void error(String message);
    void error(String message, Exception ex, int errorCode);
    void error(String message, Exception ex, int errorCode, LoggingEvent event);
    
    // Appender association
    void setAppender(Appender appender);
    void setBackupAppender(Appender appender);
    void setLogger(Logger logger);
    
    // Activation
    void activateOptions();
}

Parameters:

  • message - String error message
  • ex - Exception that occurred
  • errorCode - Integer error code
  • event - LoggingEvent being processed
  • appender - Appender for association
  • logger - Logger for association

Filter Interface

public interface Filter {
    // Filter results
    int DENY = -1;
    int NEUTRAL = 0;
    int ACCEPT = 1;
    
    // Decision method
    int decide(LoggingEvent event);
    
    // Filter chaining
    Filter getNext();
    void setNext(Filter next);
}

Parameters:

  • event - LoggingEvent to evaluate
  • next - Filter next filter in chain

Returns:

  • int decision (DENY, NEUTRAL, or ACCEPT)
  • Filter next filter in chain

Logger SPI Classes

DefaultCategoryFactory

public class DefaultCategoryFactory implements LoggerFactory {
    // Constructor
    public DefaultCategoryFactory();
    
    // Factory method implementation
    @Override
    public Logger makeNewLoggerInstance(String name);
}

Parameters:

  • name - String logger name

Returns:

  • Logger new logger instance

Hierarchy

public class Hierarchy implements LoggerRepository {
    // Constructor
    public Hierarchy(Logger root);
    
    // Logger operations
    @Override
    public Logger getLogger(String name);
    @Override
    public Logger getLogger(String name, LoggerFactory factory);
    @Override
    public Logger getRootLogger();
    @Override
    public Logger exists(String name);
    
    // Enumeration
    @Override
    public Enumeration getCurrentLoggers();
    @Override
    public Enumeration getCurrentCategories();
    
    // Configuration
    @Override
    public void shutdown();
    @Override
    public void resetConfiguration();
    @Override
    public boolean isDisabled(int level);
    @Override
    public void setThreshold(Level level);
    @Override
    public Level getThreshold();
    
    // Factory management
    @Override
    public void setLoggerFactory(LoggerFactory factory);
    @Override
    public LoggerFactory getLoggerFactory();
    
    // Hierarchy-specific methods
    public void clear();
    public void overrideAsNeeded(String override);
}

Parameters:

  • root - Logger root logger for hierarchy
  • name - String logger name
  • factory - LoggerFactory for logger creation
  • level - Level or integer threshold
  • override - String override configuration

Returns:

  • Logger, Enumeration, Level, LoggerFactory as appropriate
  • boolean for threshold checks

Error Handler Implementations

OnlyOnceErrorHandler

public class OnlyOnceErrorHandler implements ErrorHandler {
    // Constants
    public static final String WARN_PREFIX = "log4j warning: ";
    public static final String ERROR_PREFIX = "log4j error: ";
    
    // Constructor
    public OnlyOnceErrorHandler();
    
    // Error handling
    @Override
    public void error(String message);
    @Override
    public void error(String message, Exception ex, int errorCode);
    @Override
    public void error(String message, Exception ex, int errorCode, LoggingEvent event);
    
    // Configuration
    @Override
    public void setAppender(Appender appender);
    @Override
    public void setBackupAppender(Appender appender);
    @Override
    public void setLogger(Logger logger);
    @Override
    public void activateOptions();
}

Parameters:

  • message - String error message
  • ex - Exception that occurred
  • errorCode - Integer error code
  • event - LoggingEvent being processed
  • appender - Appender for configuration
  • logger - Logger for configuration

Filter Implementations

LevelRangeFilter

public class LevelRangeFilter implements Filter {
    // Configuration
    public void setLevelMin(Level levelMin);
    public Level getLevelMin();
    public void setLevelMax(Level levelMax);
    public Level getLevelMax();
    public void setAcceptOnMatch(boolean acceptOnMatch);
    public boolean getAcceptOnMatch();
    
    // Filter implementation
    @Override
    public int decide(LoggingEvent event);
    @Override
    public Filter getNext();
    @Override
    public void setNext(Filter next);
    
    // Lifecycle
    public void activateOptions();
}

Parameters:

  • levelMin - Level minimum level in range
  • levelMax - Level maximum level in range
  • acceptOnMatch - Boolean accept or deny on match
  • event - LoggingEvent to evaluate
  • next - Filter next filter in chain

Returns:

  • Level min/max levels
  • boolean accept on match setting
  • int filter decision
  • Filter next filter

LevelMatchFilter

public class LevelMatchFilter implements Filter {
    // Configuration
    public void setLevel(Level level);
    public Level getLevel();
    public void setAcceptOnMatch(boolean acceptOnMatch);
    public boolean getAcceptOnMatch();
    
    // Filter implementation
    @Override
    public int decide(LoggingEvent event);
    @Override
    public Filter getNext();
    @Override
    public void setNext(Filter next);
    
    // Lifecycle
    public void activateOptions();
}

Parameters:

  • level - Level to match against
  • acceptOnMatch - Boolean accept or deny on match
  • event - LoggingEvent to evaluate
  • next - Filter next filter in chain

Returns:

  • Level match level
  • boolean accept on match setting
  • int filter decision
  • Filter next filter

StringMatchFilter

public class StringMatchFilter implements Filter {
    // Configuration
    public void setStringToMatch(String s);
    public String getStringToMatch();
    public void setAcceptOnMatch(boolean acceptOnMatch);
    public boolean getAcceptOnMatch();
    
    // Filter implementation
    @Override
    public int decide(LoggingEvent event);
    @Override
    public Filter getNext();
    @Override
    public void setNext(Filter next);
    
    // Lifecycle
    public void activateOptions();
}

Parameters:

  • s - String to match in log messages
  • acceptOnMatch - Boolean accept or deny on match
  • event - LoggingEvent to evaluate
  • next - Filter next filter in chain

Returns:

  • String match string
  • boolean accept on match setting
  • int filter decision
  • Filter next filter

Configuration SPI

OptionHandler Interface

public interface OptionHandler {
    // Activate configured options
    void activateOptions();
}

Configurator Interface

public interface Configurator {
    // Configure from URL
    void doConfigure(URL url, LoggerRepository repository);
    
    // Configure from InputStream
    void doConfigure(InputStream inputStream, LoggerRepository repository);
}

Parameters:

  • url - URL pointing to configuration
  • inputStream - InputStream containing configuration
  • repository - LoggerRepository to configure

Advanced SPI Components

LoggingEvent

public class LoggingEvent implements Serializable {
    // Event properties
    public String getLoggerName();
    public Logger getLogger();
    public Level getLevel();
    public Object getMessage();
    public String getRenderedMessage();
    public String[] getThrowableStrRep();
    public ThrowableInformation getThrowableInformation();
    public long getTimeStamp();
    public String getThreadName();
    public LocationInfo getLocationInformation();
    public String getFQNOfLoggerClass();
    
    // MDC access
    public Object getMDC(String key);
    public void getMDCCopy();
    
    // NDC access
    public String getNDC();
    
    // Properties
    public Set getPropertyKeySet();
    public String getProperty(String key);
}

Parameters:

  • key - String key for MDC or property access

Returns:

  • Various return types depending on method (String, Level, Object, etc.)

LocationInfo

public class LocationInfo implements Serializable {
    // Location constants
    public static final String NA = "?";
    
    // Location information
    public String getClassName();
    public String getFileName();
    public String getLineNumber();
    public String getMethodName();
    public String fullInfo();
}

Returns:

  • String location information components

ThrowableInformation

public class ThrowableInformation implements Serializable {
    // Constructor
    public ThrowableInformation(Throwable throwable);
    public ThrowableInformation(String[] rep);
    
    // Throwable access
    public Throwable getThrowable();
    public String[] getThrowableStrRep();
}

Parameters:

  • throwable - Throwable exception
  • rep - String array representation

Returns:

  • Throwable original exception
  • String[] string representation

Usage Examples

Custom Logger Factory

import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.Logger;

public class CustomLoggerFactory implements LoggerFactory {
    
    @Override
    public Logger makeNewLoggerInstance(String name) {
        // Create custom logger with enhanced functionality
        return new CustomLogger(name);
    }
    
    // Custom logger implementation
    public static class CustomLogger extends Logger {
        public CustomLogger(String name) {
            super(name);
        }
        
        // Add custom logging methods
        public void audit(Object message) {
            // Custom audit logging
            super.info("AUDIT: " + message);
        }
        
        public void security(Object message) {  
            // Custom security logging
            super.warn("SECURITY: " + message);
        }
    }
}

Custom Error Handler

import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.*;

public class CustomErrorHandler implements ErrorHandler {
    private Appender appender;
    private Appender backupAppender;
    private Logger logger;
    
    @Override
    public void error(String message) {
        System.err.println("Custom Error Handler: " + message);
    }
    
    @Override
    public void error(String message, Exception ex, int errorCode) {
        System.err.println("Custom Error Handler [" + errorCode + "]: " + message);
        if (ex != null) {
            ex.printStackTrace();
        }
    }
    
    @Override
    public void error(String message, Exception ex, int errorCode, LoggingEvent event) {
        error(message, ex, errorCode);
        
        // Try backup appender if available
        if (backupAppender != null && event != null) {
            try {
                backupAppender.doAppend(event);
            } catch (Exception backupEx) {
                System.err.println("Backup appender also failed: " + backupEx.getMessage());
            }
        }
    }
    
    @Override
    public void setAppender(Appender appender) {
        this.appender = appender;
    }
    
    @Override
    public void setBackupAppender(Appender appender) {
        this.backupAppender = appender;
    }
    
    @Override
    public void setLogger(Logger logger) {
        this.logger = logger;
    }
    
    @Override
    public void activateOptions() {
        // Initialize any resources
    }
}

Custom Filter Implementation

import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;

public class CustomMessageFilter implements Filter {
    private String[] forbiddenWords;
    private Filter next;
    
    public CustomMessageFilter(String[] forbiddenWords) {
        this.forbiddenWords = forbiddenWords;
    }
    
    @Override
    public int decide(LoggingEvent event) {
        String message = event.getRenderedMessage();
        
        if (message != null) {
            for (String forbidden : forbiddenWords) {
                if (message.toLowerCase().contains(forbidden.toLowerCase())) {
                    return Filter.DENY; // Block messages with forbidden words
                }
            }
        }
        
        return Filter.NEUTRAL; // Let other filters decide
    }
    
    @Override
    public Filter getNext() {
        return next;
    }
    
    @Override
    public void setNext(Filter next) {
        this.next = next;
    }
    
    // Usage example
    public static void setupFilteredLogging() {
        // Create filter to block sensitive information
        String[] sensitiveWords = {"password", "ssn", "credit card"};
        CustomMessageFilter filter = new CustomMessageFilter(sensitiveWords);
        
        // Create appender with filter
        ConsoleAppender appender = new ConsoleAppender(
            new PatternLayout("%-5p %c - %m%n")
        );
        appender.addFilter(filter);
        
        // Configure logger
        Logger logger = Logger.getLogger("sensitive");
        logger.addAppender(appender);
        
        // Test filtering
        logger.info("User login successful"); // Will appear
        logger.info("User password is secret"); // Will be blocked
        logger.info("Processing credit card transaction"); // Will be blocked
    }
}

Custom LoggerRepository

import org.apache.log4j.spi.*;
import org.apache.log4j.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CustomLoggerRepository implements LoggerRepository {
    private final Map<String, Logger> loggers = new ConcurrentHashMap<>();
    private final Logger rootLogger;
    private LoggerFactory loggerFactory = new DefaultCategoryFactory();
    private Level threshold = Level.ALL;
    
    public CustomLoggerRepository() {
        this.rootLogger = new Logger("root");
        this.rootLogger.setLevel(Level.DEBUG);
        loggers.put("root", rootLogger);
    }
    
    @Override
    public Logger getLogger(String name) {
        return getLogger(name, loggerFactory);
    }
    
    @Override
    public Logger getLogger(String name, LoggerFactory factory) {
        Logger logger = loggers.get(name);
        if (logger == null) {
            logger = factory.makeNewLoggerInstance(name);
            loggers.put(name, logger);
            
            // Set up parent-child relationships
            setupParentChild(logger, name);
        }
        return logger;
    }
    
    @Override
    public Logger getRootLogger() {
        return rootLogger;
    }
    
    @Override
    public Logger exists(String name) {
        return loggers.get(name);
    }
    
    @Override
    public Enumeration getCurrentLoggers() {
        return Collections.enumeration(
            loggers.values().stream()
                .filter(logger -> !logger.getName().equals("root"))
                .collect(java.util.stream.Collectors.toList())
        );
    }
    
    @Override
    public Enumeration getCurrentCategories() {
        return getCurrentLoggers();
    }
    
    @Override
    public void shutdown() {
        // Close all appenders
        for (Logger logger : loggers.values()) {
            Enumeration appenders = logger.getAllAppenders();
            while (appenders.hasMoreElements()) {
                Appender appender = (Appender) appenders.nextElement();
                appender.close();
            }
        }
    }
    
    @Override
    public void resetConfiguration() {
        // Remove all appenders and reset levels
        for (Logger logger : loggers.values()) {
            logger.removeAllAppenders();
            logger.setLevel(null);
        }
        rootLogger.setLevel(Level.DEBUG);
    }
    
    @Override
    public boolean isDisabled(int level) {
        return threshold.toInt() > level;
    }
    
    @Override
    public void setThreshold(Level level) {
        this.threshold = level;
    }
    
    @Override
    public void setThreshold(String val) {
        setThreshold(Level.toLevel(val));
    }
    
    @Override
    public Level getThreshold() {
        return threshold;
    }
    
    @Override
    public void emitNoAppenderWarning(Category cat) {
        System.err.println("No appenders could be found for logger (" + 
                          cat.getName() + ").");
    }
    
    @Override
    public void setLoggerFactory(LoggerFactory factory) {
        this.loggerFactory = factory;
    }
    
    @Override
    public LoggerFactory getLoggerFactory() {
        return loggerFactory;
    }
    
    private void setupParentChild(Logger logger, String name) {
        // Simplified parent-child setup
        int lastDot = name.lastIndexOf('.');
        if (lastDot > 0) {
            String parentName = name.substring(0, lastDot);
            Logger parent = getLogger(parentName);
            // Set up parent relationship (simplified)
        }
    }
}

Advanced Filter Chain

import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.*;

public class FilterChainExample {
    
    public static void setupAdvancedFiltering() {
        // Create multiple filters
        LevelMatchFilter infoFilter = new LevelMatchFilter();
        infoFilter.setLevel(Level.INFO);
        infoFilter.setAcceptOnMatch(true);
        
        LevelRangeFilter errorFilter = new LevelRangeFilter();
        errorFilter.setLevelMin(Level.ERROR);
        errorFilter.setLevelMax(Level.FATAL);
        errorFilter.setAcceptOnMatch(true);
        
        StringMatchFilter sensitiveFilter = new StringMatchFilter();
        sensitiveFilter.setStringToMatch("password");
        sensitiveFilter.setAcceptOnMatch(false); // Deny
        
        // Chain filters
        infoFilter.setNext(errorFilter);
        errorFilter.setNext(sensitiveFilter);
        
        // Create appender with filter chain
        ConsoleAppender appender = new ConsoleAppender(
            new PatternLayout("%-5p %c - %m%n")
        );
        appender.addFilter(infoFilter);
        
        // Configure logger
        Logger logger = Logger.getLogger("filtered");
        logger.addAppender(appender);
        logger.setLevel(Level.DEBUG);
        
        // Test filter chain
        logger.debug("Debug message"); // Filtered out (not INFO or ERROR+)
        logger.info("Info message"); // Passes (INFO level)
        logger.info("User password changed"); // Blocked (contains "password")
        logger.error("Error occurred"); // Passes (ERROR level)
    }
}

Error Handler Implementations

FallbackErrorHandler

An error handler that provides failover capability by switching to a backup appender when the primary appender fails.

public class FallbackErrorHandler implements ErrorHandler {
    // Constructors
    public FallbackErrorHandler();
    
    // ErrorHandler interface methods
    public void error(String message);
    public void error(String message, Exception e, int errorCode);
    public void error(String message, Exception e, int errorCode, LoggingEvent event);
    public void setAppender(Appender primary);
    public void setBackupAppender(Appender backup);
    public void setLogger(Logger logger);
    
    // Activation
    public void activateOptions();
}

Parameters:

  • message - Error message describing the failure
  • e - Exception that caused the error
  • errorCode - Numeric error code from ErrorCode constants
  • event - LoggingEvent that failed to be processed
  • primary - Primary appender that failed
  • backup - Backup appender to use for failover
  • logger - Logger to update during failover

Usage Example:

import org.apache.log4j.*;
import org.apache.log4j.varia.FallbackErrorHandler;

public class FallbackErrorHandlerExample {
    public void setupFallback() {
        // Create primary appender (might fail)
        FileAppender primaryAppender = new FileAppender(
            new PatternLayout("%d %-5p %c - %m%n"),
            "/tmp/primary.log",
            true
        );
        primaryAppender.setName("primary");
        
        // Create backup appender (console)
        ConsoleAppender backupAppender = new ConsoleAppender(
            new PatternLayout("FALLBACK: %d %-5p %c - %m%n")
        );
        backupAppender.setName("backup");
        
        // Create fallback error handler
        FallbackErrorHandler errorHandler = new FallbackErrorHandler();
        errorHandler.setAppender(primaryAppender);
        errorHandler.setBackupAppender(backupAppender);
        errorHandler.setLogger(Logger.getLogger("com.myapp"));
        errorHandler.activateOptions();
        
        // Set error handler on primary appender
        primaryAppender.setErrorHandler(errorHandler);
        
        // Configure logger
        Logger logger = Logger.getLogger("com.myapp");
        logger.addAppender(primaryAppender);
    }
}

Rewrite Policies

RewritePolicy Interface

Base interface for implementing logging event rewrite strategies used with RewriteAppender.

public interface RewritePolicy {
    /**
     * Rewrite a logging event
     * @param source original logging event
     * @return rewritten event, original event, or null to suppress
     */
    LoggingEvent rewrite(LoggingEvent source);
}

MapRewritePolicy

A rewrite policy that processes events where the message implements java.util.Map, combining message properties with the event's existing properties.

public class MapRewritePolicy implements RewritePolicy {
    // Constructor
    public MapRewritePolicy();
    
    // RewritePolicy implementation
    public LoggingEvent rewrite(LoggingEvent source);
}

Usage Example:

import org.apache.log4j.*;
import org.apache.log4j.rewrite.MapRewritePolicy;
import java.util.HashMap;
import java.util.Map;

public class RewritePolicyExample {
    public void setupMapRewrite() {
        // Create rewrite policy
        MapRewritePolicy rewritePolicy = new MapRewritePolicy();
        
        // Create RewriteAppender (would need to be implemented)
        // RewriteAppender rewriteAppender = new RewriteAppender();
        // rewriteAppender.setRewritePolicy(rewritePolicy);
        
        // Example of map-based logging
        Logger logger = Logger.getLogger("com.myapp");
        
        Map<String, Object> logMap = new HashMap<>();
        logMap.put("message", "User action performed");
        logMap.put("userId", "12345");
        logMap.put("action", "login");
        logMap.put("timestamp", System.currentTimeMillis());
        
        // Log the map - will be processed by MapRewritePolicy
        logger.info(logMap);
    }
}

Object Renderers

ObjectRenderer Interface

Interface for custom object-to-string conversion in log messages.

public interface ObjectRenderer {
    /**
     * Render the object as a String
     * @param o object to render
     * @return String representation of the object
     */
    String doRender(Object o);
}

RendererMap

Manages mapping between classes and their corresponding ObjectRenderer implementations.

public class RendererMap {
    // Constructor
    public RendererMap();
    
    // Static methods
    public static void addRenderer(RendererSupport repository, String renderedClassName, String renderingClassName);
    
    // Instance methods
    public ObjectRenderer get(Object o);
    public ObjectRenderer get(Class clazz);
    public void put(Class clazz, ObjectRenderer renderer);
    public void clear();
}

Parameters:

  • repository - RendererSupport instance (typically LoggerRepository)
  • renderedClassName - Class name to be rendered
  • renderingClassName - ObjectRenderer implementation class name
  • o - Object instance to find renderer for
  • clazz - Class to find renderer for
  • renderer - ObjectRenderer to associate with class

Returns:

  • get() methods return ObjectRenderer instance or default renderer
  • put() and clear() methods return void

Usage Example:

import org.apache.log4j.*;
import org.apache.log4j.or.ObjectRenderer;
import org.apache.log4j.or.RendererMap;

public class ObjectRendererExample {
    
    // Custom renderer for User objects
    public static class UserRenderer implements ObjectRenderer {
        public String doRender(Object o) {
            if (o instanceof User) {
                User user = (User) o;
                return "User[id=" + user.getId() + ", name=" + user.getName() + "]";
            }
            return o.toString();
        }
    }
    
    public void setupCustomRenderer() {
        // Get logger repository that supports renderers
        LoggerRepository repository = LogManager.getLoggerRepository();
        
        // Add custom renderer for User class
        RendererMap.addRenderer(
            (org.apache.log4j.spi.RendererSupport) repository,
            "com.myapp.User",
            "com.myapp.UserRenderer"
        );
        
        // Now User objects will be rendered using UserRenderer
        Logger logger = Logger.getLogger("com.myapp");
        User user = new User(123, "John Doe");
        logger.info("Created user: " + user); // Uses custom renderer
    }
}

JMX Support (Deprecated)

Log4j 1.x compatibility API includes deprecated JMX management classes for backward compatibility. These classes are primarily for legacy applications and new code should use Log4j 2.x JMX features directly.

Key JMX Classes

// Main JMX agent (deprecated)
@Deprecated
public class Agent {
    public static Object createServer(int port);
    public static void start(Object server);
}

// MBean implementations (deprecated)
@Deprecated 
public class HierarchyDynamicMBean extends AbstractDynamicMBean;

@Deprecated
public class LoggerDynamicMBean extends AbstractDynamicMBean;

@Deprecated
public class AppenderDynamicMBean extends AbstractDynamicMBean;

Note: These JMX classes are deprecated and maintained only for compatibility. For new applications, use Log4j 2.x's built-in JMX support instead.

Install with Tessl CLI

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

docs

appenders.md

builders.md

configuration.md

context.md

index.md

layouts.md

logging.md

spi.md

tile.json