From 78d08ae362381c990a90d574c8aedf84af18669e Mon Sep 17 00:00:00 2001 From: Simon Schneider <10846939+raynigon@users.noreply.github.com> Date: Tue, 8 Nov 2022 14:58:45 +0100 Subject: [PATCH] Allow Metrics to be disabled if not needed --- .../async/service/AsyncMetricsService.java | 11 +++++ .../async/service/DefaultAsyncService.java | 32 ++++++-------- .../service/MicrometerMetricsService.java | 43 +++++++++++++++++++ .../async/service/NoOpMetricsService.java | 21 +++++++++ .../service/helper/MicrometerSample.java | 17 ++++++++ .../async/service/helper/MicrometerTimer.java | 41 ++++++++++++++++++ .../async/service/helper/NoOpSample.java | 4 ++ .../async/service/helper/NoOpTimer.java | 29 +++++++++++++ .../async/service/helper/SampleWrapper.java | 5 +++ .../async/service/helper/TimerWrapper.java | 14 ++++++ 10 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/AsyncMetricsService.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/MicrometerMetricsService.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/NoOpMetricsService.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerSample.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerTimer.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpSample.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpTimer.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/SampleWrapper.java create mode 100644 ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/TimerWrapper.java diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/AsyncMetricsService.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/AsyncMetricsService.java new file mode 100644 index 0000000..9e096c8 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/AsyncMetricsService.java @@ -0,0 +1,11 @@ +package com.raynigon.ecs.logging.async.service; + +import com.raynigon.ecs.logging.async.service.helper.TimerWrapper; + +public interface AsyncMetricsService { + + TimerWrapper createQueueTimer(Class source); + + TimerWrapper createExecutionTimer(Class source); +} + diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/DefaultAsyncService.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/DefaultAsyncService.java index 313ab3e..9bacc9a 100644 --- a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/DefaultAsyncService.java +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/DefaultAsyncService.java @@ -1,6 +1,8 @@ package com.raynigon.ecs.logging.async.service; import com.raynigon.ecs.logging.async.executor.MdcForkJoinPool; +import com.raynigon.ecs.logging.async.service.helper.SampleWrapper; +import com.raynigon.ecs.logging.async.service.helper.TimerWrapper; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; import lombok.RequiredArgsConstructor; @@ -17,24 +19,22 @@ @RequiredArgsConstructor public class DefaultAsyncService implements AsyncService { - private static final String QUEUE_TIMER_NAME = "raynigon.async.service.queue.duration"; - private static final String EXECUTION_TIMER_NAME = "raynigon.async.service.execution.duration"; + private final MdcForkJoinPool forkJoinPool; - private final MeterRegistry meterRegistry; + private final AsyncMetricsService metrics; private static final Logger log = LoggerFactory.getLogger(DefaultAsyncService.class); @Override public CompletableFuture supplyAsync(Supplier supplier) { - String sourceName = formatSource(supplier.getClass()); - Timer queueTimer = meterRegistry.timer(QUEUE_TIMER_NAME, "source", sourceName); - Timer execTimer = meterRegistry.timer(EXECUTION_TIMER_NAME, "source", sourceName); - Timer.Sample sample = Timer.start(); + TimerWrapper queueTimer = metrics.createQueueTimer(supplier.getClass()); + TimerWrapper execTimer = metrics.createExecutionTimer(supplier.getClass()); + SampleWrapper sample = queueTimer.start(); Supplier wrapped = () -> { - long nanoseconds = sample.stop(queueTimer); - log.trace("The supplier {} took {} ms in Queue", sourceName, nanoseconds / 1000000.0); + long nanoseconds = queueTimer.stop(sample); + log.trace("The supplier {} took {} ms in Queue", supplier.getClass(), nanoseconds / 1000000.0); return execTimer.record(supplier); }; log.trace("Add supplier {} to ForkJoinPool", supplier); @@ -43,19 +43,15 @@ public CompletableFuture supplyAsync(Supplier supplier) { @Override public ForkJoinTask submit(Callable callable) { - String sourceName = formatSource(callable.getClass()); - Timer queueTimer = meterRegistry.timer(QUEUE_TIMER_NAME, "source", sourceName); - Timer execTimer = meterRegistry.timer(EXECUTION_TIMER_NAME, "source", sourceName); - Timer.Sample sample = Timer.start(); + TimerWrapper queueTimer = metrics.createQueueTimer(callable.getClass()); + TimerWrapper execTimer = metrics.createExecutionTimer(callable.getClass()); + SampleWrapper sample = queueTimer.start(); Callable wrapped = () -> { - long nanoseconds = sample.stop(queueTimer); - log.trace("The callable {} took {} ms in Queue", sourceName, nanoseconds / 1000000.0); + long nanoseconds = queueTimer.stop(sample); + log.trace("The callable {} took {} ms in Queue", callable.getClass(), nanoseconds / 1000000.0); return execTimer.recordCallable(callable); }; return forkJoinPool.submit(wrapped); } - private String formatSource(Class source){ - return source.getName().split("/")[0]; - } } diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/MicrometerMetricsService.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/MicrometerMetricsService.java new file mode 100644 index 0000000..06dce62 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/MicrometerMetricsService.java @@ -0,0 +1,43 @@ +package com.raynigon.ecs.logging.async.service; + +import com.raynigon.ecs.logging.async.service.helper.MicrometerTimer; +import com.raynigon.ecs.logging.async.service.helper.TimerWrapper; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +@ConditionalOnClass(MeterRegistry.class) +@ConditionalOnProperty(name = "raynigon.logging.async.metrics.enabled", havingValue = "true") +public class MicrometerMetricsService implements AsyncMetricsService { + + + private static final String QUEUE_TIMER_NAME = "raynigon.async.service.queue.duration"; + private static final String EXECUTION_TIMER_NAME = "raynigon.async.service.execution.duration"; + + private final MeterRegistry meterRegistry; + + @Override + public TimerWrapper createQueueTimer(Class source) { + Timer timer = meterRegistry.timer(QUEUE_TIMER_NAME, "source", formatSource(source)); + return wrap(timer); + } + + @Override + public TimerWrapper createExecutionTimer(Class source) { + Timer timer = meterRegistry.timer(EXECUTION_TIMER_NAME, "source", formatSource(source)); + return wrap(timer); + } + + private TimerWrapper wrap(Timer timer) { + return new MicrometerTimer(timer); + } + + private String formatSource(Class source) { + return source.getName().split("/")[0]; + } +} diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/NoOpMetricsService.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/NoOpMetricsService.java new file mode 100644 index 0000000..6374b89 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/NoOpMetricsService.java @@ -0,0 +1,21 @@ +package com.raynigon.ecs.logging.async.service; + +import com.raynigon.ecs.logging.async.service.helper.NoOpTimer; +import com.raynigon.ecs.logging.async.service.helper.TimerWrapper; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Service; + +@Service +@ConditionalOnMissingBean(AsyncMetricsService.class) +public class NoOpMetricsService implements AsyncMetricsService { + @Override + public TimerWrapper createQueueTimer(Class source) { + return new NoOpTimer(); + } + + @Override + public TimerWrapper createExecutionTimer(Class source) { + return new NoOpTimer(); + } +} diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerSample.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerSample.java new file mode 100644 index 0000000..6139421 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerSample.java @@ -0,0 +1,17 @@ +package com.raynigon.ecs.logging.async.service.helper; + +import io.micrometer.core.instrument.Timer; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class MicrometerSample implements SampleWrapper { + + private final Timer timer; + private final Timer.Sample sample; + + public long stop() { + return sample.stop(timer); + } +} diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerTimer.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerTimer.java new file mode 100644 index 0000000..0aa7f52 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/MicrometerTimer.java @@ -0,0 +1,41 @@ +package com.raynigon.ecs.logging.async.service.helper; + +import io.micrometer.core.instrument.Timer; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; + +import java.util.concurrent.Callable; +import java.util.function.Supplier; + +@RequiredArgsConstructor +public class MicrometerTimer implements TimerWrapper{ + + private final Timer timer; + + @Override + @SneakyThrows + public V recordCallable(Callable callable) { + return timer.recordCallable(callable); + } + + @Override + public U record(Supplier supplier) { + return timer.record(supplier); + } + + @Override + public SampleWrapper start() { + return wrap(timer, Timer.start()); + } + + @Override + public long stop(SampleWrapper wrapper) { + MicrometerSample sample = (MicrometerSample) wrapper; + return sample.stop(); + } + + private SampleWrapper wrap(Timer timer, Timer.Sample sample) { + return new MicrometerSample(timer, sample); + } +} diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpSample.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpSample.java new file mode 100644 index 0000000..9ceb266 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpSample.java @@ -0,0 +1,4 @@ +package com.raynigon.ecs.logging.async.service.helper; + +public class NoOpSample implements SampleWrapper { +} diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpTimer.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpTimer.java new file mode 100644 index 0000000..d21bb09 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/NoOpTimer.java @@ -0,0 +1,29 @@ +package com.raynigon.ecs.logging.async.service.helper; + +import lombok.SneakyThrows; + +import java.util.concurrent.Callable; +import java.util.function.Supplier; + +public class NoOpTimer implements TimerWrapper { + @Override + @SneakyThrows + public V recordCallable(Callable callable) { + return callable.call(); + } + + @Override + public U record(Supplier supplier) { + return supplier.get(); + } + + @Override + public SampleWrapper start() { + return new NoOpSample(); + } + + @Override + public long stop(SampleWrapper wrapper) { + return -1; + } +} diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/SampleWrapper.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/SampleWrapper.java new file mode 100644 index 0000000..088d931 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/SampleWrapper.java @@ -0,0 +1,5 @@ +package com.raynigon.ecs.logging.async.service.helper; + +public interface SampleWrapper { + +} diff --git a/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/TimerWrapper.java b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/TimerWrapper.java new file mode 100644 index 0000000..5d211b5 --- /dev/null +++ b/ecs-logging-async/src/main/java/com/raynigon/ecs/logging/async/service/helper/TimerWrapper.java @@ -0,0 +1,14 @@ +package com.raynigon.ecs.logging.async.service.helper; + +import java.util.concurrent.Callable; +import java.util.function.Supplier; + +public interface TimerWrapper { + V recordCallable(Callable callable); + + U record(Supplier supplier); + + SampleWrapper start(); + + long stop(SampleWrapper wrapper); +}