AbstractStandardEventFormatter.java
package io.jstach.rainbowgum.format;
import io.jstach.rainbowgum.LogEncoder;
import io.jstach.rainbowgum.LogEncoder.EncoderProvider;
import io.jstach.rainbowgum.LogEncoderRegistry;
import io.jstach.rainbowgum.LogEvent;
import io.jstach.rainbowgum.LogFormatter;
/**
* An abstract formatter where the actual full layout of the event is not a concern of the
* user and by default usually has the semi-standard layout of <strong>TTLL - Time,
* Thread, Level, Logger</strong>.
*
* It allows changing the format of time, thread, level, logger, etc. Typically the
* formatters get called in the following order.
* <ol>
* <li>Timestamp</li>
* <li>Thread</li>
* <li>Level</li>
* <li>Logger Name</li>
* <li>Key Values if enabled</li>
* <li>Formatted Message</li>
* <li>Throwable if not null</li>
* </ol>
* If plugins would like to provide some sort of standard formatter they should extend
* this class as well as the {@link AbstractBuilder}.
*
* @see AbstractBuilder
*/
public class AbstractStandardEventFormatter implements LogFormatter.EventFormatter {
/**
* immutable field
*/
protected final LogFormatter timestampFormatter;
/**
* immutable field
*/
protected final LogFormatter threadFormatter;
/**
* immutable field
*/
protected final LogFormatter levelFormatter;
/**
* immutable field
*/
protected final LogFormatter nameFormatter;
/**
* immutable field
*/
protected final LogFormatter messageFormatter;
/**
* immutable field
*/
protected final LogFormatter keyValuesFormatter;
/**
* immutable field
*/
protected final LogFormatter throwableFormatter;
/**
* Combined formatter.
*/
protected final LogFormatter eventFormatter;
/**
* Override
* @param timestampFormatter not <code>null</code>.
* @param threadFormatter not <code>null</code>.
* @param levelFormatter not <code>null</code>.
* @param nameFormatter not <code>null</code>.
* @param messageFormatter not <code>null</code>.
* @param throwableFormatter not <code>null</code>.
* @param keyValuesFormatter not <code>null</code>.
*/
protected AbstractStandardEventFormatter( //
LogFormatter timestampFormatter, //
LogFormatter threadFormatter, //
LogFormatter levelFormatter, //
LogFormatter nameFormatter, //
LogFormatter messageFormatter, //
LogFormatter throwableFormatter, //
LogFormatter keyValuesFormatter) {
super();
this.levelFormatter = levelFormatter;
this.threadFormatter = threadFormatter;
this.timestampFormatter = timestampFormatter;
this.nameFormatter = nameFormatter;
this.messageFormatter = messageFormatter;
this.throwableFormatter = throwableFormatter;
this.keyValuesFormatter = keyValuesFormatter;
this.eventFormatter = build( //
timestampFormatter, //
threadFormatter, //
levelFormatter, //
nameFormatter, //
messageFormatter, //
throwableFormatter, //
keyValuesFormatter);
}
/**
* Creates the standard default TTLL layout. This is largely the default of Log4J2 and
* Logback if no formatting is picked. An example of what the default roughly looks
* like:
*
* <pre>
* 17:47:33.163 [main] WARN com.my.MyLogger - Hello Warn Message {k1=v1}
* 17:47:33.167 [main] DEBUG com.my.MyLogger - Hello Debug Message {k1=v1}
*
* </pre>
* @param timestampFormatter not <code>null</code>.
* @param threadFormatter not <code>null</code>.
* @param levelFormatter not <code>null</code>.
* @param nameFormatter not <code>null</code>.
* @param messageFormatter not <code>null</code>.
* @param throwableFormatter not <code>null</code>.
* @param keyValuesFormatter not <code>null</code>.
* @return formatter.
*/
public static LogFormatter build(LogFormatter timestampFormatter, //
LogFormatter threadFormatter, //
LogFormatter levelFormatter, //
LogFormatter nameFormatter, //
LogFormatter messageFormatter, //
LogFormatter throwableFormatter, //
LogFormatter keyValuesFormatter) {
var b = LogFormatter.builder();
if (!timestampFormatter.isNoop()) {
b.add(timestampFormatter);
b.text(" ");
}
if (!threadFormatter.isNoop()) {
b.text("[");
b.add(threadFormatter);
b.text("] ");
}
if (!levelFormatter.isNoop()) {
b.add(levelFormatter);
b.text(" ");
}
b.add(nameFormatter);
if (!keyValuesFormatter.isNoop()) {
b.add(BracedKeyValuesFormatter.ofStandard(keyValuesFormatter));
}
if (!messageFormatter.isNoop()) {
b.text(" - ");
b.add(messageFormatter);
}
b.newline();
if (!throwableFormatter.isNoop()) {
b.add(throwableFormatter);
}
return b.build();
}
/**
* Abstract TTLL Builder.
*
* @param <T> builder type.
*/
public static abstract class AbstractBuilder<T> {
/**
* mutable field
*/
protected LogFormatter levelFormatter = LevelFormatter.ofRightPadded();
/**
* mutable field
*/
protected LogFormatter timestampFormatter = TimestampFormatter.of();
/**
* mutable field
*/
protected LogFormatter threadFormatter = LogFormatter.builder().threadName().build();
/**
* mutable field
*/
protected LogFormatter nameFormatter = LogFormatter.builder().loggerName().build();
/**
* mutable field
*/
protected LogFormatter messageFormatter = LogFormatter.builder().message().build();
/**
* mutable field
*/
protected LogFormatter throwableFormatter = ThrowableFormatter.of();
/**
* mutable field
*/
protected LogFormatter keyValuesFormatter = LogFormatter.noop();
/**
* For builder
* @return this.
*/
protected abstract T self();
/**
* Do nothing constructor
*/
protected AbstractBuilder() {
}
/**
* Sets timestamp formatter. If not set
* {@link io.jstach.rainbowgum.LogFormatter.TimestampFormatter#of()} will be used.
* @param timestampFormatter formatter to use for rendering
* {@link LogEvent#timestamp()}.
* @return this builder.
*/
public T timestampFormatter(LogFormatter timestampFormatter) {
this.timestampFormatter = timestampFormatter;
return self();
}
/**
* Sets thread formatter. If not set thread name will be used.
* @param threadFormatter formatter to use for rendering thread information.
* @return this builder.
*/
public T threadFormatter(LogFormatter threadFormatter) {
this.threadFormatter = threadFormatter;
return self();
}
/**
* Sets the level formatter. If not set
* {@link io.jstach.rainbowgum.LogFormatter.LevelFormatter#ofRightPadded()} will
* be used.
* @param levelFormatter formatter to use for rendering level information.
* @return this builder.
*/
public T levelFormatter(LogFormatter levelFormatter) {
this.levelFormatter = levelFormatter;
return self();
}
/**
* Sets the logger name formatter. If not set the default will be used.
* @param nameFormatter formatter to use for rendering logger name.
* @return this builder.
*/
public T nameFormatter(LogFormatter nameFormatter) {
this.nameFormatter = nameFormatter;
return self();
}
/**
* Sets the throwable formatter. If not set
* {@link io.jstach.rainbowgum.LogFormatter.ThrowableFormatter#of()} will be used.
* @param throwableFormatter formatter to use for rendering throwables.
* @return this builder.
*/
public T throwableFormatter(LogFormatter throwableFormatter) {
this.throwableFormatter = throwableFormatter;
return self();
}
/**
* Sets the throwable formatter. If not set
* {@link io.jstach.rainbowgum.LogFormatter.ThrowableFormatter#of()} will be used.
* @param throwableFormatter formatter to use for rendering throwables.
* @return this builder.
*/
public T throwableFormatter(ThrowableFormatter throwableFormatter) {
this.throwableFormatter = throwableFormatter;
return self();
}
/**
* Sets the key values formatter. If not set the default key values formatter will
* be used which is a noop.
* @param keyValuesFormatter formatter to use for rendering key values.
* @return this builder.
*/
public T keyValuesFormatter(LogFormatter keyValuesFormatter) {
this.keyValuesFormatter = keyValuesFormatter;
return self();
}
}
/**
* Convenience to register the encoder.
* @return encoder provider.
* @see TTLL#SCHEMA
*/
public EncoderProvider toEncoderProvider() {
return EncoderProvider.of(LogEncoder.of(eventFormatter));
}
/**
* Will register this TTLL like encoder with the uri schema {@value TTLL#SCHEMA} and
* will be used as the default encoder if other encoders are not found.
* @param registry encoder registry.
*/
public void register(LogEncoderRegistry registry) {
register(registry, TTLL.SCHEMA);
}
/**
* Registers this TTLL like encoder with the given uri schema.
* @param registry encoder registry.
* @param schema uri schema to register under.
*/
public void register(LogEncoderRegistry registry, String schema) {
registry.register(schema, toEncoderProvider());
}
@Override
public void format(StringBuilder output, LogEvent logEvent) {
eventFormatter.format(output, logEvent);
}
}