From 2b88f696cd3c4fa28655027b9c387e6ad8ac28d3 Mon Sep 17 00:00:00 2001 From: Jon Schneider Date: Thu, 18 May 2017 14:30:42 -0500 Subject: [PATCH] Implement @Scheduled timing, changed record -> recordThrowable in Timer, Gradle 4.0 --- gradle/wrapper/gradle-wrapper.jar | Bin 54212 -> 52818 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 19 +++--- .../metrics/boot/EnableMetricsBoot1.java | 12 ++++ .../metrics/instrument/MetricException.java | 28 -------- .../metrics/instrument/ThrowableCallable.java | 12 ++++ .../metrics/instrument/Timer.java | 2 +- .../instrument/internal/AbstractTimer.java | 7 +- .../scheduling/MetricsSchedulingAspect.java | 54 ++++++++++++++++ .../metrics/instrument/TimerTest.java | 4 +- .../MetricsSchedulingAspectTest.java | 60 ++++++++++++++++++ 11 files changed, 153 insertions(+), 49 deletions(-) delete mode 100644 src/main/java/org/springframework/metrics/instrument/MetricException.java create mode 100644 src/main/java/org/springframework/metrics/instrument/ThrowableCallable.java create mode 100644 src/main/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspect.java create mode 100644 src/test/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspectTest.java diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 14c04550e03a7f5b132c354660e0a06d75c046ad..deedc7fa5e6310eac3148a7dd0b1f069b07364cb 100644 GIT binary patch delta 16354 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 delta 17894 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°NoGAn5y-t|>!Z+90D81L3S}8f+(Es=X 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d71ccc3630..2cfc421b76 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Apr 10 14:49:12 CDT 2017 +#Thu May 18 12:01:02 CDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-milestone-2-bin.zip diff --git a/gradlew b/gradlew index 4453ccea33..9aa616c273 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash ############################################################################## ## @@ -154,19 +154,16 @@ if $cygwin ; then esac fi -# Escape application args -save ( ) { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") } -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then +if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then cd "$(dirname "$0")" fi -exec "$JAVACMD" "$@" +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/src/main/java/org/springframework/metrics/boot/EnableMetricsBoot1.java b/src/main/java/org/springframework/metrics/boot/EnableMetricsBoot1.java index 02e0a13923..c091d9aa72 100644 --- a/src/main/java/org/springframework/metrics/boot/EnableMetricsBoot1.java +++ b/src/main/java/org/springframework/metrics/boot/EnableMetricsBoot1.java @@ -32,6 +32,7 @@ import org.springframework.core.env.Environment; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.metrics.instrument.MeterRegistry; +import org.springframework.metrics.instrument.scheduling.MetricsSchedulingAspect; import org.springframework.metrics.instrument.web.*; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -40,6 +41,7 @@ import javax.servlet.http.HttpServletRequest; import java.lang.annotation.*; import java.util.ArrayList; +import java.util.regex.Pattern; /** * Enable dimensional metrics collection. @@ -109,6 +111,16 @@ public WebMetricsTagProvider emptyMetricsTagProvider() { } } + /** + * If AOP is not enabled, scheduled interception will not work. + */ + @Bean + @ConditionalOnClass({RestTemplate.class, JoinPoint.class}) + @ConditionalOnProperty(value = "spring.aop.enabled", havingValue = "true", matchIfMissing = true) + public MetricsSchedulingAspect metricsSchedulingAspect(MeterRegistry registry) { + return new MetricsSchedulingAspect(registry); + } + /** * If AOP is not enabled, client request interception will still work, but the URI tag * will always be evaluated to "none". diff --git a/src/main/java/org/springframework/metrics/instrument/MetricException.java b/src/main/java/org/springframework/metrics/instrument/MetricException.java deleted file mode 100644 index 6d80055f0d..0000000000 --- a/src/main/java/org/springframework/metrics/instrument/MetricException.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright 2017 Pivotal Software, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.metrics.instrument; - -public class MetricException extends RuntimeException { - - public MetricException(String msg, Throwable e) { - super(msg, e); - } - - public MetricException(Throwable e) { - super(e); - } - -} diff --git a/src/main/java/org/springframework/metrics/instrument/ThrowableCallable.java b/src/main/java/org/springframework/metrics/instrument/ThrowableCallable.java new file mode 100644 index 0000000000..aa29294b3b --- /dev/null +++ b/src/main/java/org/springframework/metrics/instrument/ThrowableCallable.java @@ -0,0 +1,12 @@ +package org.springframework.metrics.instrument; + +@FunctionalInterface +public interface ThrowableCallable { + /** + * Computes a result, or throws an exception if unable to do so. + * + * @return computed result + * @throws Throwable if unable to compute a result + */ + V call() throws Throwable; +} diff --git a/src/main/java/org/springframework/metrics/instrument/Timer.java b/src/main/java/org/springframework/metrics/instrument/Timer.java index 33d5183adb..a8f6ce5900 100644 --- a/src/main/java/org/springframework/metrics/instrument/Timer.java +++ b/src/main/java/org/springframework/metrics/instrument/Timer.java @@ -39,7 +39,7 @@ public interface Timer extends Meter { * @param f Function to execute and measure the execution time. * @return The return value of `f`. */ - T record(Callable f) throws MetricException; + T recordThrowable(ThrowableCallable f) throws Throwable; /** * Executes the runnable `f` and records the time taken. diff --git a/src/main/java/org/springframework/metrics/instrument/internal/AbstractTimer.java b/src/main/java/org/springframework/metrics/instrument/internal/AbstractTimer.java index 0e202cffdf..c3b70aaa38 100644 --- a/src/main/java/org/springframework/metrics/instrument/internal/AbstractTimer.java +++ b/src/main/java/org/springframework/metrics/instrument/internal/AbstractTimer.java @@ -16,10 +16,9 @@ package org.springframework.metrics.instrument.internal; import org.springframework.metrics.instrument.Clock; -import org.springframework.metrics.instrument.MetricException; +import org.springframework.metrics.instrument.ThrowableCallable; import org.springframework.metrics.instrument.Timer; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; public abstract class AbstractTimer implements Timer { @@ -32,12 +31,10 @@ protected AbstractTimer(String name, Clock clock) { } @Override - public T record(Callable f) throws MetricException { + public T recordThrowable(ThrowableCallable f) throws Throwable { final long s = clock.monotonicTime(); try { return f.call(); - } catch (Exception e) { - throw new MetricException(e); } finally { final long e = clock.monotonicTime(); record(e - s, TimeUnit.NANOSECONDS); diff --git a/src/main/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspect.java b/src/main/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspect.java new file mode 100644 index 0000000000..f1d04a6543 --- /dev/null +++ b/src/main/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspect.java @@ -0,0 +1,54 @@ +package org.springframework.metrics.instrument.scheduling; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.metrics.instrument.MeterRegistry; +import org.springframework.metrics.instrument.annotation.Timed; + +import java.lang.reflect.Method; + +@Aspect +public class MetricsSchedulingAspect { + protected final Log logger = LogFactory.getLog(MetricsSchedulingAspect.class); + + private final MeterRegistry registry; + + public MetricsSchedulingAspect(MeterRegistry registry) { + this.registry = registry; + } + + @Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))") + public Object timeScheduledOperation(ProceedingJoinPoint pjp) throws Throwable { + Method method = ((MethodSignature) pjp.getSignature()).getMethod(); + + String signature = pjp.getSignature().toShortString(); + + if (method.getDeclaringClass().isInterface()) { + try { + method = pjp.getTarget().getClass().getDeclaredMethod(pjp.getSignature().getName(), + method.getParameterTypes()); + } catch (final SecurityException | NoSuchMethodException e) { + logger.warn("Unable to perform metrics timing on " + signature, e); + return pjp.proceed(); + } + } + + Timed timed = method.getAnnotation(Timed.class); + + if (timed == null) { + logger.debug("Skipping metrics timing on " + signature + ": no @Timed annotation is present on the method"); + return pjp.proceed(); + } + + if (timed.value().isEmpty()) { + logger.warn("Unable to perform metrics timing on " + signature + ": @Timed annotation must have a value used to name the metric"); + return pjp.proceed(); + } + + return registry.timer(timed.value()).recordThrowable(pjp::proceed); + } +} diff --git a/src/test/java/org/springframework/metrics/instrument/TimerTest.java b/src/test/java/org/springframework/metrics/instrument/TimerTest.java index d9f2cfbedf..63e48f161d 100644 --- a/src/test/java/org/springframework/metrics/instrument/TimerTest.java +++ b/src/test/java/org/springframework/metrics/instrument/TimerTest.java @@ -68,7 +68,7 @@ void recordWithRunnable(MeterRegistry registry) throws Exception { Timer t = registry.timer("myTimer"); try { - t.record((Runnable) () -> clock(registry).addAndGetNanos(10)); + t.record(() -> clock(registry).addAndGetNanos(10)); } finally { assertAll(() -> assertEquals(1L, t.count()), () -> assertEquals(10, t.totalTimeNanos() ,1.0e-12)); @@ -82,7 +82,7 @@ void recordCallableException(MeterRegistry registry) { Timer t = registry.timer("myTimer"); assertThrows(Exception.class, () -> { - t.record(() -> { + t.recordThrowable(() -> { clock(registry).addAndGetNanos(10); throw new Exception("uh oh"); }); diff --git a/src/test/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspectTest.java b/src/test/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspectTest.java new file mode 100644 index 0000000000..42c3a76dec --- /dev/null +++ b/src/test/java/org/springframework/metrics/instrument/scheduling/MetricsSchedulingAspectTest.java @@ -0,0 +1,60 @@ +package org.springframework.metrics.instrument.scheduling; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.metrics.boot.EnableMetrics; +import org.springframework.metrics.instrument.MeterRegistry; +import org.springframework.metrics.instrument.Timer; +import org.springframework.metrics.instrument.annotation.Timed; +import org.springframework.metrics.instrument.simple.SimpleMeterRegistry; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SpringExtension.class) +@SpringBootTest +class MetricsSchedulingAspectTest { + + @Autowired + MeterRegistry registry; + + @Test + void scheduledIsInstrumented() { + assertThat(registry.findMeter(Timer.class, "beeper")) + .containsInstanceOf(Timer.class) + .hasValueSatisfying(t -> assertThat(t.count()).isEqualTo(1)); + } + + @SpringBootApplication + @EnableMetrics + @EnableScheduling + static class MetricsApp { + @Bean + MeterRegistry registry() { + return new SimpleMeterRegistry(); + } + + @Timed("beeper") + @Scheduled(fixedRate = 1000) + void beep1() { + System.out.println("beep"); + } + + @Timed // not instrumented because @Timed lacks a metric name + @Scheduled(fixedRate = 1000) + void beep2() { + System.out.println("beep"); + } + + @Scheduled(fixedRate = 1000) // not instrumented because it isn't @Timed + void beep3() { + System.out.println("beep"); + } + } +}