Core infrastructure and basic components for the Logback logging framework, providing appenders, encoders, layouts, filters, and event processing pipeline
—
Core appender classes and interfaces for writing log events to various destinations. Appenders are the components responsible for outputting log events to different targets like console, files, networks, or custom destinations.
The foundational interface that all appenders must implement, providing the core contract for log event processing.
/**
* Core interface for all log event appenders.
* Appenders are responsible for writing log events to their destination.
*/
public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable<E> {
/**
* Get the appender name.
* @return appender name
*/
String getName();
/**
* Process a log event. This is the main method called by the logging framework.
* @param event the log event to process
*/
void doAppend(E event);
/**
* Set the appender name.
* @param name the name to assign to this appender
*/
void setName(String name);
}Base implementation providing synchronized event processing, filter support, and lifecycle management. Most custom appenders should extend this class.
/**
* Base appender implementation with filtering and synchronization.
* Provides thread-safe doAppend() method and filter chain support.
*/
public abstract class AppenderBase<E> extends ContextAwareBase implements Appender<E> {
/**
* Thread-safe template method that applies filters before calling append().
* @param eventObject the event to append
* @throws LogbackException if appending fails
*/
public synchronized void doAppend(E eventObject) throws LogbackException;
/**
* Subclasses must implement this method to handle the actual appending.
* Called by doAppend() after filter processing.
* @param eventObject the event to append
*/
protected abstract void append(E eventObject);
/**
* Start the appender. Subclasses should override to perform initialization.
*/
public void start();
/**
* Stop the appender. Subclasses should override to perform cleanup.
*/
public void stop();
/**
* Check if the appender is started.
* @return true if started, false otherwise
*/
public boolean isStarted();
// Filter management methods inherited from FilterAttachable
public void addFilter(Filter<E> newFilter);
public void clearAllFilters();
public List<Filter<E>> getCopyOfAttachedFiltersList();
public FilterReply getFilterChainDecision(E event);
}Base class for appenders that handle their own synchronization or don't require it.
/**
* Base appender without synchronized doAppend() method.
* Use when the appender handles synchronization internally or when synchronization is not needed.
*/
public abstract class UnsynchronizedAppenderBase<E> extends ContextAwareBase
implements Appender<E> {
/**
* Non-synchronized template method for event processing.
* @param eventObject the event to append
*/
public void doAppend(E eventObject);
/**
* Subclasses implement this to handle actual appending.
* @param eventObject the event to append
*/
protected abstract void append(E eventObject);
}Base class for appenders that output to an OutputStream, providing encoding support and immediate flush control.
/**
* Appender that writes to an OutputStream with encoder support.
* Base class for console and file appenders.
*/
public class OutputStreamAppender<E> extends UnsynchronizedAppenderBase<E> {
/**
* Set the target output stream.
* @param outputStream the stream to write to
*/
public void setOutputStream(OutputStream outputStream);
/**
* Get the current output stream.
* @return the current output stream
*/
public OutputStream getOutputStream();
/**
* Set the encoder for formatting events.
* @param encoder the encoder to use
*/
public void setEncoder(Encoder<E> encoder);
/**
* Get the current encoder.
* @return the current encoder
*/
public Encoder<E> getEncoder();
/**
* Control whether to flush immediately after each event.
* @param immediateFlush true to flush immediately, false to buffer
*/
public void setImmediateFlush(boolean immediateFlush);
/**
* Check if immediate flush is enabled.
* @return true if immediate flush is enabled
*/
public boolean isImmediateFlush();
/**
* Set a layout (deprecated - use encoder instead).
* @param layout the layout to wrap in an encoder
* @deprecated Use setEncoder() instead
*/
@Deprecated
public void setLayout(Layout<E> layout);
}Appender for writing to console (stdout or stderr).
/**
* Console appender with configurable target (stdout/stderr).
*/
public class ConsoleAppender<E> extends OutputStreamAppender<E> {
/**
* Set the console target.
* @param value "System.out" or "System.err"
*/
public void setTarget(String value);
/**
* Get the current console target.
* @return "System.out" or "System.err"
*/
public String getTarget();
}File-based appender with support for append mode, prudent mode (multi-JVM safety), and buffer configuration.
/**
* File appender with collision detection and multi-JVM safety features.
*/
public class FileAppender<E> extends OutputStreamAppender<E> {
/**
* Set the target file path.
* @param file path to the log file
*/
public void setFile(String file);
/**
* Get the current file path.
* @return path to the log file
*/
public String getFile();
/**
* Set append mode.
* @param append true to append to existing file, false to truncate
*/
public void setAppend(boolean append);
/**
* Check if append mode is enabled.
* @return true if appending, false if truncating
*/
public boolean isAppend();
/**
* Enable prudent mode for multi-JVM safety.
* @param prudent true to enable prudent mode
*/
public void setPrudent(boolean prudent);
/**
* Check if prudent mode is enabled.
* @return true if prudent mode is enabled
*/
public boolean isPrudent();
/**
* Set the buffer size for file operations.
* @param bufferSize buffer size in bytes
*/
public void setBufferSize(FileSize bufferSize);
/**
* Get the current buffer size.
* @return buffer size
*/
public FileSize getBufferSize();
/**
* Open a file for writing.
* @param fileName path to the file to open
* @throws IOException if file cannot be opened
*/
public void openFile(String fileName) throws IOException;
}Base class for asynchronous appenders that use a worker thread and queue for non-blocking log processing.
/**
* Asynchronous appender base with configurable queue and worker thread.
*/
public abstract class AsyncAppenderBase<E> extends UnsynchronizedAppenderBase<E>
implements AppenderAttachable<E> {
/**
* Set the queue size for buffering events.
* @param queueSize maximum number of events to buffer
*/
public void setQueueSize(int queueSize);
/**
* Get the current queue size.
* @return queue size
*/
public int getQueueSize();
/**
* Set the threshold for discarding events when queue is full.
* @param discardingThreshold threshold for discarding events
*/
public void setDiscardingThreshold(int discardingThreshold);
/**
* Get the discarding threshold.
* @return discarding threshold
*/
public int getDiscardingThreshold();
/**
* Set the maximum time to wait for queue flush on shutdown.
* @param maxFlushTime maximum flush time in milliseconds
*/
public void setMaxFlushTime(int maxFlushTime);
/**
* Get the maximum flush time.
* @return maximum flush time in milliseconds
*/
public int getMaxFlushTime();
/**
* Enable never-block mode to prevent blocking when queue is full.
* @param neverBlock true to enable never-block mode
*/
public void setNeverBlock(boolean neverBlock);
/**
* Check if never-block mode is enabled.
* @return true if never-block mode is enabled
*/
public boolean isNeverBlock();
/**
* Add an appender to receive events from the async queue.
* @param newAppender appender to add
*/
public void addAppender(Appender<E> newAppender);
/**
* Get the number of events in the queue.
* @return queue depth
*/
public int getQueueSize();
/**
* Get the number of elements remaining in the queue.
* @return remaining queue capacity
*/
public int getRemainingCapacity();
}import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
// Create and configure console appender
ConsoleAppender<Object> appender = new ConsoleAppender<>();
appender.setContext(context);
appender.setTarget("System.out");
// Configure encoder
LayoutWrappingEncoder<Object> encoder = new LayoutWrappingEncoder<>();
encoder.setContext(context);
// encoder.setLayout(layout); // Set your layout here
encoder.start();
appender.setEncoder(encoder);
appender.start();
// Use the appender
appender.doAppend(someEvent);import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.util.FileSize;
// Create file appender with multi-JVM safety
FileAppender<Object> fileAppender = new FileAppender<>();
fileAppender.setContext(context);
fileAppender.setFile("/path/to/application.log");
fileAppender.setAppend(true);
fileAppender.setPrudent(true); // Enable multi-JVM safety
fileAppender.setBufferSize(new FileSize(8192)); // 8KB buffer
fileAppender.setEncoder(encoder);
fileAppender.start();import ch.qos.logback.core.AppenderBase;
public class CustomAppender<E> extends AppenderBase<E> {
private String customProperty;
@Override
protected void append(E eventObject) {
// Custom appending logic here
System.out.println("Custom: " + eventObject.toString());
}
public void setCustomProperty(String customProperty) {
this.customProperty = customProperty;
}
public String getCustomProperty() {
return customProperty;
}
@Override
public void start() {
if (customProperty == null) {
addError("CustomProperty is not set");
return;
}
super.start();
}
}/**
* Interface for components that can attach multiple appenders.
*/
public interface AppenderAttachable<E> {
/**
* Add an appender.
* @param newAppender appender to add
*/
void addAppender(Appender<E> newAppender);
/**
* Iterate over attached appenders.
* @return iterator for appenders
*/
Iterator<Appender<E>> iteratorForAppenders();
/**
* Get an appender by name.
* @param name appender name
* @return appender with the given name, or null
*/
Appender<E> getAppender(String name);
/**
* Check if an appender is attached.
* @param appender appender to check
* @return true if attached
*/
boolean isAttached(Appender<E> appender);
/**
* Detach and stop all appenders.
*/
void detachAndStopAllAppenders();
/**
* Detach a specific appender.
* @param appender appender to detach
* @return true if appender was attached and detached
*/
boolean detachAppender(Appender<E> appender);
/**
* Append an event to all attached appenders.
* @param event event to append
* @return number of appenders that received the event
*/
int appendLoopOnAppenders(E event);
}All appenders implement the LifeCycle interface and follow a consistent start/stop pattern:
start() to initialize resources and validate configurationdoAppend()stop() to cleanup resources and flush buffersAppenders should always be started before use and stopped when no longer needed to ensure proper resource management.
Install with Tessl CLI
npx tessl i tessl/maven-ch-qos-logback--logback-core