Skip to content

Commit 8994c8f

Browse files
@timed should record Throwables not only Exceptions (#5479)
--------- Co-authored-by: Jonatan Ivanov <[email protected]>
1 parent f0aa18d commit 8994c8f

File tree

2 files changed

+79
-63
lines changed

2 files changed

+79
-63
lines changed

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,19 +210,19 @@ private Object processWithTimer(ProceedingJoinPoint pjp, Timed timed, String met
210210
return ((CompletionStage<?>) pjp.proceed()).whenComplete(
211211
(result, throwable) -> record(pjp, timed, metricName, sample, getExceptionTag(throwable)));
212212
}
213-
catch (Exception ex) {
214-
record(pjp, timed, metricName, sample, ex.getClass().getSimpleName());
215-
throw ex;
213+
catch (Throwable e) {
214+
record(pjp, timed, metricName, sample, e.getClass().getSimpleName());
215+
throw e;
216216
}
217217
}
218218

219219
String exceptionClass = DEFAULT_EXCEPTION_TAG_VALUE;
220220
try {
221221
return pjp.proceed();
222222
}
223-
catch (Exception ex) {
224-
exceptionClass = ex.getClass().getSimpleName();
225-
throw ex;
223+
catch (Throwable e) {
224+
exceptionClass = e.getClass().getSimpleName();
225+
throw e;
226226
}
227227
finally {
228228
record(pjp, timed, metricName, sample, exceptionClass);
@@ -269,9 +269,9 @@ private Object processWithLongTaskTimer(ProceedingJoinPoint pjp, Timed timed, St
269269
return ((CompletionStage<?>) pjp.proceed())
270270
.whenComplete((result, throwable) -> sample.ifPresent(this::stopTimer));
271271
}
272-
catch (Exception ex) {
272+
catch (Throwable e) {
273273
sample.ifPresent(this::stopTimer);
274-
throw ex;
274+
throw e;
275275
}
276276
}
277277

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

Lines changed: 71 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import io.micrometer.core.instrument.Timer;
2323
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
2424
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
25-
import io.micrometer.core.instrument.search.MeterNotFoundException;
2625
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
2726
import io.micrometer.core.lang.NonNull;
2827
import org.aspectj.lang.ProceedingJoinPoint;
@@ -69,7 +68,7 @@ void timeMethodWithSkipPredicate() {
6968

7069
service.call();
7170

72-
assertThat(registry.find("call").timer()).isNull();
71+
assertThat(registry.getMeters()).isEmpty();
7372
}
7473

7574
@Test
@@ -87,8 +86,7 @@ void timeMethodWithLongTaskTimer() {
8786
.tag("class", getClass().getName() + "$TimedService")
8887
.tag("method", "longCall")
8988
.tag("extra", "tag")
90-
.longTaskTimers()
91-
.size()).isEqualTo(1);
89+
.longTaskTimers()).hasSize(1);
9290
}
9391

9492
@Test
@@ -102,13 +100,7 @@ void timeMethodFailure() {
102100

103101
service.call();
104102

105-
assertThatExceptionOfType(MeterNotFoundException.class).isThrownBy(() -> {
106-
failingRegistry.get("call")
107-
.tag("class", getClass().getName() + "$TimedService")
108-
.tag("method", "call")
109-
.tag("extra", "tag")
110-
.timer();
111-
});
103+
assertThat(failingRegistry.getMeters()).isEmpty();
112104
}
113105

114106
@Test
@@ -122,13 +114,50 @@ void timeMethodFailureWithLongTaskTimer() {
122114

123115
service.longCall();
124116

125-
assertThatExceptionOfType(MeterNotFoundException.class).isThrownBy(() -> {
126-
failingRegistry.get("longCall")
127-
.tag("class", getClass().getName() + "$TimedService")
128-
.tag("method", "longCall")
129-
.tag("extra", "tag")
130-
.longTaskTimer();
131-
});
117+
assertThat(failingRegistry.getMeters()).isEmpty();
118+
}
119+
120+
@Test
121+
void timeMethodWithError() {
122+
MeterRegistry registry = new SimpleMeterRegistry();
123+
124+
AspectJProxyFactory pf = new AspectJProxyFactory(new TimedService());
125+
pf.addAspect(new TimedAspect(registry));
126+
127+
TimedService service = pf.getProxy();
128+
129+
assertThat(registry.getMeters()).isEmpty();
130+
131+
assertThatThrownBy(service::callRaisingError).isInstanceOf(TestError.class);
132+
133+
assertThat(registry.get("callRaisingError")
134+
.tag("class", getClass().getName() + "$TimedService")
135+
.tag("method", "callRaisingError")
136+
.tag("extra", "tag")
137+
.tag("exception", "TestError")
138+
.timer()
139+
.count()).isEqualTo(1);
140+
}
141+
142+
@Test
143+
void timeMethodWithErrorAndLongTaskTimer() {
144+
MeterRegistry registry = new SimpleMeterRegistry();
145+
146+
AspectJProxyFactory pf = new AspectJProxyFactory(new TimedService());
147+
pf.addAspect(new TimedAspect(registry));
148+
149+
TimedService service = pf.getProxy();
150+
151+
assertThat(registry.getMeters()).isEmpty();
152+
153+
assertThatThrownBy(service::longCallRaisingError).isInstanceOf(TestError.class);
154+
155+
assertThat(registry.get("longCallRaisingError")
156+
.tag("class", getClass().getName() + "$TimedService")
157+
.tag("method", "longCallRaisingError")
158+
.tag("extra", "tag")
159+
.longTaskTimer()
160+
.activeTasks()).isEqualTo(0);
132161
}
133162

134163
@Test
@@ -143,12 +172,7 @@ void timeMethodWhenCompleted() {
143172
GuardedResult guardedResult = new GuardedResult();
144173
CompletableFuture<?> completableFuture = service.call(guardedResult);
145174

146-
assertThat(registry.find("call")
147-
.tag("class", getClass().getName() + "$AsyncTimedService")
148-
.tag("method", "call")
149-
.tag("extra", "tag")
150-
.tag("exception", "none")
151-
.timer()).isNull();
175+
assertThat(registry.getMeters()).isEmpty();
152176

153177
guardedResult.complete();
154178
completableFuture.join();
@@ -174,21 +198,16 @@ void timeMethodWhenCompletedExceptionally() {
174198
GuardedResult guardedResult = new GuardedResult();
175199
CompletableFuture<?> completableFuture = service.call(guardedResult);
176200

177-
assertThat(registry.find("call")
178-
.tag("class", getClass().getName() + "$AsyncTimedService")
179-
.tag("method", "call")
180-
.tag("extra", "tag")
181-
.tag("exception", "NullPointerException")
182-
.timer()).isNull();
201+
assertThat(registry.getMeters()).isEmpty();
183202

184-
guardedResult.complete(new NullPointerException());
203+
guardedResult.complete(new IllegalStateException("simulated"));
185204
catchThrowableOfType(completableFuture::join, CompletionException.class);
186205

187206
assertThat(registry.get("call")
188207
.tag("class", getClass().getName() + "$AsyncTimedService")
189208
.tag("method", "call")
190209
.tag("extra", "tag")
191-
.tag("exception", "NullPointerException")
210+
.tag("exception", "IllegalStateException")
192211
.timer()
193212
.count()).isEqualTo(1);
194213
}
@@ -267,12 +286,7 @@ void timeMethodFailureWhenCompletedExceptionally() {
267286
guardedResult.complete();
268287
completableFuture.join();
269288

270-
assertThatExceptionOfType(MeterNotFoundException.class).isThrownBy(() -> failingRegistry.get("call")
271-
.tag("class", getClass().getName() + "$AsyncTimedService")
272-
.tag("method", "call")
273-
.tag("extra", "tag")
274-
.tag("exception", "none")
275-
.timer());
289+
assertThat(failingRegistry.getMeters()).isEmpty();
276290
}
277291

278292
@Test
@@ -289,13 +303,7 @@ void timeMethodFailureWithLongTaskTimerWhenCompleted() {
289303
guardedResult.complete();
290304
completableFuture.join();
291305

292-
assertThatExceptionOfType(MeterNotFoundException.class).isThrownBy(() -> {
293-
failingRegistry.get("longCall")
294-
.tag("class", getClass().getName() + "$AsyncTimedService")
295-
.tag("method", "longCall")
296-
.tag("extra", "tag")
297-
.longTaskTimer();
298-
});
306+
assertThat(failingRegistry.getMeters()).isEmpty();
299307
}
300308

301309
@Test
@@ -361,16 +369,10 @@ void timeClassFailure() {
361369

362370
service.call();
363371

364-
assertThatExceptionOfType(MeterNotFoundException.class).isThrownBy(() -> {
365-
failingRegistry.get("call")
366-
.tag("class", "io.micrometer.core.aop.TimedAspectTest$TimedClass")
367-
.tag("method", "call")
368-
.tag("extra", "tag")
369-
.timer();
370-
});
372+
assertThat(failingRegistry.getMeters()).isEmpty();
371373
}
372374

373-
private final class FailingMeterRegistry extends SimpleMeterRegistry {
375+
private static final class FailingMeterRegistry extends SimpleMeterRegistry {
374376

375377
private FailingMeterRegistry() {
376378
super();
@@ -380,14 +382,14 @@ private FailingMeterRegistry() {
380382
@Override
381383
protected Timer newTimer(@NonNull Id id, @NonNull DistributionStatisticConfig distributionStatisticConfig,
382384
@NonNull PauseDetector pauseDetector) {
383-
throw new RuntimeException();
385+
throw new RuntimeException("FailingMeterRegistry");
384386
}
385387

386388
@NonNull
387389
@Override
388390
protected LongTaskTimer newLongTaskTimer(@Nonnull Id id,
389391
@Nonnull DistributionStatisticConfig distributionStatisticConfig) {
390-
throw new RuntimeException();
392+
throw new RuntimeException("FailingMeterRegistry");
391393
}
392394

393395
}
@@ -402,6 +404,16 @@ void call() {
402404
void longCall() {
403405
}
404406

407+
@Timed(value = "callRaisingError", extraTags = { "extra", "tag" })
408+
void callRaisingError() {
409+
throw new TestError();
410+
}
411+
412+
@Timed(value = "longCallRaisingError", extraTags = { "extra", "tag" }, longTask = true)
413+
void longCallRaisingError() {
414+
throw new TestError();
415+
}
416+
405417
}
406418

407419
static class AsyncTimedService {
@@ -476,4 +488,8 @@ public void call() {
476488

477489
}
478490

491+
static class TestError extends Error {
492+
493+
}
494+
479495
}

0 commit comments

Comments
 (0)