Core infrastructure and basic components for the Logback logging framework, providing appenders, encoders, layouts, filters, and event processing pipeline
—
Flexible pattern-based formatting system with conversion chains, color support, and extensible converter framework for custom log formatting. Pattern processing enables sophisticated log message formatting with placeholder substitution and conditional formatting.
Base class for pattern-based layouts with pattern compilation and conversion chain management.
/**
* Base class for pattern-based layouts with conversion chain support.
*/
public abstract class PatternLayoutBase<E> extends LayoutBase<E> {
/**
* Set the conversion pattern.
* @param pattern conversion pattern with placeholders
*/
public void setPattern(String pattern);
/**
* Get the conversion pattern.
* @return conversion pattern
*/
public String getPattern();
/**
* Set post-compile processor for pattern customization.
* @param postCompileProcessor processor for post-compilation customization
*/
public void setPostCompileProcessor(PostCompileProcessor<E> postCompileProcessor);
@Override
public void start();
@Override
public void stop();
}Base class for all pattern converters in the conversion chain.
/**
* Base class for pattern converters that transform events into text.
*/
public abstract class Converter<E> implements ContextAware {
private Converter<E> next;
/**
* Write the conversion result to the string builder.
* @param buf string builder to write to
* @param event event to convert
*/
public abstract void write(StringBuilder buf, E event);
/**
* Set the next converter in the chain.
* @param next next converter
*/
public void setNext(Converter<E> next);
/**
* Get the next converter in the chain.
* @return next converter
*/
public Converter<E> getNext();
}Converter with formatting options like width, alignment, and truncation.
/**
* Converter with formatting capabilities (width, alignment, truncation).
*/
public abstract class FormattingConverter<E> extends Converter<E> {
private FormatInfo formatInfo;
/**
* Convert event to string (implemented by subclasses).
* @param event event to convert
* @return converted string
*/
public abstract String convert(E event);
/**
* Set formatting information.
* @param formatInfo formatting options
*/
public void setFormattingInfo(FormatInfo formatInfo);
/**
* Get formatting information.
* @return formatting options
*/
public FormatInfo getFormattingInfo();
@Override
public void write(StringBuilder buf, E event);
}Converter that can wrap child converters for complex formatting scenarios.
/**
* Converter that wraps child converters for composite formatting.
*/
public abstract class CompositeConverter<E> extends DynamicConverter<E> {
private Converter<E> childConverter;
/**
* Set the child converter.
* @param child child converter to wrap
*/
public void setChildConverter(Converter<E> child);
/**
* Get the child converter.
* @return child converter
*/
public Converter<E> getChildConverter();
@Override
public void start();
}Converter for static text in patterns.
/**
* Converter for literal text in patterns.
*/
public class LiteralConverter<E> extends Converter<E> {
private String literal;
/**
* Set the literal text.
* @param literal text to output
*/
public void setLiteral(String literal);
/**
* Get the literal text.
* @return literal text
*/
public String getLiteral();
@Override
public void write(StringBuilder buf, E event);
}Class containing formatting information for converters.
/**
* Formatting information for converters (width, alignment, truncation).
*/
public class FormatInfo {
public int min; // Minimum width
public int max; // Maximum width
public boolean leftPad; // Left padding flag
public boolean leftTruncate; // Left truncation flag
/**
* Create format info with specified parameters.
* @param min minimum width
* @param max maximum width
* @param leftPad true for left padding
* @param leftTruncate true for left truncation
*/
public FormatInfo(int min, int max, boolean leftPad, boolean leftTruncate);
/**
* Check if formatting is identity (no formatting applied).
* @return true if no formatting
*/
public boolean isIdentity();
}ANSI color support for console output with various color options.
/**
* Base class for foreground color converters.
*/
public abstract class ForegroundCompositeConverterBase<E> extends CompositeConverter<E> {
/**
* Get the ANSI color code for this converter.
* @return ANSI color code
*/
protected abstract String getForegroundColorCode();
@Override
protected String transform(E event, String in);
}
// Specific color converters
public class BlackCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class RedCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class GreenCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class YellowCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class BlueCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class MagentaCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class CyanCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class WhiteCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class GrayCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
// Bold color variants
public class BoldRedCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
public class BoldGreenCompositeConverter<E> extends ForegroundCompositeConverterBase<E> { }
// ... additional bold variantsANSI escape sequence constants for color formatting.
/**
* ANSI escape sequences for console colors.
*/
public class ANSIConstants {
public static final String ESC_START = "\033[";
public static final String ESC_END = "m";
public static final String BOLD = "1;";
public static final String NORMAL = "0;";
// Color codes
public static final String BLACK = "30";
public static final String RED = "31";
public static final String GREEN = "32";
public static final String YELLOW = "33";
public static final String BLUE = "34";
public static final String MAGENTA = "35";
public static final String CYAN = "36";
public static final String WHITE = "37";
public static final String DEFAULT = "39";
// Reset
public static final String RESET = ESC_START + "0" + ESC_END;
}Framework for parsing pattern strings into converter chains.
/**
* Parser for converting pattern strings into node trees.
*/
public class Parser<E> {
/**
* Parse pattern string into node tree.
* @return root node of parsed pattern
* @throws ScanException if parsing fails
*/
public Node parse() throws ScanException;
/**
* Set context for the parser.
* @param context context for error reporting
*/
public void setContext(Context context);
}
/**
* Compiler for converting node trees into converter chains.
*/
public class Compiler<E> {
/**
* Compile node tree into converter chain.
* @param head root node
* @param converterMap map of converter classes
* @return head of converter chain
*/
public Converter<E> compile(Node head, Map<String, String> converterMap);
/**
* Set context for the compiler.
* @param context context for error reporting
*/
public void setContext(Context context);
}Node classes representing parsed pattern elements.
/**
* Base class for pattern syntax tree nodes.
*/
public class Node {
private Node next;
private Object value;
/**
* Set the next node in the chain.
* @param next next node
*/
public void setNext(Node next);
/**
* Get the next node.
* @return next node
*/
public Node getNext();
/**
* Set the node value.
* @param value node value
*/
public void setValue(Object value);
/**
* Get the node value.
* @return node value
*/
public Object getValue();
}
/**
* Node for literal text.
*/
public class LiteralNode extends Node { }
/**
* Node for simple conversion keywords.
*/
public class SimpleKeywordNode extends Node { }
/**
* Node for composite conversion keywords with options.
*/
public class CompositeNode extends Node {
private List<String> options;
/**
* Set conversion options.
* @param options list of option strings
*/
public void setOptions(List<String> options);
/**
* Get conversion options.
* @return list of options
*/
public List<String> getOptions();
}Utility methods for working with converter chains.
/**
* Utility methods for converter chain management.
*/
public class ConverterUtil {
/**
* Set context on all converters in the chain.
* @param context context to set
* @param head head of converter chain
*/
public static <E> void setContextForConverters(Context context, Converter<E> head);
/**
* Start all converters in the chain.
* @param head head of converter chain
*/
public static <E> void startConverters(Converter<E> head);
/**
* Find tail converter in the chain.
* @param head head of converter chain
* @return tail converter
*/
public static <E> Converter<E> findTail(Converter<E> head);
}import ch.qos.logback.core.pattern.PatternLayoutBase;
public class SimplePatternLayout<E> extends PatternLayoutBase<E> {
@Override
public String doLayout(E event) {
// Use the compiled converter chain to format the event
StringBuilder sb = new StringBuilder();
if (head != null) {
head.write(sb, event);
}
return sb.toString();
}
}
// Configure and use
SimplePatternLayout<LoggingEvent> layout = new SimplePatternLayout<>();
layout.setContext(context);
layout.setPattern("%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n");
layout.start();import ch.qos.logback.core.pattern.FormattingConverter;
public class HostnameConverter<E> extends FormattingConverter<E> {
private static final String HOSTNAME = getHostname();
@Override
public String convert(E event) {
return HOSTNAME;
}
private static String getHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "unknown";
}
}
}
// Register and use in pattern
Map<String, String> converterMap = new HashMap<>();
converterMap.put("hostname", HostnameConverter.class.getName());
// Pattern: "%d{yyyy-MM-dd HH:mm:ss} [%hostname] %msg%n"import ch.qos.logback.core.pattern.color.*;
// Create pattern with colors
String colorPattern = "%black(%d{HH:mm:ss.SSS}) " +
"%highlight(%-5level) " +
"%cyan(%logger{36}) - " +
"%msg%n";
PatternLayoutBase<LoggingEvent> layout = new PatternLayoutBase<LoggingEvent>() {
@Override
public String doLayout(LoggingEvent event) {
StringBuilder sb = new StringBuilder();
if (head != null) {
head.write(sb, event);
}
return sb.toString();
}
};
layout.setContext(context);
layout.setPattern(colorPattern);
layout.start();import ch.qos.logback.core.pattern.CompositeConverter;
public class LevelColorConverter<E> extends CompositeConverter<E> {
@Override
protected String transform(E event, String in) {
if (event instanceof LoggingEvent) {
LoggingEvent loggingEvent = (LoggingEvent) event;
Level level = loggingEvent.getLevel();
String colorCode;
switch (level.toString()) {
case "ERROR":
colorCode = ANSIConstants.RED;
break;
case "WARN":
colorCode = ANSIConstants.YELLOW;
break;
case "INFO":
colorCode = ANSIConstants.GREEN;
break;
case "DEBUG":
colorCode = ANSIConstants.CYAN;
break;
default:
colorCode = ANSIConstants.DEFAULT;
}
return ANSIConstants.ESC_START + colorCode + ANSIConstants.ESC_END +
in + ANSIConstants.RESET;
}
return in;
}
}import ch.qos.logback.core.pattern.parser.Parser;
import ch.qos.logback.core.pattern.parser.Compiler;
public class DynamicPatternLayout<E> extends LayoutBase<E> {
private String pattern;
private Converter<E> head;
private Map<String, String> converterMap;
public void updatePattern(String newPattern) {
this.pattern = newPattern;
recompile();
}
private void recompile() {
try {
Parser<E> parser = new Parser<>(pattern);
parser.setContext(getContext());
Node head = parser.parse();
Compiler<E> compiler = new Compiler<>();
compiler.setContext(getContext());
this.head = compiler.compile(head, converterMap);
ConverterUtil.setContextForConverters(getContext(), this.head);
ConverterUtil.startConverters(this.head);
} catch (Exception e) {
addError("Failed to compile pattern: " + pattern, e);
}
}
@Override
public String doLayout(E event) {
if (head == null) {
return "";
}
StringBuilder sb = new StringBuilder();
head.write(sb, event);
return sb.toString();
}
public void setConverterMap(Map<String, String> converterMap) {
this.converterMap = converterMap;
}
}// Custom converter that accepts options
public class TruncateConverter<E> extends FormattingConverter<E> {
private int maxLength = 50;
private String suffix = "...";
@Override
public void start() {
List<String> options = getOptionList();
if (options != null && !options.isEmpty()) {
try {
maxLength = Integer.parseInt(options.get(0));
if (options.size() > 1) {
suffix = options.get(1);
}
} catch (NumberFormatException e) {
addError("Invalid truncate length: " + options.get(0));
}
}
super.start();
}
@Override
public String convert(E event) {
String message = event.toString();
if (message.length() <= maxLength) {
return message;
}
return message.substring(0, maxLength - suffix.length()) + suffix;
}
}
// Usage in pattern: "%truncate{30,…}(%msg)"%d{pattern} - Date/time formatting%p or %level - Log level%t or %thread - Thread name%c{length} or %logger{length} - Logger name%m or %msg - Message%n - Line separator%r - Milliseconds since start%F - File name%L - Line number%M - Method name%20logger - Right-pad to 20 characters%-20logger - Left-pad to 20 characters%.30logger - Truncate to 30 characters%.-30logger - Truncate from left to 30 characters%20.30logger - Pad to 20, truncate at 30%black(), %red(), %green(), %yellow(), %blue(), %magenta(), %cyan(), %white()%boldRed(), %boldGreen(), etc.%highlight() - Level-based coloringThe pattern processing framework provides powerful and flexible formatting capabilities with excellent extensibility for custom formatting requirements.
Install with Tessl CLI
npx tessl i tessl/maven-ch-qos-logback--logback-core