io.jstach.rainbowgum.disruptor.DisruptorLogPublisher Maven / Gradle / Ivy
package io.jstach.rainbowgum.disruptor;
import java.util.concurrent.ThreadFactory;
import org.eclipse.jdt.annotation.Nullable;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.ExceptionHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import io.jstach.rainbowgum.MetaLog;
import io.jstach.rainbowgum.LogAppender;
import io.jstach.rainbowgum.LogConfig;
import io.jstach.rainbowgum.LogEvent;
import io.jstach.rainbowgum.LogPublisher.AsyncLogPublisher;
/**
* Disruptor async publisher.
*/
public final class DisruptorLogPublisher implements AsyncLogPublisher {
private final Disruptor disruptor;
private final RingBuffer ringBuffer;
/**
* Creates.
* @param appenders appenders.
* @param threadFactory thread factory to create writer thread.
* @param bufferSize maximum queue elements.
* @return publisher.
*/
public static DisruptorLogPublisher of(Iterable extends LogAppender> appenders, ThreadFactory threadFactory,
int bufferSize) {
Disruptor disruptor = new Disruptor<>(LogEventCell::new, bufferSize, threadFactory);
disruptor.setDefaultExceptionHandler(new LogExceptionHandler(disruptor::shutdown));
boolean found = false;
for (var appender : appenders) {
disruptor.handleEventsWith(new LogEventHandler(appender));
found = true;
}
if (!found) {
throw new IllegalStateException();
}
var ringBuffer = disruptor.getRingBuffer();
var router = new DisruptorLogPublisher(disruptor, ringBuffer);
return router;
}
@Override
public void start(LogConfig config) {
disruptor.start();
}
DisruptorLogPublisher(Disruptor disruptor, RingBuffer ringBuffer) {
super();
this.disruptor = disruptor;
this.ringBuffer = ringBuffer;
}
@Override
public void log(LogEvent event) {
long sequence = ringBuffer.next();
try {
LogEventCell cell = ringBuffer.get(sequence);
cell.event = event;
}
finally {
ringBuffer.publish(sequence);
}
}
@Override
public void close() {
this.disruptor.halt();
}
private static class LogEventCell {
@Nullable
LogEvent event;
}
private static record LogEventHandler(LogAppender appender) implements EventHandler {
@Override
public void onEvent(LogEventCell event, long sequence, boolean endOfBatch) throws Exception {
var logEvent = event.event;
if (logEvent == null) {
return;
}
appender.append(logEvent);
}
}
private record LogExceptionHandler(Runnable shutdownHook) implements ExceptionHandler
© 2015 - 2025 Weber Informatics LLC | Privacy Policy