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

async-logging.mddocs/

Async Logging

Asynchronous logging capabilities for high-throughput applications with configurable queue sizes and discard policies. Async logging improves application performance by moving log I/O operations to background threads.

Capabilities

AsyncAppenderFactory Interface

Base interface for creating asynchronous appender wrappers that can wrap any synchronous appender in an async wrapper.

/**
 * Interface for creating async appenders
 */
public interface AsyncAppenderFactory<E> {
    /**
     * Build an async appender wrapper
     * @return configured AsyncAppenderBase instance
     */
    AsyncAppenderBase<E> build();
}

AsyncLoggingEventAppenderFactory

Default implementation that creates AsyncAppender instances specifically for ILoggingEvent objects.

/**
 * Creates AsyncAppender instances for ILoggingEvent
 */
public class AsyncLoggingEventAppenderFactory implements AsyncAppenderFactory<ILoggingEvent> {
    /**
     * Build an AsyncAppender for logging events
     * @return configured AsyncAppender instance
     */
    @Override
    public AsyncAppenderBase<ILoggingEvent> build();
}

Async Configuration in AbstractAppenderFactory

All appender factories support async configuration through the AbstractAppenderFactory base class:

public abstract class AbstractAppenderFactory<E> implements AppenderFactory<E> {
    protected int queueSize = 256;
    protected int discardingThreshold = -1;
    protected boolean includeCallerData = false;
    protected boolean neverBlock = false;
    
    /**
     * Set the async queue size
     * @param queueSize the size of the async queue (default: 256)
     */
    public void setQueueSize(int queueSize);
    
    /**
     * Get the async queue size
     * @return the current queue size
     */
    public int getQueueSize();
    
    /**
     * Set the async discarding threshold
     * @param discardingThreshold events below this level may be discarded when queue is full
     *                           (-1 disables discarding, default: -1)
     */
    public void setDiscardingThreshold(int discardingThreshold);
    
    /**
     * Get the async discarding threshold
     * @return the current discarding threshold
     */
    public int getDiscardingThreshold();
    
    /**
     * Include caller data in async logging
     * @param includeCallerData true to include caller information (impacts performance)
     */
    public void setIncludeCallerData(boolean includeCallerData);
    
    /**
     * Check if caller data is included
     * @return true if caller data is included
     */
    public boolean isIncludeCallerData();
    
    /**
     * Set non-blocking behavior for async appenders
     * @param neverBlock true to never block on full queue (may lose log events)
     */
    public void setNeverBlock(boolean neverBlock);
    
    /**
     * Check if async appender never blocks
     * @return true if configured to never block
     */
    public boolean isNeverBlock();
    
    /**
     * Wrap appender in async wrapper if needed
     * @param context the logger context
     * @param asyncAppenderFactory factory for async appenders
     * @param appender the appender to wrap
     * @return the wrapped appender (or original if async not configured)
     */
    protected Appender<E> wrapAsync(LoggerContext context, 
                                   AsyncAppenderFactory<E> asyncAppenderFactory, 
                                   Appender<E> appender);
}

Async Configuration Examples

Basic Async File Logging

FileAppenderFactory<ILoggingEvent> fileAppender = new FileAppenderFactory<>();
fileAppender.setCurrentLogFilename("./logs/application.log");

// Configure async settings
fileAppender.setQueueSize(512);               // Larger queue for high throughput
fileAppender.setIncludeCallerData(false);     // Disable for better performance
fileAppender.setNeverBlock(false);            // Block when queue is full (prevents loss)
fileAppender.setDiscardingThreshold(-1);     // Never discard events

// Build with async wrapper
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
AsyncLoggingEventAppenderFactory asyncFactory = new AsyncLoggingEventAppenderFactory();
Appender<ILoggingEvent> appender = fileAppender.build(context, "MyApp", 
    new DropwizardLayoutFactory(), new ThresholdLevelFilterFactory(), asyncFactory);

High-Throughput Async Configuration

ConsoleAppenderFactory<ILoggingEvent> consoleAppender = new ConsoleAppenderFactory<>();

// High-throughput configuration
consoleAppender.setQueueSize(2048);           // Very large queue
consoleAppender.setDiscardingThreshold(20);   // Discard INFO and below when queue is 80% full
consoleAppender.setIncludeCallerData(false);  // Disable caller data for performance
consoleAppender.setNeverBlock(true);          // Never block application threads

// This configuration prioritizes application performance over log completeness

Balanced Async Configuration

FileAppenderFactory<ILoggingEvent> fileAppender = new FileAppenderFactory<>();
fileAppender.setCurrentLogFilename("./logs/application.log");

// Balanced configuration
fileAppender.setQueueSize(1024);              // Reasonable queue size
fileAppender.setDiscardingThreshold(0);       // Discard TRACE events when queue is full
fileAppender.setIncludeCallerData(true);      // Include caller data for debugging
fileAppender.setNeverBlock(false);            // Block to ensure important events are logged

// This configuration balances performance with log completeness

Async Behavior and Performance Considerations

Queue Management

The async appender uses a bounded queue to buffer log events:

  • Queue Size: Determines how many events can be buffered
  • Queue Full Behavior: Controlled by neverBlock setting
    • neverBlock = false: Application thread blocks until queue space is available
    • neverBlock = true: Events may be dropped when queue is full

Discarding Threshold

When the queue reaches the discarding threshold percentage:

  • Events below the threshold level are discarded
  • Higher-level events are still queued
  • Threshold is calculated as: (queueSize * discardingThreshold) / 100
  • Use -1 to disable discarding entirely

Discarding Level Mapping:

// Default discarding behavior by level
if (discardingThreshold >= 0) {
    // Events at TRACE, DEBUG levels may be discarded
    // INFO, WARN, ERROR levels are preserved
}

Caller Data Performance Impact

Including caller data has significant performance implications:

// High performance (recommended for production)
appender.setIncludeCallerData(false);

// Lower performance but includes method/line information
appender.setIncludeCallerData(true);

When includeCallerData = true, each log event captures:

  • Method name
  • Line number
  • Class name
  • File name

This information is expensive to obtain and should be disabled in high-throughput scenarios.

Async Appender Shutdown

Async appenders must be properly shut down to flush remaining events:

// Proper shutdown
LoggingFactory loggingFactory = // ... your logging factory
loggingFactory.stop(); // Flushes async queues and stops background threads

// Or manually stop async appenders
AsyncAppenderBase<ILoggingEvent> asyncAppender = // ... your async appender
asyncAppender.stop(); // Waits for queue to drain and stops worker thread

Monitoring Async Appenders

Queue Statistics

You can monitor async appender performance through JMX or programmatically:

AsyncAppenderBase<ILoggingEvent> asyncAppender = // ... your async appender

// Check queue status
int queueSize = asyncAppender.getQueueSize();
int remainingCapacity = asyncAppender.getRemainingCapacity();
int numberOfElementsInQueue = queueSize - remainingCapacity;

// Monitor discard counts (if supported by implementation)
// Note: Dropwizard may expose these through metrics

Metrics Integration

Dropwizard Logging integrates with Dropwizard Metrics to provide async appender monitoring:

MetricRegistry metrics = new MetricRegistry();
loggingFactory.configure(metrics, "MyApplication");

// Metrics may include:
// - Queue depth
// - Discard counts  
// - Processing rates
// - Error counts

Troubleshooting Async Logging

Common Issues

Log Events Not Appearing:

  • Check if queue is full and events are being discarded
  • Verify proper shutdown to flush remaining events
  • Ensure async appender is properly started

Application Blocking:

  • Check neverBlock setting
  • Monitor queue depth
  • Consider increasing queue size

Missing Caller Information:

  • Verify includeCallerData is set to true
  • Note performance impact of enabling caller data

Memory Usage:

  • Large queue sizes consume more memory
  • Each queued event holds references until processed
  • Consider queue size vs. memory constraints

Debug Configuration

// Enable debug logging for async appenders
Logger asyncLogger = LoggerFactory.getLogger(AsyncAppender.class);
asyncLogger.setLevel(Level.DEBUG);

// This will show queue statistics and discard information

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