CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-dropwizard--dropwizard-logging

Comprehensive logging framework module for Dropwizard applications providing configurable appenders, formatters, and logback integration

Pending
Overview
Eval results
Files

filter-system.mddocs/

Filter System

Configurable filter system for controlling which log events are processed by appenders with threshold and custom filtering capabilities. The filter system provides both level-based filtering and extensible custom filter support.

Capabilities

FilterFactory Interface

Base SPI interface for creating custom Logback filters with Jackson-based polymorphic configuration.

/**
 * SPI for creating Logback Filter instances
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public interface FilterFactory<E> extends Discoverable {
    /**
     * Build a filter instance
     * @return configured Filter instance
     */
    Filter<E> build();
}

LevelFilterFactory Interface

Interface for creating level-based filters that filter events based on logging levels.

/**
 * Interface for creating level-based filters
 */
public interface LevelFilterFactory<E> {
    /**
     * Build a level filter instance
     * @param threshold the minimum level threshold
     * @return configured Filter instance
     */
    Filter<E> build(Level threshold);
}

ThresholdLevelFilterFactory

Default implementation that creates threshold filters for filtering events below a minimum log level.

/**
 * Creates threshold filters for minimum log levels
 */
public class ThresholdLevelFilterFactory implements LevelFilterFactory<ILoggingEvent> {
    /**
     * Build a threshold filter that accepts events at or above the threshold level
     * @param threshold the minimum level threshold
     * @return ThresholdFilter configured with the specified level
     */
    @Override
    public Filter<ILoggingEvent> build(Level threshold);
}

Usage Example:

ThresholdLevelFilterFactory filterFactory = new ThresholdLevelFilterFactory();
Filter<ILoggingEvent> filter = filterFactory.build(Level.WARN);

// The filter will accept WARN, ERROR levels and reject DEBUG, INFO levels
FilterReply reply1 = filter.decide(infoEvent);  // Returns DENY
FilterReply reply2 = filter.decide(warnEvent);  // Returns NEUTRAL (accept)
FilterReply reply3 = filter.decide(errorEvent); // Returns NEUTRAL (accept)

NullLevelFilterFactory

No-op filter factory that creates filters which always return NEUTRAL, effectively passing all events through.

/**
 * Creates no-op filters that always return NEUTRAL
 */
public class NullLevelFilterFactory<E> implements LevelFilterFactory<E> {
    /**
     * Build a no-op filter that accepts all events
     * @param threshold ignored parameter
     * @return Filter that always returns NEUTRAL
     */
    @Override
    public Filter<E> build(Level threshold);
}

Usage Example:

NullLevelFilterFactory<ILoggingEvent> filterFactory = new NullLevelFilterFactory<>();
Filter<ILoggingEvent> filter = filterFactory.build(Level.DEBUG); // threshold ignored

// The filter will accept all events regardless of level
FilterReply reply = filter.decide(anyEvent); // Always returns NEUTRAL

Filter Configuration in Appenders

Filters can be configured on appenders to control which events are processed. The AbstractAppenderFactory provides support for multiple filter configurations.

Using Filters with Appenders

public abstract class AbstractAppenderFactory<E> implements AppenderFactory<E> {
    protected List<FilterFactory<E>> filterFactories = new ArrayList<>();
    
    /**
     * Set additional filter factories
     * @param filterFactories list of filter factories to apply
     */
    public void setFilterFactories(List<FilterFactory<E>> filterFactories);
    
    /**
     * Get the configured filter factories
     * @return list of filter factories
     */
    public List<FilterFactory<E>> getFilterFactories();
    
    /**
     * Add a single filter factory
     * @param filterFactory the filter factory to add
     */
    public void addFilterFactory(FilterFactory<E> filterFactory);
}

Usage Example:

// Create a console appender with custom filtering
ConsoleAppenderFactory<ILoggingEvent> consoleAppender = new ConsoleAppenderFactory<>();

// Add a threshold filter to only show WARN and above
ThresholdLevelFilterFactory thresholdFilter = new ThresholdLevelFilterFactory();
List<FilterFactory<ILoggingEvent>> filters = new ArrayList<>();
filters.add(thresholdFilter);

consoleAppender.setFilterFactories(filters);
consoleAppender.setThreshold(Level.WARN); // This also applies threshold filtering

// Build the appender
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
Appender<ILoggingEvent> appender = consoleAppender.build(context, "MyApp", 
    new DropwizardLayoutFactory(), thresholdFilter, new AsyncLoggingEventAppenderFactory());

Custom Filter Implementation

You can create custom filters by implementing the FilterFactory interface:

Custom Filter Example

/**
 * Example custom filter that filters by logger name pattern
 */
@JsonTypeName("logger-pattern")
public class LoggerPatternFilterFactory implements FilterFactory<ILoggingEvent> {
    private String pattern;
    private boolean include = true;
    
    public void setPattern(String pattern) {
        this.pattern = pattern;
    }
    
    public void setInclude(boolean include) {
        this.include = include;
    }
    
    @Override
    public Filter<ILoggingEvent> build() {
        return new Filter<ILoggingEvent>() {
            private Pattern compiledPattern = Pattern.compile(pattern);
            
            @Override
            public FilterReply decide(ILoggingEvent event) {
                boolean matches = compiledPattern.matcher(event.getLoggerName()).matches();
                
                if (include) {
                    return matches ? FilterReply.NEUTRAL : FilterReply.DENY;
                } else {
                    return matches ? FilterReply.DENY : FilterReply.NEUTRAL;
                }
            }
        };
    }
}

Usage Example:

// Filter to only include database-related loggers
LoggerPatternFilterFactory dbFilter = new LoggerPatternFilterFactory();
dbFilter.setPattern(".*\\.db\\..*");
dbFilter.setInclude(true);

// Filter to exclude noisy loggers
LoggerPatternFilterFactory noiseFilter = new LoggerPatternFilterFactory();
noiseFilter.setPattern("com\\.noisy\\..*");
noiseFilter.setInclude(false);

// Apply filters to an appender
FileAppenderFactory<ILoggingEvent> fileAppender = new FileAppenderFactory<>();
fileAppender.setFilterFactories(Arrays.asList(dbFilter, noiseFilter));

Filter Chain Behavior

When multiple filters are configured on an appender, they are applied in order with the following logic:

  1. ACCEPT: Event is immediately accepted and logged, skipping remaining filters
  2. DENY: Event is immediately rejected and not logged, skipping remaining filters
  3. NEUTRAL: Continue to the next filter in the chain

If all filters return NEUTRAL, the event is accepted and logged.

Filter Chain Example:

// Create multiple filters
List<FilterFactory<ILoggingEvent>> filterChain = Arrays.asList(
    createThresholdFilter(Level.DEBUG),     // First: must be DEBUG or above
    createLoggerPatternFilter("com.app.*"), // Second: must match logger pattern
    createCustomBusinessFilter()            // Third: custom business logic
);

ConsoleAppenderFactory<ILoggingEvent> appender = new ConsoleAppenderFactory<>();
appender.setFilterFactories(filterChain);

// Event processing:
// 1. ThresholdFilter: if level < DEBUG -> DENY (stop)
// 2. LoggerPatternFilter: if logger doesn't match -> DENY (stop)  
// 3. CustomBusinessFilter: apply business logic -> ACCEPT/DENY/NEUTRAL
// 4. If all return NEUTRAL -> event is logged

Built-in Logback Filters

You can also wrap standard Logback filters in FilterFactory implementations:

Common Logback Filters

  • ThresholdFilter: Filter by minimum level (provided by ThresholdLevelFilterFactory)
  • LevelFilter: Filter by exact level match
  • RegexFilter: Filter by regex pattern matching on formatted message
  • MDCFilter: Filter by MDC (Mapped Diagnostic Context) values
  • EvaluatorFilter: Filter using Groovy/Janino expressions

Example wrapping a RegexFilter:

@JsonTypeName("regex")
public class RegexFilterFactory implements FilterFactory<ILoggingEvent> {
    private String regex;
    private FilterReply onMatch = FilterReply.NEUTRAL;
    private FilterReply onMismatch = FilterReply.DENY;
    
    @Override
    public Filter<ILoggingEvent> build() {
        ch.qos.logback.core.filter.Filter<ILoggingEvent> regexFilter = 
            new ch.qos.logback.core.filter.Filter<ILoggingEvent>() {
                private Pattern pattern = Pattern.compile(regex);
                
                @Override
                public FilterReply decide(ILoggingEvent event) {
                    String message = event.getFormattedMessage();
                    return pattern.matcher(message).find() ? onMatch : onMismatch;
                }
            };
        return regexFilter;
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-dropwizard--dropwizard-logging

docs

appender-factories.md

async-logging.md

filter-system.md

index.md

layout-system.md

logging-factories.md

utility-classes.md

tile.json