import dev.caskeleton.adapter.outbound.notification.core.FailOpenNotificationProvider; import dev.caskeleton.adapter.outbound.notification.core.NotificationProvider; import dev.caskeleton.adapter.outbound.support.FailOpenDependencyLogger; import dev.caskeleton.application.notification.Channel; import dev.caskeleton.application.notification.Notification; import java.lang.reflect.Proxy; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; public class NotificationLoggerFailureProbe { private static Logger loggerThatThrowsOn(String methodToThrow, AtomicInteger debug, AtomicInteger warn) { return (Logger) Proxy.newProxyInstance( NotificationLoggerFailureProbe.class.getClassLoader(), new Class[] {Logger.class}, (proxy, method, args) -> { if (method.getName().equals("debug")) debug.incrementAndGet(); if (method.getName().equals("warn")) warn.incrementAndGet(); if (method.getName().equals(methodToThrow)) { throw new IllegalStateException("logger-" + methodToThrow + "-failed"); } if (method.getReturnType() == boolean.class) return true; if (method.getReturnType() == String.class) return "probe.notification"; return null; }); } public static void main(String[] args) { Notification n = new Notification("secret@gmail.com", "subject", "body"); AtomicInteger sends = new AtomicInteger(); AtomicInteger debug = new AtomicInteger(); AtomicInteger warn = new AtomicInteger(); NotificationProvider successful = new NotificationProvider() { public Channel channel() { return Channel.EMAIL; } public String providerId() { return "google-email"; } public void send(Notification ignored) { sends.incrementAndGet(); } }; var successPath = new FailOpenNotificationProvider( successful, new FailOpenDependencyLogger(loggerThatThrowsOn("debug", debug, warn))); successPath.send(n); System.out.printf("SUCCESS_PATH sends=%d debugCalls=%d warnCalls=%d%n", sends.get(), debug.get(), warn.get()); AtomicInteger failDebug = new AtomicInteger(); AtomicInteger failWarn = new AtomicInteger(); NotificationProvider failing = new NotificationProvider() { public Channel channel() { return Channel.EMAIL; } public String providerId() { return "google-email"; } public void send(Notification ignored) { throw new RuntimeException("provider-failed"); } }; var failurePath = new FailOpenNotificationProvider( failing, new FailOpenDependencyLogger(loggerThatThrowsOn("warn", failDebug, failWarn))); try { failurePath.send(n); System.out.println("FAILURE_PATH propagated=none"); } catch (RuntimeException ex) { System.out.printf("FAILURE_PATH propagated=%s:%s warnCalls=%d%n", ex.getClass().getSimpleName(), ex.getMessage(), failWarn.get()); } } }