From d9c031d58491be18b031a65c2f9483e8af6840c8 Mon Sep 17 00:00:00 2001 From: Jonatan Ivanov Date: Wed, 6 Nov 2024 14:44:28 -0800 Subject: [PATCH] Add docs for multiple MeterTag annotations See https://github.com/micrometer-metrics/micrometer/issues/4081 --- .../modules/ROOT/pages/concepts/counters.adoc | 4 + docs/modules/ROOT/pages/concepts/timers.adoc | 4 + .../docs/metrics/CountedAspectTest.java | 63 +++++++++++ .../docs/metrics/TimedAspectTest.java | 61 ++++++++++ .../spring6/aop/CountedAspectTest.java | 106 +++++++++++++++++- .../samples/spring6/aop/TimedAspectTest.java | 20 ++-- 6 files changed, 245 insertions(+), 13 deletions(-) diff --git a/docs/modules/ROOT/pages/concepts/counters.adoc b/docs/modules/ROOT/pages/concepts/counters.adoc index 288685c456..fa0cf86e81 100644 --- a/docs/modules/ROOT/pages/concepts/counters.adoc +++ b/docs/modules/ROOT/pages/concepts/counters.adoc @@ -118,6 +118,10 @@ include::{include-java}/metrics/CountedAspectTest.java[tags=example_value_resolv // Example for calling the provided include::{include-java}/metrics/CountedAspectTest.java[tags=example_value_spel,indent=0] + +// Example for using multiple @MeterTag annotations on the same parameter +// @MeterTags({ @MeterTag(...), @MeterTag(...) }) can be also used +include::{include-java}/metrics/CountedAspectTest.java[tags=example_multi_annotations,indent=0] ----- == Function-tracking Counters diff --git a/docs/modules/ROOT/pages/concepts/timers.adoc b/docs/modules/ROOT/pages/concepts/timers.adoc index 697083df3b..225f55a399 100644 --- a/docs/modules/ROOT/pages/concepts/timers.adoc +++ b/docs/modules/ROOT/pages/concepts/timers.adoc @@ -144,6 +144,10 @@ include::{include-java}/metrics/TimedAspectTest.java[tags=example_value_resolver // Example for calling the provided include::{include-java}/metrics/TimedAspectTest.java[tags=example_value_spel,indent=0] + +// Example for using multiple @MeterTag annotations on the same parameter +// @MeterTags({ @MeterTag(...), @MeterTag(...) }) can be also used +include::{include-java}/metrics/TimedAspectTest.java[tags=example_multi_annotations,indent=0] ----- == Function-tracking Timers diff --git a/docs/src/test/java/io/micrometer/docs/metrics/CountedAspectTest.java b/docs/src/test/java/io/micrometer/docs/metrics/CountedAspectTest.java index 29dcba5d48..b1889f0538 100644 --- a/docs/src/test/java/io/micrometer/docs/metrics/CountedAspectTest.java +++ b/docs/src/test/java/io/micrometer/docs/metrics/CountedAspectTest.java @@ -107,6 +107,30 @@ void meterTagsWithExpression(AnnotatedTestClass annotatedClass) { // end::example_value_spel[] } + @ParameterizedTest + @EnumSource(AnnotatedTestClass.class) + void multipleMeterTagsWithExpression(AnnotatedTestClass annotatedClass) { + MeterRegistry registry = new SimpleMeterRegistry(); + CountedAspect countedAspect = new CountedAspect(registry); + countedAspect.setMeterTagAnnotationHandler( + new CountedMeterTagAnnotationHandler(aClass -> valueResolver, aClass -> valueExpressionResolver)); + + AspectJProxyFactory pf = new AspectJProxyFactory(annotatedClass.newInstance()); + pf.addAspect(countedAspect); + + MeterTagClassInterface service = pf.getProxy(); + + // tag::example_multi_annotations[] + service.getMultipleAnnotationsForTagValueExpression(new DataHolder("zxe", "qwe")); + + assertThat(registry.get("method.counted") + .tag("value1", "value1: zxe") + .tag("value2", "value2: qwe") + .counter() + .count()).isEqualTo(1); + // end::example_multi_annotations[] + } + enum AnnotatedTestClass { CLASS_WITHOUT_INTERFACE(MeterTagClass.class), CLASS_WITH_INTERFACE(MeterTagClassChild.class); @@ -142,6 +166,11 @@ void getAnnotationForTagValueExpression( @Counted void getAnnotationForArgumentToString(@MeterTag("test") Long param); + @Counted + void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value1", expression = "'value1: ' + value1") @MeterTag(key = "value2", + expression = "'value2: ' + value2") DataHolder param); + } // end::interface[] @@ -164,6 +193,13 @@ public void getAnnotationForTagValueExpression( public void getAnnotationForArgumentToString(@MeterTag("test") Long param) { } + @Counted + @Override + public void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value1", expression = "'value1: ' + value1") @MeterTag(key = "value2", + expression = "'value2: ' + value2") DataHolder param) { + } + } static class MeterTagClassChild implements MeterTagClassInterface { @@ -183,6 +219,33 @@ public void getAnnotationForTagValueExpression(String test) { public void getAnnotationForArgumentToString(Long param) { } + @Counted + @Override + public void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value2", expression = "'value2: ' + value2") DataHolder param) { + } + + } + + static class DataHolder { + + private final String value1; + + private final String value2; + + private DataHolder(String value1, String value2) { + this.value1 = value1; + this.value2 = value2; + } + + public String getValue1() { + return value1; + } + + public String getValue2() { + return value2; + } + } } diff --git a/docs/src/test/java/io/micrometer/docs/metrics/TimedAspectTest.java b/docs/src/test/java/io/micrometer/docs/metrics/TimedAspectTest.java index b237210db5..77fcb77e88 100644 --- a/docs/src/test/java/io/micrometer/docs/metrics/TimedAspectTest.java +++ b/docs/src/test/java/io/micrometer/docs/metrics/TimedAspectTest.java @@ -107,6 +107,28 @@ void meterTagsWithExpression(AnnotatedTestClass annotatedClass) { // end::example_value_spel[] } + @ParameterizedTest + @EnumSource(AnnotatedTestClass.class) + void multipleMeterTagsWithExpression(AnnotatedTestClass annotatedClass) { + MeterRegistry registry = new SimpleMeterRegistry(); + TimedAspect timedAspect = new TimedAspect(registry); + timedAspect.setMeterTagAnnotationHandler( + new MeterTagAnnotationHandler(aClass -> valueResolver, aClass -> valueExpressionResolver)); + + AspectJProxyFactory pf = new AspectJProxyFactory(annotatedClass.newInstance()); + pf.addAspect(timedAspect); + + MeterTagClassInterface service = pf.getProxy(); + + // tag::example_multi_annotations[] + service.getMultipleAnnotationsForTagValueExpression(new DataHolder("zxe", "qwe")); + + assertThat( + registry.get("method.timed").tag("value1", "value1: zxe").tag("value2", "value2: qwe").timer().count()) + .isEqualTo(1); + // end::example_multi_annotations[] + } + enum AnnotatedTestClass { CLASS_WITHOUT_INTERFACE(MeterTagClass.class), CLASS_WITH_INTERFACE(MeterTagClassChild.class); @@ -142,6 +164,11 @@ void getAnnotationForTagValueExpression( @Timed void getAnnotationForArgumentToString(@MeterTag("test") Long param); + @Timed + void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value1", expression = "'value1: ' + value1") @MeterTag(key = "value2", + expression = "'value2: ' + value2") DataHolder param); + } // end::interface[] @@ -164,6 +191,13 @@ public void getAnnotationForTagValueExpression( public void getAnnotationForArgumentToString(@MeterTag("test") Long param) { } + @Timed + @Override + public void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value1", expression = "'value1: ' + value1") @MeterTag(key = "value2", + expression = "'value2: ' + value2") DataHolder param) { + } + } static class MeterTagClassChild implements MeterTagClassInterface { @@ -183,6 +217,33 @@ public void getAnnotationForTagValueExpression(String test) { public void getAnnotationForArgumentToString(Long param) { } + @Timed + @Override + public void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value2", expression = "'value2: ' + value2") DataHolder param) { + } + + } + + static class DataHolder { + + private final String value1; + + private final String value2; + + private DataHolder(String value1, String value2) { + this.value1 = value1; + this.value2 = value2; + } + + public String getValue1() { + return value1; + } + + public String getValue2() { + return value2; + } + } } diff --git a/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/CountedAspectTest.java b/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/CountedAspectTest.java index 21adf850c0..e0b730b250 100644 --- a/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/CountedAspectTest.java +++ b/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/CountedAspectTest.java @@ -19,9 +19,7 @@ import io.micrometer.common.annotation.ValueResolver; import io.micrometer.core.Issue; import io.micrometer.core.annotation.Counted; -import io.micrometer.core.aop.CountedAspect; -import io.micrometer.core.aop.CountedMeterTagAnnotationHandler; -import io.micrometer.core.aop.MeterTag; +import io.micrometer.core.aop.*; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; @@ -496,6 +494,49 @@ void meterTagsWithExpression(AnnotatedTestClass annotatedClass) { assertThat(registry.get("method.counted").tag("test", "hello characters").counter().count()).isEqualTo(1); } + @ParameterizedTest + @EnumSource(AnnotatedTestClass.class) + void multipleMeterTagsWithExpression(AnnotatedTestClass annotatedClass) { + MeterRegistry registry = new SimpleMeterRegistry(); + CountedAspect countedAspect = new CountedAspect(registry); + countedAspect.setMeterTagAnnotationHandler(meterTagAnnotationHandler); + + AspectJProxyFactory pf = new AspectJProxyFactory(annotatedClass.newInstance()); + pf.addAspect(countedAspect); + + MeterTagClassInterface service = pf.getProxy(); + + service.getMultipleAnnotationsForTagValueExpression(new DataHolder("zxe", "qwe")); + + assertThat(registry.get("method.counted") + .tag("value1", "value1: zxe") + .tag("value2", "value2.overridden: qwe") + .counter() + .count()).isEqualTo(1); + } + + @ParameterizedTest + @EnumSource(AnnotatedTestClass.class) + void multipleMeterTagsWithinContainerWithExpression(AnnotatedTestClass annotatedClass) { + MeterRegistry registry = new SimpleMeterRegistry(); + CountedAspect countedAspect = new CountedAspect(registry); + countedAspect.setMeterTagAnnotationHandler(meterTagAnnotationHandler); + + AspectJProxyFactory pf = new AspectJProxyFactory(annotatedClass.newInstance()); + pf.addAspect(countedAspect); + + MeterTagClassInterface service = pf.getProxy(); + + service.getMultipleAnnotationsWithContainerForTagValueExpression(new DataHolder("zxe", "qwe")); + + assertThat(registry.get("method.counted") + .tag("value1", "value1: zxe") + .tag("value2", "value2: qwe") + .tag("value3", "value3.overridden: ZXEQWE") + .counter() + .count()).isEqualTo(1); + } + @Test void meterTagOnPackagePrivateMethod() { MeterRegistry registry = new SimpleMeterRegistry(); @@ -547,6 +588,17 @@ void getAnnotationForTagValueExpression( @Counted void getAnnotationForArgumentToString(@MeterTag("test") Long param); + @Counted + void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value1", expression = "'value1: ' + value1") @MeterTag(key = "value2", + expression = "'value2: ' + value2") DataHolder param); + + @Counted + void getMultipleAnnotationsWithContainerForTagValueExpression(@MeterTags({ + @MeterTag(key = "value1", expression = "'value1: ' + value1"), + @MeterTag(key = "value2", expression = "'value2: ' + value2"), @MeterTag(key = "value3", + expression = "'value3: ' + value1.toUpperCase + value2.toUpperCase") }) DataHolder param); + } static class MeterTagClass implements MeterTagClassInterface { @@ -572,6 +624,21 @@ public void getAnnotationForArgumentToString(@MeterTag("test") Long param) { void getAnnotationForPackagePrivateMethod(@MeterTag("foo") String foo) { } + @Counted + @Override + public void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value1", expression = "'value1: ' + value1") @MeterTag(key = "value2", + expression = "'value2.overridden: ' + value2") DataHolder param) { + } + + @Counted + @Override + public void getMultipleAnnotationsWithContainerForTagValueExpression(@MeterTags({ + @MeterTag(key = "value1", expression = "'value1: ' + value1"), + @MeterTag(key = "value2", expression = "'value2: ' + value2"), @MeterTag(key = "value3", + expression = "'value3.overridden: ' + value1.toUpperCase + value2.toUpperCase") }) DataHolder param) { + } + } static class MeterTagClassChild implements MeterTagClassInterface { @@ -591,6 +658,39 @@ public void getAnnotationForTagValueExpression(String test) { public void getAnnotationForArgumentToString(Long param) { } + @Counted + @Override + public void getMultipleAnnotationsForTagValueExpression( + @MeterTag(key = "value2", expression = "'value2.overridden: ' + value2") DataHolder param) { + } + + @Counted + @Override + public void getMultipleAnnotationsWithContainerForTagValueExpression(@MeterTag(key = "value3", + expression = "'value3.overridden: ' + value1.toUpperCase + value2.toUpperCase") DataHolder param) { + } + + } + + static class DataHolder { + + private final String value1; + + private final String value2; + + private DataHolder(String value1, String value2) { + this.value1 = value1; + this.value2 = value2; + } + + public String getValue1() { + return value1; + } + + public String getValue2() { + return value2; + } + } } diff --git a/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/TimedAspectTest.java b/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/TimedAspectTest.java index 242ad50686..1afede1331 100644 --- a/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/TimedAspectTest.java +++ b/samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/TimedAspectTest.java @@ -537,7 +537,7 @@ void meterTagsWithExpression(AnnotatedTestClass annotatedClass) { service.getAnnotationForTagValueExpression("15L"); - assertThat(registry.get("method.timed").tag("test", "hello characters. overridden").timer().count()) + assertThat(registry.get("method.timed").tag("test", "hello characters.overridden").timer().count()) .isEqualTo(1); } @@ -557,7 +557,7 @@ void multipleMeterTagsWithExpression(AnnotatedTestClass annotatedClass) { assertThat(registry.get("method.timed") .tag("value1", "value1: zxe") - .tag("value2", "value2. overridden: qwe") + .tag("value2", "value2.overridden: qwe") .timer() .count()).isEqualTo(1); } @@ -579,7 +579,7 @@ void multipleMeterTagsWithinContainerWithExpression(AnnotatedTestClass annotated assertThat(registry.get("method.timed") .tag("value1", "value1: zxe") .tag("value2", "value2: qwe") - .tag("value3", "value3. overridden: ZXEQWE") + .tag("value3", "value3.overridden: ZXEQWE") .timer() .count()).isEqualTo(1); } @@ -678,7 +678,7 @@ public void getAnnotationForTagValueResolver( @Timed @Override public void getAnnotationForTagValueExpression( - @MeterTag(key = "test", expression = "'hello' + ' characters. overridden'") String test) { + @MeterTag(key = "test", expression = "'hello' + ' characters.overridden'") String test) { } @Timed @@ -694,7 +694,7 @@ void getAnnotationForPackagePrivateMethod(@MeterTag("foo") String foo) { @Override public void getMultipleAnnotationsForTagValueExpression( @MeterTag(key = "value1", expression = "'value1: ' + value1") @MeterTag(key = "value2", - expression = "'value2. overridden: ' + value2") DataHolder param) { + expression = "'value2.overridden: ' + value2") DataHolder param) { } @@ -703,7 +703,7 @@ public void getMultipleAnnotationsForTagValueExpression( public void getMultipleAnnotationsWithContainerForTagValueExpression(@MeterTags({ @MeterTag(key = "value1", expression = "'value1: ' + value1"), @MeterTag(key = "value2", expression = "'value2: ' + value2"), @MeterTag(key = "value3", - expression = "'value3. overridden: ' + value1.toUpperCase + value2.toUpperCase") }) DataHolder param) { + expression = "'value3.overridden: ' + value1.toUpperCase + value2.toUpperCase") }) DataHolder param) { } } @@ -718,7 +718,7 @@ public void getAnnotationForTagValueResolver(String test) { @Timed @Override public void getAnnotationForTagValueExpression( - @MeterTag(key = "test", expression = "'hello' + ' characters. overridden'") String test) { + @MeterTag(key = "test", expression = "'hello' + ' characters.overridden'") String test) { } @Timed @@ -729,13 +729,13 @@ public void getAnnotationForArgumentToString(Long param) { @Timed @Override public void getMultipleAnnotationsForTagValueExpression( - @MeterTag(key = "value2", expression = "'value2. overridden: ' + value2") DataHolder param) { + @MeterTag(key = "value2", expression = "'value2.overridden: ' + value2") DataHolder param) { } @Timed @Override public void getMultipleAnnotationsWithContainerForTagValueExpression(@MeterTag(key = "value3", - expression = "'value3. overridden: ' + value1.toUpperCase + value2.toUpperCase") DataHolder param) { + expression = "'value3.overridden: ' + value1.toUpperCase + value2.toUpperCase") DataHolder param) { } } @@ -885,7 +885,7 @@ public void call() { } - public static final class DataHolder { + static class DataHolder { private final String value1;