Skip to content

Commit

Permalink
Fix shutdown and event builder
Browse files Browse the repository at this point in the history
  • Loading branch information
agentgt committed Jan 24, 2024
1 parent a9c0b34 commit 61eb407
Show file tree
Hide file tree
Showing 8 changed files with 549 additions and 101 deletions.
288 changes: 266 additions & 22 deletions core/src/main/java/io/jstach/rainbowgum/LogEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
import java.io.UncheckedIOException;
import java.lang.System.Logger.Level;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

import org.eclipse.jdt.annotation.Nullable;

import io.jstach.rainbowgum.KeyValues.MutableKeyValues;
import io.jstach.rainbowgum.LogEvent.Builder;
import io.jstach.rainbowgum.LogRouter.Router;

/**
* A LogEvent is a container for a single call to a logger. An event should not created
Expand Down Expand Up @@ -77,7 +82,7 @@ public static LogEvent of(System.Logger.Level level, String loggerName, String m
String threadName = currentThread.getName();
long threadId = currentThread.threadId();
return new OneArgLogEvent(timeStamp, threadName, threadId, level, loggerName, message, keyValues,
messageFormatter, arg1);
messageFormatter, null, arg1);
}

/**
Expand All @@ -101,7 +106,7 @@ public static LogEvent of(System.Logger.Level level, String loggerName, String m
String threadName = currentThread.getName();
long threadId = currentThread.threadId();
return new TwoArgLogEvent(timeStamp, threadName, threadId, level, loggerName, message, keyValues,
messageFormatter, arg1, arg2);
messageFormatter, null, arg1, arg2);
}

/**
Expand All @@ -125,7 +130,7 @@ public static LogEvent ofArgs(System.Logger.Level level, String loggerName, Stri
String threadName = currentThread.getName();
long threadId = currentThread.threadId();
return new ArrayArgLogEvent(timeStamp, threadName, threadId, level, loggerName, message, keyValues,
messageFormatter, args);
messageFormatter, null, args);
}

/**
Expand Down Expand Up @@ -219,6 +224,257 @@ default void formattedMessage(Appendable a) {
*/
public LogEvent freeze(Instant timestamp);

/**
* A builder to create events by calling {@link Router#eventBuilder(String, Level)}.
* <strong>{@link #log()}</strong> should be called at the very end otherwise the
* event will not be logged.
*/
public sealed interface Builder {

/**
* Timestamp when the event was created.
* @param timestamp time the event happened.
* @return this.
*/
public Builder timestamp(Instant timestamp);

/**
* Add an argument to the event being built.
* @param argSupplier supplier will be called immediatly if this event is to be
* logged.
* @return this.
*/
Builder arg(Supplier<?> argSupplier);

/**
* Add an argument to the event being built.
* @param arg maybe null.
* @return this.
*/
Builder arg(@Nullable Object arg);

/**
* Sets the message formatter which interpolates argument place holders.
* @param messageFormatter formatter if not set
* {@link LogMessageFormatter.StandardMessageFormatter#SLF4J} will be used.
* @return this.
*/
public Builder messageFormatter(LogMessageFormatter messageFormatter);

/**
* Name of the thread.
* @param threadName name of thread.
* @return this.
* @apiNote this maybe empty and often is if virtual threads are used.
*/
public Builder threadName(String threadName);

/**
* Thread id.
* @param threadId {@link Thread#getId()}.
* @return this.
*/
public Builder threadId(long threadId);

/**
* Unformatted message.
* @param message unformatted message.
* @return unformatted message
*/
public Builder message(String message);

/**
* Throwable at the time of the event passed from the logger.
* @param throwable exception at the time of the event.
* @return if the event does not have a throwable <code>null</code> will be
* returned.
*/
public Builder throwable(@Nullable Throwable throwable);

/**
* Key values that usually come from MDC or an SLF4J Event Builder.
* @param keyValues will use the passed in keyvalues for the event.
* @return key values.
*/
public Builder keyValues(KeyValues keyValues);

/**
* Will log the event with the current values.
* @return true if accepted.
*/
public boolean log();

}

}

final class LogEventBuilder implements LogEvent.Builder {

private final LogEventLogger logger;

private final Level level;

private final String loggerName;

private Instant timestamp = Instant.now();

private String threadName = Thread.currentThread().getName();

private long threadId = Thread.currentThread().threadId();

private String message = "";

private @Nullable Throwable throwable;

private KeyValues keyValues = KeyValues.of();

private @Nullable List<Object> args = null;

private LogMessageFormatter messageFormatter = LogMessageFormatter.StandardMessageFormatter.SLF4J;

LogEventBuilder(LogEventLogger logger, Level level, String loggerName) {
super();
this.logger = logger;
this.level = level;
this.loggerName = loggerName;
}

@Override
public Builder timestamp(Instant timestamp) {
this.timestamp = timestamp;
return this;
}

@Override
public Builder threadName(String threadName) {
this.threadName = threadName;
return this;
}

@Override
public Builder threadId(long threadId) {
this.threadId = threadId;
return this;
}

@Override
public Builder message(String message) {
this.message = message;
return this;
}

@Override
public Builder messageFormatter(LogMessageFormatter messageFormatter) {
this.messageFormatter = messageFormatter;
return this;
}

@Override
public Builder throwable(@Nullable Throwable throwable) {
this.throwable = throwable;
return this;
}

@Override
public Builder keyValues(KeyValues keyValues) {
this.keyValues = keyValues;
return this;
}

@Override
public Builder arg(Object arg) {
var list = this.args;
if (list == null) {
list = this.args = new ArrayList<>();
}
list.add(arg);
return this;
}

@Override
public Builder arg(Supplier<?> argSupplier) {
return arg(argSupplier.get());
}

@Override
public boolean log() {
List<Object> args = this.args;
if (args == null) {
logger.log(new DefaultLogEvent(timestamp, threadName, threadId, level, loggerName, message, keyValues,
throwable));
return true;
}
int size = args.size();
LogEvent event = switch (size) {
case 0 ->
new DefaultLogEvent(timestamp, threadName, threadId, level, loggerName, message, keyValues, throwable);
case 1 -> new OneArgLogEvent(timestamp, threadName, threadId, level, loggerName, message, keyValues,
messageFormatter, throwable, args.get(0));
case 2 -> new TwoArgLogEvent(timestamp, threadName, threadId, level, loggerName, message, keyValues,
messageFormatter, throwable, args.get(0), args.get(1));
default -> new ArrayArgLogEvent(timestamp, threadName, threadId, level, loggerName, message, keyValues,
messageFormatter, throwable, args.toArray());
};
logger.log(event);
return true;
}

}

enum NoOpLogEventBuilder implements LogEvent.Builder {

NOOP;

@Override
public Builder timestamp(Instant timestamp) {
return this;
}

@Override
public Builder threadName(String threadName) {
return this;
}

@Override
public Builder threadId(long threadId) {
return this;
}

@Override
public Builder message(String message) {
return this;
}

@Override
public Builder throwable(@Nullable Throwable throwable) {
return this;
}

@Override
public Builder keyValues(KeyValues keyValues) {
return this;
}

@Override
public Builder messageFormatter(LogMessageFormatter messageFormatter) {
return this;
}

@Override
public boolean log() {
return false;
}

@Override
public Builder arg(Supplier<?> argSupplier) {
return this;
}

@Override
public Builder arg(@Nullable Object arg) {
return this;
}

}

enum EmptyLogEvent implements LogEvent {
Expand Down Expand Up @@ -291,7 +547,7 @@ public LogEvent freeze(Instant timestamp) {
}

record OneArgLogEvent(Instant timestamp, String threadName, long threadId, System.Logger.Level level, String loggerName,
String message, KeyValues keyValues, LogMessageFormatter messageFormatter,
String message, KeyValues keyValues, LogMessageFormatter messageFormatter, @Nullable Throwable throwable,
@Nullable Object arg1) implements LogEvent {

public void formattedMessage(StringBuilder sb) {
Expand All @@ -302,10 +558,6 @@ public int argCount() {
return 1;
}

public @Nullable Throwable throwable() {
return null;
}

public LogEvent freeze() {
return freeze(timestamp);
}
Expand All @@ -314,14 +566,14 @@ public LogEvent freeze(Instant timestamp) {
StringBuilder sb = new StringBuilder(message.length());
formattedMessage(sb);
return new DefaultLogEvent(timestamp, threadName, threadId, level, loggerName, sb.toString(),
keyValues.freeze(), null);
keyValues.freeze(), throwable);
}

}

record TwoArgLogEvent(Instant timestamp, String threadName, long threadId, System.Logger.Level level, String loggerName,
String message, KeyValues keyValues, LogMessageFormatter messageFormatter, @Nullable Object arg1,
@Nullable Object arg2) implements LogEvent {
String message, KeyValues keyValues, LogMessageFormatter messageFormatter, @Nullable Throwable throwable,
@Nullable Object arg1, @Nullable Object arg2) implements LogEvent {

public void formattedMessage(StringBuilder sb) {
messageFormatter.format(sb, message, arg1, arg2);
Expand All @@ -331,10 +583,6 @@ public int argCount() {
return 2;
}

public @Nullable Throwable throwable() {
return null;
}

public LogEvent freeze() {
return freeze(timestamp);
}
Expand All @@ -343,13 +591,13 @@ public LogEvent freeze(Instant timestamp) {
StringBuilder sb = new StringBuilder(message.length());
formattedMessage(sb);
return new DefaultLogEvent(timestamp, threadName, threadId, level, loggerName, sb.toString(),
keyValues.freeze(), null);
keyValues.freeze(), throwable);
}
}

record ArrayArgLogEvent(Instant timestamp, String threadName, long threadId, System.Logger.Level level,
String loggerName, String message, KeyValues keyValues, LogMessageFormatter messageFormatter,
Object[] args) implements LogEvent {
@Nullable Throwable throwable, Object[] args) implements LogEvent {

public void formattedMessage(StringBuilder sb) {
messageFormatter.formatArray(sb, message, args);
Expand All @@ -359,10 +607,6 @@ public int argCount() {
return args.length;
}

public @Nullable Throwable throwable() {
return null;
}

public LogEvent freeze() {
return freeze(timestamp);
}
Expand All @@ -371,7 +615,7 @@ public LogEvent freeze(Instant timestamp) {
StringBuilder sb = new StringBuilder(message.length());
formattedMessage(sb);
return new DefaultLogEvent(timestamp, threadName, threadId, level, loggerName, sb.toString(),
keyValues.freeze(), null);
keyValues.freeze(), throwable);
}

}
Expand Down
Loading

0 comments on commit 61eb407

Please sign in to comment.