Skip to content

Commit 12db19f

Browse files
Merge branch '1.12.x' into 1.13.x
2 parents e3ac3ad + adfdd3e commit 12db19f

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-5
lines changed

micrometer-core/src/main/java/io/micrometer/core/aop/CountedAspect.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.micrometer.common.lang.NonNullApi;
1919
import io.micrometer.common.lang.Nullable;
20+
import io.micrometer.common.util.internal.logging.WarnThenDebugLogger;
2021
import io.micrometer.core.annotation.Counted;
2122
import io.micrometer.core.instrument.*;
2223
import org.aspectj.lang.ProceedingJoinPoint;
@@ -77,6 +78,8 @@
7778
@NonNullApi
7879
public class CountedAspect {
7980

81+
private static final WarnThenDebugLogger joinPointTagsFunctionLogger = new WarnThenDebugLogger(CountedAspect.class);
82+
8083
private static final Predicate<ProceedingJoinPoint> DONT_SKIP_ANYTHING = pjp -> false;
8184

8285
public final String DEFAULT_EXCEPTION_TAG_VALUE = "none";
@@ -163,10 +166,24 @@ public CountedAspect(MeterRegistry registry, Predicate<ProceedingJoinPoint> shou
163166
public CountedAspect(MeterRegistry registry, Function<ProceedingJoinPoint, Iterable<Tag>> tagsBasedOnJoinPoint,
164167
Predicate<ProceedingJoinPoint> shouldSkip) {
165168
this.registry = registry;
166-
this.tagsBasedOnJoinPoint = tagsBasedOnJoinPoint;
169+
this.tagsBasedOnJoinPoint = makeSafe(tagsBasedOnJoinPoint);
167170
this.shouldSkip = shouldSkip;
168171
}
169172

173+
private Function<ProceedingJoinPoint, Iterable<Tag>> makeSafe(
174+
Function<ProceedingJoinPoint, Iterable<Tag>> function) {
175+
return pjp -> {
176+
try {
177+
return function.apply(pjp);
178+
}
179+
catch (Throwable t) {
180+
joinPointTagsFunctionLogger
181+
.log("Exception thrown from the tagsBasedOnJoinPoint function configured on CountedAspect.", t);
182+
return Tags.empty();
183+
}
184+
};
185+
}
186+
170187
@Around("@within(io.micrometer.core.annotation.Counted) and not @annotation(io.micrometer.core.annotation.Counted)")
171188
@Nullable
172189
public Object countedClass(ProceedingJoinPoint pjp) throws Throwable {

micrometer-core/src/main/java/io/micrometer/core/aop/TimedAspect.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.micrometer.common.lang.NonNullApi;
1919
import io.micrometer.common.lang.Nullable;
20+
import io.micrometer.common.util.internal.logging.WarnThenDebugLogger;
2021
import io.micrometer.core.annotation.Incubating;
2122
import io.micrometer.core.annotation.Timed;
2223
import io.micrometer.core.instrument.*;
@@ -84,6 +85,8 @@
8485
@Incubating(since = "1.0.0")
8586
public class TimedAspect {
8687

88+
private static final WarnThenDebugLogger joinPointTagsFunctionLogger = new WarnThenDebugLogger(TimedAspect.class);
89+
8790
private static final Predicate<ProceedingJoinPoint> DONT_SKIP_ANYTHING = pjp -> false;
8891

8992
public static final String DEFAULT_METRIC_NAME = "method.timed";
@@ -157,10 +160,24 @@ public TimedAspect(MeterRegistry registry, Predicate<ProceedingJoinPoint> should
157160
public TimedAspect(MeterRegistry registry, Function<ProceedingJoinPoint, Iterable<Tag>> tagsBasedOnJoinPoint,
158161
Predicate<ProceedingJoinPoint> shouldSkip) {
159162
this.registry = registry;
160-
this.tagsBasedOnJoinPoint = tagsBasedOnJoinPoint;
163+
this.tagsBasedOnJoinPoint = makeSafe(tagsBasedOnJoinPoint);
161164
this.shouldSkip = shouldSkip;
162165
}
163166

167+
private Function<ProceedingJoinPoint, Iterable<Tag>> makeSafe(
168+
Function<ProceedingJoinPoint, Iterable<Tag>> function) {
169+
return pjp -> {
170+
try {
171+
return function.apply(pjp);
172+
}
173+
catch (Throwable t) {
174+
joinPointTagsFunctionLogger
175+
.log("Exception thrown from the tagsBasedOnJoinPoint function configured on TimedAspect.", t);
176+
return Tags.empty();
177+
}
178+
};
179+
}
180+
164181
@Around("@within(io.micrometer.core.annotation.Timed) and not @annotation(io.micrometer.core.annotation.Timed)")
165182
@Nullable
166183
public Object timedClass(ProceedingJoinPoint pjp) throws Throwable {

micrometer-core/src/test/java/io/micrometer/core/aop/CountedAspectTest.java

+18
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@
1515
*/
1616
package io.micrometer.core.aop;
1717

18+
import io.micrometer.core.Issue;
1819
import io.micrometer.core.annotation.Counted;
1920
import io.micrometer.core.instrument.Counter;
2021
import io.micrometer.core.instrument.MeterRegistry;
22+
import io.micrometer.core.instrument.Tag;
2123
import io.micrometer.core.instrument.search.MeterNotFoundException;
2224
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
2325
import org.aspectj.lang.ProceedingJoinPoint;
2426
import org.junit.jupiter.api.Test;
2527
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
2628

2729
import java.util.concurrent.CompletableFuture;
30+
import java.util.function.Function;
2831
import java.util.function.Predicate;
2932

3033
import static java.util.concurrent.CompletableFuture.supplyAsync;
@@ -195,6 +198,21 @@ void countedWithEmptyMetricNamesWhenCompleted() {
195198
assertThat(meterRegistry.get("method.counted").tag("result", "failure").counter().count()).isOne();
196199
}
197200

201+
@Test
202+
@Issue("#5584")
203+
void pjpFunctionThrows() {
204+
CountedService countedService = getAdvisedService(new CountedService(),
205+
new CountedAspect(meterRegistry, (Function<ProceedingJoinPoint, Iterable<Tag>>) jp -> {
206+
throw new RuntimeException("test");
207+
}));
208+
countedService.succeedWithMetrics();
209+
210+
Counter counter = meterRegistry.get("metric.success").tag("extra", "tag").tag("result", "success").counter();
211+
212+
assertThat(counter.count()).isOne();
213+
assertThat(counter.getId().getDescription()).isNull();
214+
}
215+
198216
static class CountedService {
199217

200218
@Counted(value = "metric.none", recordFailuresOnly = true)

micrometer-core/src/test/java/io/micrometer/core/aop/TimedAspectTest.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
import io.micrometer.common.annotation.ValueExpressionResolver;
1919
import io.micrometer.common.annotation.ValueResolver;
2020
import io.micrometer.common.lang.NonNull;
21+
import io.micrometer.core.Issue;
2122
import io.micrometer.core.annotation.Timed;
22-
import io.micrometer.core.instrument.LongTaskTimer;
23+
import io.micrometer.core.instrument.*;
2324
import io.micrometer.core.instrument.Meter.Id;
24-
import io.micrometer.core.instrument.MeterRegistry;
25-
import io.micrometer.core.instrument.Timer;
2625
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
2726
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
2827
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
@@ -36,6 +35,7 @@
3635
import javax.annotation.Nonnull;
3736
import java.util.concurrent.CompletableFuture;
3837
import java.util.concurrent.CompletionException;
38+
import java.util.function.Function;
3939
import java.util.function.Predicate;
4040

4141
import static java.util.concurrent.CompletableFuture.supplyAsync;
@@ -378,6 +378,22 @@ void timeClassFailure() {
378378
assertThat(failingRegistry.getMeters()).isEmpty();
379379
}
380380

381+
@Issue("#5584")
382+
void pjpFunctionThrows() {
383+
MeterRegistry registry = new SimpleMeterRegistry();
384+
385+
AspectJProxyFactory pf = new AspectJProxyFactory(new TimedService());
386+
pf.addAspect(new TimedAspect(registry, (Function<ProceedingJoinPoint, Iterable<Tag>>) jp -> {
387+
throw new RuntimeException("test");
388+
}));
389+
390+
TimedService service = pf.getProxy();
391+
392+
service.call();
393+
394+
assertThat(registry.get("call").tag("extra", "tag").timer().count()).isEqualTo(1);
395+
}
396+
381397
@Test
382398
void ignoreClassLevelAnnotationIfMethodLevelPresent() {
383399
MeterRegistry registry = new SimpleMeterRegistry();

0 commit comments

Comments
 (0)