package com.equalexperts.logging.impl; import com.equalexperts.logging.DiagnosticContextSupplier; import com.equalexperts.logging.LogMessage; import com.equalexperts.logging.OpsLogger; import java.time.Clock; import java.util.Optional; import java.util.concurrent.locks.Lock; import java.util.function.Consumer; /** OpsLogger which writes each entry directly to the Destination */ public class BasicOpsLogger<T extends Enum<T> & LogMessage> implements OpsLogger<T> { private final Clock clock; private final Consumer<Throwable> errorHandler; private final Destination<T> destination; private final Lock lock; private final DiagnosticContextSupplier diagnosticContextSupplier; private final boolean closeable; public BasicOpsLogger(Clock clock, DiagnosticContextSupplier diagnosticContextSupplier, Destination<T> destination, Lock lock, Consumer<Throwable> errorHandler) { this(clock, diagnosticContextSupplier, destination, lock, errorHandler, true); } private BasicOpsLogger(Clock clock, DiagnosticContextSupplier diagnosticContextSupplier, Destination<T> destination, Lock lock, Consumer<Throwable> errorHandler, boolean closeable) { this.clock = clock; this.diagnosticContextSupplier = diagnosticContextSupplier; this.destination = destination; this.lock = lock; this.errorHandler = errorHandler; this.closeable = closeable; } @Override public void close() throws Exception { if (closeable) { destination.close(); } } @Override public void log(T message, Object... details) { try { LogicalLogRecord<T> record = constructLogRecord(message, Optional.empty(), details); publish(record); } catch (Throwable t) { errorHandler.accept(t); } } @Override public void logThrowable(T message, Throwable cause, Object... details) { try { LogicalLogRecord<T> record = constructLogRecord(message, Optional.of(cause), details); publish(record); } catch (Throwable t) { errorHandler.accept(t); } } @Override public BasicOpsLogger<T> with(DiagnosticContextSupplier override) { return new BasicOpsLogger<>(clock, override, destination, lock, errorHandler, false); } private LogicalLogRecord<T> constructLogRecord(T message, Optional<Throwable> o, Object... details) { return new LogicalLogRecord<>(clock.instant(), new DiagnosticContext(diagnosticContextSupplier), message, o, details); } private void publish(LogicalLogRecord<T> record) throws Exception { lock.lock(); try { destination.beginBatch(); try { destination.publish(record); } finally { destination.endBatch(); } } finally { lock.unlock(); } } public Clock getClock() { return clock; } public Destination<T> getDestination() { return destination; } public DiagnosticContextSupplier getDiagnosticContextSupplier() { return diagnosticContextSupplier; } public Lock getLock() { return lock; } public Consumer<Throwable> getErrorHandler() { return errorHandler; } }