Repository: quarkusio/quarkus
Issue: SmallRye GraphQL extension's metrics are broken

The producer of vendor `MetricRegistry` is detected as unused (unless an application injects it directly, which makes no sense), but it is needed at runtime. This appears at application boot:

```
CDI: programmatic lookup problem detected
-----------------------------------------
At least one bean matched the required type and qualifiers but was marked as unused and removed during build
Removed beans:
	- PRODUCER_METHOD bean io.smallrye.metrics.MetricRegistries#getVendorRegistry() [types=[class org.eclipse.microprofile.metrics.MetricRegistry], qualifiers=[@org.eclipse.microprofile.metrics.annotation.RegistryType(type=VENDOR)]]
Required type: class org.eclipse.microprofile.metrics.MetricRegistry
Required qualifiers: [@org.eclipse.microprofile.metrics.annotation.RegistryType(type=VENDOR)]
Solutions:
	- Application developers can eliminate false positives via the @Unremovable annotation
	- Extensions can eliminate false positives via build items, e.g. using the UnremovableBeanBuildItem
	- See also https://quarkus.io/guides/cdi-reference#remove_unused_beans
```

Unfortunately, `io.quarkus.smallrye.graphql.deployment.MetricsTest` is unable to catch this error, because the test itself injects the vendor registry, therefore it's not unused and everything works....


Changed files:
extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/SmallRyeGraphQLProcessor.java
extensions/smallrye-graphql/deployment/src/test/java/io/quarkus/smallrye/graphql/deployment/MetricsTest.java

diff --git a/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/SmallRyeGraphQLProcessor.java b/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/SmallRyeGraphQLProcessor.java
index 4a10723fefc..2b1bf82f786 100644
--- a/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/SmallRyeGraphQLProcessor.java
+++ b/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/SmallRyeGraphQLProcessor.java
@@ -26,6 +26,7 @@
 import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
 import io.quarkus.arc.deployment.BeanContainerBuildItem;
 import io.quarkus.arc.deployment.BeanDefiningAnnotationBuildItem;
+import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
 import io.quarkus.bootstrap.model.AppArtifact;
 import io.quarkus.bootstrap.model.AppDependency;
 import io.quarkus.deployment.Capabilities;
@@ -54,6 +55,7 @@
 import io.quarkus.deployment.util.IoUtil;
 import io.quarkus.deployment.util.ServiceUtil;
 import io.quarkus.runtime.LaunchMode;
+import io.quarkus.runtime.metrics.MetricsFactory;
 import io.quarkus.smallrye.graphql.runtime.SmallRyeGraphQLRecorder;
 import io.quarkus.vertx.http.deployment.HttpRootPathBuildItem;
 import io.quarkus.vertx.http.deployment.RequireBodyHandlerBuildItem;
@@ -168,9 +170,13 @@ void buildExecutionService(
     void activateMetrics(Capabilities capabilities,
             Optional<MetricsCapabilityBuildItem> metricsCapability,
             SmallRyeGraphQLConfig smallRyeGraphQLConfig,
-            BuildProducer<SystemPropertyBuildItem> systemProperties) {
+            BuildProducer<SystemPropertyBuildItem> systemProperties,
+            BuildProducer<UnremovableBeanBuildItem> unremovableBeans) {
         if (smallRyeGraphQLConfig.metricsEnabled) {
             if (metricsCapability.isPresent()) {
+                if (metricsCapability.get().metricsSupported(MetricsFactory.MP_METRICS)) {
+                    unremovableBeans.produce(UnremovableBeanBuildItem.beanClassNames("io.smallrye.metrics.MetricRegistries"));
+                }
                 systemProperties.produce(new SystemPropertyBuildItem("smallrye.graphql.metrics.enabled", "true"));
             } else {
                 LOG.info("The quarkus.smallrye-graphql.metrics.enabled property is true, but a metrics " +
diff --git a/extensions/smallrye-graphql/deployment/src/test/java/io/quarkus/smallrye/graphql/deployment/MetricsTest.java b/extensions/smallrye-graphql/deployment/src/test/java/io/quarkus/smallrye/graphql/deployment/MetricsTest.java
index fd535769cc1..8afcdbb3138 100644
--- a/extensions/smallrye-graphql/deployment/src/test/java/io/quarkus/smallrye/graphql/deployment/MetricsTest.java
+++ b/extensions/smallrye-graphql/deployment/src/test/java/io/quarkus/smallrye/graphql/deployment/MetricsTest.java
@@ -3,7 +3,6 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
-import javax.inject.Inject;
 import javax.json.Json;
 import javax.json.JsonObject;
 
@@ -11,7 +10,6 @@
 import org.eclipse.microprofile.metrics.MetricRegistry;
 import org.eclipse.microprofile.metrics.SimpleTimer;
 import org.eclipse.microprofile.metrics.Tag;
-import org.eclipse.microprofile.metrics.annotation.RegistryType;
 import org.hamcrest.CoreMatchers;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.asset.EmptyAsset;
@@ -22,6 +20,7 @@
 
 import io.quarkus.test.QuarkusUnitTest;
 import io.restassured.RestAssured;
+import io.smallrye.metrics.MetricRegistries;
 
 public class MetricsTest {
 
@@ -32,13 +31,10 @@ public class MetricsTest {
                     .addAsResource(new StringAsset("quarkus.smallrye-graphql.metrics.enabled=true"), "application.properties")
                     .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"));
 
-    @Inject
-    @RegistryType(type = MetricRegistry.Type.VENDOR)
-    MetricRegistry metricRegistry;
-
     // Run a Query and check that its corresponding metric is updated
     @Test
     public void testQuery() {
+        MetricRegistry metricRegistry = MetricRegistries.get(MetricRegistry.Type.VENDOR);
         SimpleTimer metric = metricRegistry.getSimpleTimers()
                 .get(new MetricID("mp_graphql", new Tag("type", "Query"), new Tag("name", "ping")));
         assertNotNull(metric, "Metrics should be registered eagerly");