Repository: quarkusio/quarkus
Issue: @Timed and @Counted annotations fails when exceptions occurs

The following method with ```@Counted``` and ```@Timed``` annotations fails if any exception occurs during the invocation. For instance, if I want the method to throw a javax.ws.rs.NotFoundException in some cases, it doesn't work due to these annotations and I instead get a HTTP status 500. If I remove the annotations the expected HTTP status code is 404 when calling ```/greeting/notfound```
```java
  @GET
  @Produces(MediaType.TEXT_PLAIN)
  @Path("/greeting/{name}")
  @Timed(name = "greetingTime", description = "Timing of the greeting method", absolute = true)
  @Counted(name = "greeting", description = "Counting of the greeting method", absolute = true,
      monotonic = true)
  public String greeting(@PathParam("name") String name) {
    if (name.equals("notfound"))
      throw new NotFoundException();
    return service.greeting(name);
  }
```
I'm using Quarkus version 0.12.0, JDK 11 on macOS Mojave and maven 3.6.0
```
ERROR: UT005023: Exception handling request to /greeting/fail
org.jboss.resteasy.spi.UnhandledException: java.lang.RuntimeException: Cannot invoke method: io.smallrye.metrics.interceptors.TimedInterceptor#timedMethod on io.smallrye.metrics.interceptors.TimedInterceptor@1f4b5667
	at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:103)
	at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:323)
	at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:209)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:495)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:252)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:153)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:156)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:238)
	at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:229)
	at io.quarkus.resteasy.runtime.ResteasyFilter$ResteasyResponseWrapper.sendError(ResteasyFilter.java:72)
	at io.undertow.servlet.handlers.DefaultServlet.doGet(DefaultServlet.java:175)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:686)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
	at io.quarkus.resteasy.runtime.ResteasyFilter.doFilter(ResteasyFilter.java:43)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.opentracing.contrib.jaxrs2.server.SpanFinishingFilter.doFilter(SpanFinishingFilter.java:52)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.quarkus.undertow.runtime.UndertowDeploymentTemplate$7$1$1.call(UndertowDeploymentTemplate.java:415)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1998)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1525)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1382)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: Cannot invoke method: io.smallrye.metrics.interceptors.TimedInterceptor#timedMethod on io.smallrye.metrics.interceptors.TimedInterceptor@1f4b5667
	at io.quarkus.arc.Reflections.invokeMethod(Reflections.java:114)
	at io.smallrye.metrics.interceptors.TimedInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.InvocationContextImpl$InterceptorInvocation.invoke(InvocationContextImpl.java:270)
	at io.quarkus.arc.InvocationContextImpl.invokeNext(InvocationContextImpl.java:149)
	at io.quarkus.arc.InvocationContextImpl.proceed(InvocationContextImpl.java:173)
	at se.acme.quarkus.GreetingFacade_Subclass.greeting(Unknown Source)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:152)
	at org.jboss.resteasy.core.MethodInjectorImpl.lambda$invoke$3(MethodInjectorImpl.java:123)
	at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:680)
	at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:658)
	at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2094)
	at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:143)
	at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:123)
	at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:543)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:418)
	at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:372)
	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:374)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:343)
	at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invoke$1(ResourceMethodInvoker.java:317)
	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2235)
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:143)
	at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:317)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:476)
	... 49 more
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at io.quarkus.arc.Reflections.invokeMethod(Reflections.java:111)
	... 77 more
Caused by: java.lang.RuntimeException: Cannot invoke method: io.smallrye.metrics.interceptors.CountedInterceptor#countedMethod on io.smallrye.metrics.interceptors.CountedInterceptor@13619d1d
	at io.quarkus.arc.Reflections.invokeMethod(Reflections.java:114)
	at io.smallrye.metrics.interceptors.CountedInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.InvocationContextImpl$InterceptorInvocation.invoke(InvocationContextImpl.java:270)
	at io.quarkus.arc.InvocationContextImpl.invokeNext(InvocationContextImpl.java:149)
	at io.quarkus.arc.InvocationContextImpl.proceed(InvocationContextImpl.java:173)
	at io.smallrye.metrics.interceptors.TimedInterceptor.timedCallable(TimedInterceptor.java:80)
	at io.smallrye.metrics.interceptors.TimedInterceptor.timedMethod(TimedInterceptor.java:63)
	... 82 more
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at io.quarkus.arc.Reflections.invokeMethod(Reflections.java:111)
	... 88 more
Caused by: javax.ws.rs.NotFoundException: HTTP 404 Not Found
	at se.acme.quarkus.GreetingFacade.greeting(GreetingFacade.java:27)
	at se.acme.quarkus.GreetingFacade_Subclass.greeting$$superaccessor1(Unknown Source)
	at se.acme.quarkus.GreetingFacade_Subclass$$function$$3.apply(Unknown Source)
	at io.quarkus.arc.InvocationContextImpl.interceptorChainCompleted(InvocationContextImpl.java:157)
	at io.quarkus.arc.InvocationContextImpl.proceed(InvocationContextImpl.java:177)
	at io.smallrye.metrics.interceptors.CountedInterceptor.countedCallable(CountedInterceptor.java:81)
	at io.smallrye.metrics.interceptors.CountedInterceptor.countedMethod(CountedInterceptor.java:63)
	... 93 more
```

Changed files:
independent-projects/arc/runtime/src/main/java/io/quarkus/arc/Reflections.java
integration-tests/main/src/test/java/io/quarkus/example/test/MetricsTestCase.java
integration-tests/main/src/main/java/io/quarkus/example/metrics/MetricsResource.java

diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/Reflections.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/Reflections.java
index 3f5fa991150..36431dd2a79 100644
--- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/Reflections.java
+++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/Reflections.java
@@ -109,8 +109,13 @@ public static Object invokeMethod(Class<?> clazz, String name, Class<?>[] paramT
                 method.setAccessible(true);
             }
             return method.invoke(instance, args);
-        } catch (NoSuchMethodException | SecurityException | IllegalArgumentException | IllegalAccessException
-                | InvocationTargetException e) {
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            if (t instanceof RuntimeException) {
+                throw (RuntimeException) t;
+            }
+            throw new RuntimeException("Cannot invoke method: " + clazz.getName() + "#" + name + " on " + instance, e);
+        } catch (NoSuchMethodException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
             throw new RuntimeException("Cannot invoke method: " + clazz.getName() + "#" + name + " on " + instance, e);
         }
     }
diff --git a/integration-tests/main/src/main/java/io/quarkus/example/metrics/MetricsResource.java b/integration-tests/main/src/main/java/io/quarkus/example/metrics/MetricsResource.java
index 3558f4ad980..1e4ce5c2a12 100644
--- a/integration-tests/main/src/main/java/io/quarkus/example/metrics/MetricsResource.java
+++ b/integration-tests/main/src/main/java/io/quarkus/example/metrics/MetricsResource.java
@@ -18,6 +18,7 @@
 
 import javax.inject.Inject;
 import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
 import javax.ws.rs.Path;
 
 import org.eclipse.microprofile.metrics.Histogram;
@@ -84,4 +85,11 @@ public String counterWithTags() {
         return "TEST";
     }
 
+    @GET
+    @Path("/counter-throwing-not-found-exception")
+    @Counted(monotonic = true, name = "counter_404")
+    public String counterWithTagsThrowingNotFound() {
+        throw new NotFoundException();
+    }
+
 }
diff --git a/integration-tests/main/src/test/java/io/quarkus/example/test/MetricsTestCase.java b/integration-tests/main/src/test/java/io/quarkus/example/test/MetricsTestCase.java
index 78a234e804d..df9343bbba4 100644
--- a/integration-tests/main/src/test/java/io/quarkus/example/test/MetricsTestCase.java
+++ b/integration-tests/main/src/test/java/io/quarkus/example/test/MetricsTestCase.java
@@ -138,6 +138,15 @@ public void testVendorMetrics() {
                 .body(containsString("vendor:memory_max_non_heap_bytes "));
     }
 
+    /**
+     * A REST method with metrics is throwing a NotFoundException, so the client should receive 404.
+     */
+    @Test
+    public void testEndpointWithMetricsThrowingException() {
+        RestAssured.when().get("/metricsresource/counter-throwing-not-found-exception").then()
+                .statusCode(404);
+    }
+
     private void assertMetricExactValue(String name, String val) {
         RestAssured.when().get("/metrics").then()
                 .body(containsString(name + " " + val));