Describe the bug
When you add both micrometer and fault tolerance extension, you'll be facing the following exception
2020-09-09 12:54:35,488 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.AmbiguousResolutionException: Ambiguous dependencies for type org.eclipse.microprofile.metrics.MetricRegistry and qualifiers [@Default]
- java member: io.smallrye.faulttolerance.metrics.MetricsCollectorFactory#registry
- declared on CLASS bean [types=[io.smallrye.faulttolerance.metrics.MetricsCollectorFactory, java.lang.Object], qualifiers=[@Default, @Any], target=io.smallrye.faulttolerance.metrics.MetricsCollectorFactory]
- available beans:
- CLASS bean [types=[org.eclipse.microprofile.metrics.MetricRegistry, java.lang.Object, io.quarkus.smallrye.faulttolerance.runtime.NoopMetricRegistry], qualifiers=[@Default, @Any], target=io.quarkus.smallrye.faulttolerance.runtime.NoopMetricRegistry]
- PRODUCER METHOD bean [types=[org.eclipse.microprofile.metrics.MetricRegistry, io.quarkus.micrometer.runtime.binder.mpmetrics.MetricRegistryAdapter, java.lang.Object], qualifiers=[@Default, @Any], target=io.quarkus.micrometer.runtime.binder.mpmetrics.MetricRegistryAdapter produceRegistry(io.micrometer.core.instrument.MeterRegistry registry), declaringBean=io.quarkus.micrometer.runtime.binder.mpmetrics.MpMetricsRegistryProducer]
As I created the io.quarkus.smallrye.faulttolerance.runtime.NoopMetricRegistry I know what's going on ;)
The fault tolerance need a metric registry to registers it's metrics. In case the smallrye-metric extension is not present we provides a NoopMetricRegistry.
We need to update this code to also check for the presence of the Micrometer extension.
/cc @Ladicek
/cc @ebullient
The fault tolerance code is good: https://github.com/quarkusio/quarkus/blob/master/extensions/smallrye-fault-tolerance/deployment/src/main/java/io/quarkus/smallrye/faulttolerance/deployment/SmallRyeFaultToleranceProcessor.java#L153
So the fix should be on the micrometer extension that should provides the metrics capability.
I can try to find some time to fix this if you want.
Let me double check why that doesn't work.. and what the most appropriate fix is given the two extensions. Won't take long, I don't think. ;)
This will be a change to the fault tolerance extension to use the MetricsCapabilityBuildItem / MetricsFactoryBuildItem found in core as of 1.7 (moving away from the metrics capability constant).
moving away from the metrics capability constant
Capability is the standard way to do this kind of dependency check as it requires no maven dependencies. It has been design for this use case.
Yes — but there aren’t enough constants, and their meaning changes. As of 1.7, we added a different way for metrics. It also does not require maven dependencies (the BuildItems mentioned are in core)
OK then, if no maven dependencies I'm OK with it ;)
Patch is pretty simple -- give it a whirl?
I'm building Quarkus with this patch now.
I'll let you know if it fixes the issue.
I encountered this problem this morning when I switeched to 1.8.0.Final and wanted to use the micrometer extension with prometheus.
I had to remove the fault-tolerance to be able to build and run the service.
@dwamara I have plans to release 1.8.1.Final on Friday.
Just saw this issue now while moving to 1.8.0. Glad that it is already fixed.
Hey, guys
Sorry for not testing the fix before it gets released but I just tried to use the 1.8.1 Final now.
The initial crash does not happen anymore but when I try to call a method that uses @CircuitBreaker (from quarkus-smallrye-fault-tolerance) I get this exception:
java.lang.UnsupportedOperationException: Can not register a pre-constructed Metric with Micrometer
at io.quarkus.micrometer.runtime.binder.mpmetrics.MetricRegistryAdapter.register(MetricRegistryAdapter.java:46)
at io.smallrye.faulttolerance.metrics.MetricsCollectorFactory$MetricsCollectorImpl.gaugeRegister(MetricsCollectorFactory.java:79)
at io.smallrye.faulttolerance.metrics.MetricsCollectorFactory$MetricsCollectorImpl.circuitBreakerClosedTimeProvider(MetricsCollectorFactory.java:164)
at io.smallrye.faulttolerance.core.circuit.breaker.CircuitBreaker.<init>(CircuitBreaker.java:73)
at io.smallrye.faulttolerance.FaultToleranceInterceptor.prepareSyncStrategy(FaultToleranceInterceptor.java:320)
at io.smallrye.faulttolerance.FaultToleranceInterceptor.lambda$syncFlow$4(FaultToleranceInterceptor.java:202)
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705)
at io.smallrye.faulttolerance.internal.StrategyCache.getStrategy(StrategyCache.java:23)
at io.smallrye.faulttolerance.FaultToleranceInterceptor.syncFlow(FaultToleranceInterceptor.java:201)
at io.smallrye.faulttolerance.FaultToleranceInterceptor.interceptCommand(FaultToleranceInterceptor.java:159)
at io.smallrye.faulttolerance.FaultToleranceInterceptor_Bean.intercept(FaultToleranceInterceptor_Bean.zig:555)
at org.jboss.resteasy.microprofile.client.InvocationContextImpl$InterceptorInvocation.invoke(InvocationContextImpl.java:154)
at org.jboss.resteasy.microprofile.client.InvocationContextImpl.invokeNext(InvocationContextImpl.java:53)
at org.jboss.resteasy.microprofile.client.InvocationContextImpl.proceed(InvocationContextImpl.java:89)
at org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:141)
I will try to take a deeper look later today to try to help with something.
If I don't use the CircuitBreaker it works.
Ah. yes. That is one of those places we'll have to sort out re: intersection of smallrye and MP Metrics and micrometer.
Fault Tolerance is pre-creating an MP Meter (probably a Counter or a Gauge), instead of letting the registry create and return it. This will be a new issue, and may need a fix in Smallrye FT ... @kenfinnigan
Cool. Let me open then.
Thanks, @ebullient