diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/AbstractTimer.java b/spectator-api/src/main/java/com/netflix/spectator/api/AbstractTimer.java index c772a24b9..1306d673e 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/AbstractTimer.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/AbstractTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,6 @@ */ package com.netflix.spectator.api; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - - /** * Base class to simplify implementing a {@link Timer}. */ @@ -32,23 +28,7 @@ public AbstractTimer(Clock clock) { this.clock = clock; } - @Override public T record(Callable f) throws Exception { - final long s = clock.monotonicTime(); - try { - return f.call(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } - } - - @Override public void record(Runnable f) { - final long s = clock.monotonicTime(); - try { - f.run(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } + @Override public Clock clock() { + return clock; } } diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/CompositeTimer.java b/spectator-api/src/main/java/com/netflix/spectator/api/CompositeTimer.java index 9ec77a20a..2001f017d 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/CompositeTimer.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/CompositeTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ import java.util.Collection; import java.util.Iterator; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** Timer implementation for the composite registry. */ @@ -31,32 +30,16 @@ final class CompositeTimer extends CompositeMeter implements Timer { this.clock = clock; } + @Override public Clock clock() { + return clock; + } + @Override public void record(long amount, TimeUnit unit) { for (Timer t : meters) { t.record(amount, unit); } } - @Override public T record(Callable f) throws Exception { - final long s = clock.monotonicTime(); - try { - return f.call(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } - } - - @Override public void record(Runnable f) { - final long s = clock.monotonicTime(); - try { - f.run(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } - } - @Override public long count() { Iterator it = meters.iterator(); return it.hasNext() ? it.next().count() : 0L; diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/NoopTimer.java b/spectator-api/src/main/java/com/netflix/spectator/api/NoopTimer.java index ad8738a42..d92641f4d 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/NoopTimer.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/NoopTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.netflix.spectator.api; import java.util.Collections; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** Counter implementation for the no-op registry. */ @@ -39,14 +38,6 @@ enum NoopTimer implements Timer { return Collections.emptyList(); } - @Override public T record(Callable f) throws Exception { - return f.call(); - } - - @Override public void record(Runnable f) { - f.run(); - } - @Override public long count() { return 0L; } diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/SwapTimer.java b/spectator-api/src/main/java/com/netflix/spectator/api/SwapTimer.java index 1e5ff4823..a576f4732 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/SwapTimer.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/SwapTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ import com.netflix.spectator.impl.SwapMeter; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.LongSupplier; @@ -35,28 +34,12 @@ final class SwapTimer extends SwapMeter implements Timer { return registry.timer(id); } - @Override public void record(long amount, TimeUnit unit) { - get().record(amount, unit); - } - - @Override public T record(Callable f) throws Exception { - final long s = registry.clock().monotonicTime(); - try { - return f.call(); - } finally { - final long e = registry.clock().monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } + @Override public Clock clock() { + return registry.clock(); } - @Override public void record(Runnable f) { - final long s = registry.clock().monotonicTime(); - try { - f.run(); - } finally { - final long e = registry.clock().monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } + @Override public void record(long amount, TimeUnit unit) { + get().record(amount, unit); } @Override public long count() { diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/Timer.java b/spectator-api/src/main/java/com/netflix/spectator/api/Timer.java index 87bcbaea4..1a5f7fdb8 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/Timer.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/Timer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,11 @@ import java.time.Duration; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; +import java.util.function.DoubleSupplier; +import java.util.function.IntSupplier; +import java.util.function.LongSupplier; +import java.util.function.Supplier; /** * Timer intended to track a large number of short running events. Example would be something like @@ -30,6 +35,14 @@ * will always return 0. */ public interface Timer extends Meter { + + /** + * The clock used for timing events. + */ + default Clock clock() { + return Clock.SYSTEM; + } + /** * Updates the statistics kept by the timer with the specified amount. * @@ -95,6 +108,34 @@ default void record(Duration[] amounts, int n) { } } + /** + * Executes the callable `f` and records the time taken. + * + * @param f + * Function to execute and measure the execution time. + * @return + * The return value of `f`. + * + * @deprecated Use {@link #recordCallable(Callable)} instead. + */ + @Deprecated + default T record(Callable f) throws Exception { + return recordCallable(f); + } + + /** + * Executes the runnable `f` and records the time taken. + * + * @param f + * Function to execute and measure the execution time. + * + * @deprecated Use {@link #recordRunnable(Runnable)} instead. + */ + @Deprecated + default void record(Runnable f) { + recordRunnable(f); + } + /** * Executes the callable `f` and records the time taken. * @@ -103,7 +144,16 @@ default void record(Duration[] amounts, int n) { * @return * The return value of `f`. */ - T record(Callable f) throws Exception; + default T recordCallable(Callable f) throws Exception { + final Clock clock = clock(); + long s = clock.monotonicTime(); + try { + return f.call(); + } finally { + long e = clock.monotonicTime(); + record(e - s, TimeUnit.NANOSECONDS); + } + } /** * Executes the runnable `f` and records the time taken. @@ -111,7 +161,111 @@ default void record(Duration[] amounts, int n) { * @param f * Function to execute and measure the execution time. */ - void record(Runnable f); + default void recordRunnable(Runnable f) { + final Clock clock = clock(); + long s = clock.monotonicTime(); + try { + f.run(); + } finally { + long e = clock.monotonicTime(); + record(e - s, TimeUnit.NANOSECONDS); + } + } + + /** + * Executes the callable `f` and records the time taken. + * + * @param f + * Function to execute and measure the execution time. + * @return + * The return value of `f`. + */ + default T recordSupplier(Supplier f) { + final Clock clock = clock(); + long s = clock.monotonicTime(); + try { + return f.get(); + } finally { + long e = clock.monotonicTime(); + record(e - s, TimeUnit.NANOSECONDS); + } + } + + /** + * Executes the callable `f` and records the time taken. + * + * @param f + * Function to execute and measure the execution time. + * @return + * The return value of `f`. + */ + default boolean recordBooleanSupplier(BooleanSupplier f) { + final Clock clock = clock(); + long s = clock.monotonicTime(); + try { + return f.getAsBoolean(); + } finally { + long e = clock.monotonicTime(); + record(e - s, TimeUnit.NANOSECONDS); + } + } + + /** + * Executes the callable `f` and records the time taken. + * + * @param f + * Function to execute and measure the execution time. + * @return + * The return value of `f`. + */ + default double recordDoubleSupplier(DoubleSupplier f) { + final Clock clock = clock(); + long s = clock.monotonicTime(); + try { + return f.getAsDouble(); + } finally { + long e = clock.monotonicTime(); + record(e - s, TimeUnit.NANOSECONDS); + } + } + + /** + * Executes the callable `f` and records the time taken. + * + * @param f + * Function to execute and measure the execution time. + * @return + * The return value of `f`. + */ + default int recordIntSupplier(IntSupplier f) { + final Clock clock = clock(); + long s = clock.monotonicTime(); + try { + return f.getAsInt(); + } finally { + long e = clock.monotonicTime(); + record(e - s, TimeUnit.NANOSECONDS); + } + } + + /** + * Executes the callable `f` and records the time taken. + * + * @param f + * Function to execute and measure the execution time. + * @return + * The return value of `f`. + */ + default long recordLongSupplier(LongSupplier f) { + final Clock clock = clock(); + long s = clock.monotonicTime(); + try { + return f.getAsLong(); + } finally { + long e = clock.monotonicTime(); + record(e - s, TimeUnit.NANOSECONDS); + } + } /** * The number of times that record has been called since this timer was last reset. @@ -133,7 +287,7 @@ default void record(Duration[] amounts, int n) { * cost, but the updates may be delayed a bit in reaching the meter. The updates will only * be seen after the updater is explicitly flushed. * - * The caller should ensure that the updater is closed after using to guarantee any resources + *

The caller should ensure that the updater is closed after using to guarantee any resources * associated with it are cleaned up. In some cases failure to close the updater could result * in a memory leak. * diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/histogram/BucketTimer.java b/spectator-api/src/main/java/com/netflix/spectator/api/histogram/BucketTimer.java index b96ce699c..11d675862 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/histogram/BucketTimer.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/histogram/BucketTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2021 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ import com.netflix.spectator.api.Utils; import java.util.Collections; -import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -76,33 +75,15 @@ public static BucketTimer get(Registry registry, Id id, LongFunction f) return false; } + @Override public Clock clock() { + return registry.clock(); + } + @Override public void record(long amount, TimeUnit unit) { final long nanos = unit.toNanos(amount); timer(f.apply(nanos)).record(amount, unit); } - @Override public T record(Callable rf) throws Exception { - final Clock clock = registry.clock(); - final long s = clock.monotonicTime(); - try { - return rf.call(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } - } - - @Override public void record(Runnable rf) { - final Clock clock = registry.clock(); - final long s = clock.monotonicTime(); - try { - rf.run(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } - } - /** Return the timer for a given bucket. */ Timer timer(String bucket) { return Utils.computeIfAbsent(timers, bucket, timerFactory); diff --git a/spectator-api/src/main/java/com/netflix/spectator/api/histogram/PercentileTimer.java b/spectator-api/src/main/java/com/netflix/spectator/api/histogram/PercentileTimer.java index 0960ed65f..960890107 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/api/histogram/PercentileTimer.java +++ b/spectator-api/src/main/java/com/netflix/spectator/api/histogram/PercentileTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,6 @@ import java.time.Duration; import java.util.Collections; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReferenceArray; @@ -153,7 +152,7 @@ public Builder withRange(Duration min, Duration max) { * for the important range of values and reduce the overhead associated with tracking the * data distribution. * - * For example, suppose you are making a client call and timeout after 10 seconds. Setting + *

For example, suppose you are making a client call and timeout after 10 seconds. Setting * the range to 10 seconds will restrict the possible set of buckets used to those * approaching the boundary. So we can still detect if it is nearing failure, but percentiles * that are further away from the range may be inflated compared to the actual value. @@ -246,34 +245,16 @@ private long restrict(long amount) { return Math.max(v, min); } + @Override public Clock clock() { + return registry.clock(); + } + @Override public void record(long amount, TimeUnit unit) { final long nanos = restrict(unit.toNanos(amount)); timer.record(amount, unit); counterFor(PercentileBuckets.indexOf(nanos)).increment(); } - @Override public T record(Callable rf) throws Exception { - final Clock clock = registry.clock(); - final long s = clock.monotonicTime(); - try { - return rf.call(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } - } - - @Override public void record(Runnable rf) { - final Clock clock = registry.clock(); - final long s = clock.monotonicTime(); - try { - rf.run(); - } finally { - final long e = clock.monotonicTime(); - record(e - s, TimeUnit.NANOSECONDS); - } - } - /** * Computes the specified percentile for this timer. The unit will be seconds. * diff --git a/spectator-api/src/main/java/com/netflix/spectator/impl/Scheduler.java b/spectator-api/src/main/java/com/netflix/spectator/impl/Scheduler.java index 4716e90df..6affbfba0 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/impl/Scheduler.java +++ b/spectator-api/src/main/java/com/netflix/spectator/impl/Scheduler.java @@ -486,7 +486,7 @@ private final class Worker implements Runnable { final long delay = clock.wallTime() - task.getNextExecutionTime(); stats.taskExecutionDelay().record(delay, TimeUnit.MILLISECONDS); - stats.taskExecutionTime().record(() -> task.runAndReschedule(queue, stats)); + stats.taskExecutionTime().recordRunnable(() -> task.runAndReschedule(queue, stats)); } catch (InterruptedException e) { LOGGER.debug("task interrupted", e); break; diff --git a/spectator-ext-sandbox/src/main/java/com/netflix/spectator/sandbox/BucketTimer.java b/spectator-ext-sandbox/src/main/java/com/netflix/spectator/sandbox/BucketTimer.java index d496873dd..137f8947b 100644 --- a/spectator-ext-sandbox/src/main/java/com/netflix/spectator/sandbox/BucketTimer.java +++ b/spectator-ext-sandbox/src/main/java/com/netflix/spectator/sandbox/BucketTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,13 +15,13 @@ */ package com.netflix.spectator.sandbox; +import com.netflix.spectator.api.Clock; import com.netflix.spectator.api.Id; import com.netflix.spectator.api.Measurement; import com.netflix.spectator.api.Registry; import com.netflix.spectator.api.Spectator; import com.netflix.spectator.api.Timer; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** @@ -85,16 +85,12 @@ public static BucketTimer get(Registry registry, Id id, BucketFunction f) { return t.hasExpired(); } - @Override public void record(long amount, TimeUnit unit) { - t.record(amount, unit); - } - - @Override public T record(Callable rf) throws Exception { - return t.record(rf); + @Override public Clock clock() { + return t.clock(); } - @Override public void record(Runnable rf) { - t.record(rf); + @Override public void record(long amount, TimeUnit unit) { + t.record(amount, unit); } @Override public long count() { diff --git a/spectator-reg-atlas/src/main/java/com/netflix/spectator/atlas/AtlasTimer.java b/spectator-reg-atlas/src/main/java/com/netflix/spectator/atlas/AtlasTimer.java index a8eb0c952..9c75bd84c 100644 --- a/spectator-reg-atlas/src/main/java/com/netflix/spectator/atlas/AtlasTimer.java +++ b/spectator-reg-atlas/src/main/java/com/netflix/spectator/atlas/AtlasTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import com.netflix.spectator.impl.StepValue; import java.time.Duration; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -95,6 +94,10 @@ private void reportMaxMeasurement(long now, MeasurementConsumer consumer, Id mid consumer.accept(mid, timestamp, maxValue); } + @Override public Clock clock() { + return clock; + } + @Override public void record(long amount, TimeUnit unit) { long now = clock.wallTime(); count.getCurrent(now).incrementAndGet(); @@ -166,24 +169,6 @@ private void updateMax(AtomicLong maxValue, long v) { } } - @Override public T record(Callable f) throws Exception { - final long start = clock.monotonicTime(); - try { - return f.call(); - } finally { - record(clock.monotonicTime() - start, TimeUnit.NANOSECONDS); - } - } - - @Override public void record(Runnable f) { - final long start = clock.monotonicTime(); - try { - f.run(); - } finally { - record(clock.monotonicTime() - start, TimeUnit.NANOSECONDS); - } - } - @Override public long count() { return count.poll(); } diff --git a/spectator-reg-micrometer/src/main/java/com/netflix/spectator/micrometer/MicrometerTimer.java b/spectator-reg-micrometer/src/main/java/com/netflix/spectator/micrometer/MicrometerTimer.java index 6a8e8a675..ceb1e8c24 100644 --- a/spectator-reg-micrometer/src/main/java/com/netflix/spectator/micrometer/MicrometerTimer.java +++ b/spectator-reg-micrometer/src/main/java/com/netflix/spectator/micrometer/MicrometerTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2019 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import com.netflix.spectator.api.Measurement; import com.netflix.spectator.api.Timer; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** @@ -39,14 +38,6 @@ class MicrometerTimer extends MicrometerMeter implements Timer { impl.record(amount, unit); } - @Override public T record(Callable f) throws Exception { - return impl.recordCallable(f); - } - - @Override public void record(Runnable f) { - impl.record(f); - } - @Override public long count() { return impl.count(); } diff --git a/spectator-reg-sidecar/src/main/java/com/netflix/spectator/sidecar/SidecarTimer.java b/spectator-reg-sidecar/src/main/java/com/netflix/spectator/sidecar/SidecarTimer.java index 930f170c4..60718f29e 100644 --- a/spectator-reg-sidecar/src/main/java/com/netflix/spectator/sidecar/SidecarTimer.java +++ b/spectator-reg-sidecar/src/main/java/com/netflix/spectator/sidecar/SidecarTimer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import com.netflix.spectator.api.Id; import com.netflix.spectator.api.Timer; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** @@ -37,6 +36,10 @@ class SidecarTimer extends SidecarMeter implements Timer { this.writer = writer; } + @Override public Clock clock() { + return clock; + } + @Override public void record(long amount, TimeUnit unit) { final double seconds = unit.toNanos(amount) / 1e9; if (seconds >= 0.0) { @@ -44,24 +47,6 @@ class SidecarTimer extends SidecarMeter implements Timer { } } - @Override public T record(Callable f) throws Exception { - final long start = clock.monotonicTime(); - try { - return f.call(); - } finally { - record(clock.monotonicTime() - start, TimeUnit.NANOSECONDS); - } - } - - @Override public void record(Runnable f) { - final long start = clock.monotonicTime(); - try { - f.run(); - } finally { - record(clock.monotonicTime() - start, TimeUnit.NANOSECONDS); - } - } - @Override public long count() { return 0L; }