-
Notifications
You must be signed in to change notification settings - Fork 68
Description
Expected Behavior
Attempting to inject a MeterRegistry with OtlpMeterRegistry on the classpath in an otherwise-minimal project should work without issue.
Actual Behaviour
Attempting to inject a MeterRegistry with OtlpMeterRegistry on the classpath in an otherwise-minimal project results in the following exception:
io.micronaut.context.exceptions.BeanInstantiationException:
Error instantiating bean of type [io.micrometer.core.instrument.composite.CompositeMeterRegistry]
Message: com/google/protobuf/RuntimeVersion$RuntimeDomain
Path Taken:
c.e.OtlpMeterRegistryDependencyDemoTest#meterRegistry
\---> @i.m.c.a.Primary @j.i.Singleton i.m.c.i.c.CompositeMeterRegistry i.m.c.m.m.MeterRegistryFactory.compositeMeterRegistry#compositeMeterRegistry([List<MeterRegistry> registries], List<MeterRegistryConfigurer<MeterRegistry>> configurers)
at io.micronaut.context.DefaultBeanContext.resolveByBeanFactory(DefaultBeanContext.java:2357)
at io.micronaut.context.DefaultBeanContext.createRegistration(DefaultBeanContext.java:3162)
at io.micronaut.context.SingletonScope.getOrCreate(SingletonScope.java:80)
at io.micronaut.context.DefaultBeanContext.resolveBeanRegistration(DefaultBeanContext.java:3012)
at io.micronaut.context.DefaultBeanContext.addCandidateToList(DefaultBeanContext.java:3625)
at io.micronaut.context.DefaultBeanContext.resolveBeanRegistrations(DefaultBeanContext.java:3580)
at io.micronaut.context.DefaultBeanContext.getBeanRegistrations(DefaultBeanContext.java:3554)
at io.micronaut.context.DefaultBeanContext.getBeansOfType(DefaultBeanContext.java:1480)
at io.micronaut.context.AbstractBeanResolutionContext.getBeansOfType(AbstractBeanResolutionContext.java:240)
at io.micronaut.context.AbstractInitializableBeanDefinition.resolveBeansOfType(AbstractInitializableBeanDefinition.java:2226)
at io.micronaut.context.AbstractInitializableBeanDefinition.getBeansOfTypeForConstructorArgument(AbstractInitializableBeanDefinition.java:1515)
at io.micronaut.configuration.metrics.micrometer.$MeterRegistryFactory$CompositeMeterRegistry0$Definition.instantiate(Unknown Source)
at io.micronaut.context.DefaultBeanContext.resolveByBeanFactory(DefaultBeanContext.java:2342)
at io.micronaut.context.DefaultBeanContext.createRegistration(DefaultBeanContext.java:3162)
at io.micronaut.context.SingletonScope.getOrCreate(SingletonScope.java:80)
at io.micronaut.context.DefaultBeanContext.resolveBeanRegistration(DefaultBeanContext.java:3012)
at io.micronaut.context.DefaultBeanContext.resolveBeanRegistration(DefaultBeanContext.java:2774)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1786)
at io.micronaut.context.AbstractBeanResolutionContext.getBean(AbstractBeanResolutionContext.java:210)
at io.micronaut.context.AbstractInitializableBeanDefinition.resolveBean(AbstractInitializableBeanDefinition.java:2137)
at io.micronaut.context.AbstractInitializableBeanDefinition.getBeanForField(AbstractInitializableBeanDefinition.java:1711)
at com.example.$OtlpMeterRegistryDependencyDemoTest$Definition.inject(Unknown Source)
at io.micronaut.context.DefaultBeanContext.doInjectAndInitialize(DefaultBeanContext.java:2679)
at io.micronaut.context.DefaultBeanContext.inject(DefaultBeanContext.java:1014)
at io.micronaut.test.extensions.AbstractMicronautExtension.beforeEach(AbstractMicronautExtension.java:476)
at io.micronaut.test.extensions.junit5.MicronautJunit5Extension.beforeEach(MicronautJunit5Extension.java:236)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
Caused by: java.lang.NoClassDefFoundError: com/google/protobuf/RuntimeVersion$RuntimeDomain
at io.opentelemetry.proto.resource.v1.Resource.<clinit>(Resource.java:21)
at io.micrometer.registry.otlp.OtlpMeterRegistry.<init>(OtlpMeterRegistry.java:130)
at io.micrometer.registry.otlp.OtlpMeterRegistry.<init>(OtlpMeterRegistry.java:119)
at io.micrometer.registry.otlp.OtlpMeterRegistry.<init>(OtlpMeterRegistry.java:108)
at io.micronaut.configuration.metrics.micrometer.otlp.OtlpMeterRegistryFactory.otlpMeterRegistry(OtlpMeterRegistryFactory.java:51)
at io.micronaut.configuration.metrics.micrometer.otlp.$OtlpMeterRegistryFactory$OtlpMeterRegistry0$Definition.instantiate(Unknown Source)
at io.micronaut.context.DefaultBeanContext.resolveByBeanFactory(DefaultBeanContext.java:2342)
... 27 more
Caused by: java.lang.ClassNotFoundException: com.google.protobuf.RuntimeVersion$RuntimeDomain
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
... 34 more
The problem is that OtlpMeterRegistry ultimately depends on com.google.protobuf.RuntimeVersion, which exists in protobuf-java 4.x, but not 3.x. The micronaut-parent POM sets the protobuf version to 3.25.8.
This has been a problem since Micronaut 4.9.0, which bumped from a transitive dependency on io.opentelemetry.proto:opentelemetry-proto:1.2.0-alpha to ...:1.5.0-alpha, which is what introduces the protobuf-java 4.x dependency.
Steps To Reproduce
- Create a new Micronaut project:
mn create-app --build=maven --jdk=21 --lang=java --test=junit com.example.otlp-meter-registry-dependency-demo- Add
io.micronaut.micrometer:micronaut-micrometer-registry-otlpas a dependency and add@Inject MeterRegistry meterRegistryto the auto-generated test class:
diff --git a/pom.xml b/pom.xml
index 83be2e2..0080cd2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,10 @@
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>io.micronaut.micrometer</groupId>
+ <artifactId>micronaut-micrometer-registry-otlp</artifactId>
+ </dependency>
<dependency>
<groupId>io.micronaut.serde</groupId>
<artifactId>micronaut-serde-jackson</artifactId>
diff --git a/src/test/java/com/example/OtlpMeterRegistryDependencyDemoTest.java b/src/test/java/com/example/OtlpMeterRegistryDependencyDemoTest.java
index 9a4d6c2..78f3630 100644
--- a/src/test/java/com/example/OtlpMeterRegistryDependencyDemoTest.java
+++ b/src/test/java/com/example/OtlpMeterRegistryDependencyDemoTest.java
@@ -1,5 +1,6 @@
package com.example;
+import io.micrometer.core.instrument.MeterRegistry;
import io.micronaut.runtime.EmbeddedApplication;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
@@ -13,6 +14,9 @@ class OtlpMeterRegistryDependencyDemoTest {
@Inject
EmbeddedApplication<?> application;
+ @Inject
+ MeterRegistry meterRegistry;
+
@Test
void testItWorks() {
Assertions.assertTrue(application.isRunning());- Run the test:
./mvnw clean test
...
[ERROR] Errors:
[ERROR] OtlpMeterRegistryDependencyDemoTest.testItWorks » BeanInstantiation Error instantiating bean of type [io.micrometer.core.instrument.composite.CompositeMeterRegistry]
Message: com/google/protobuf/RuntimeVersion$RuntimeDomain
Path Taken:
c.e.OtlpMeterRegistryDependencyDemoTest#meterRegistry
\---> @i.m.c.a.Primary @j.i.Singleton i.m.c.i.c.CompositeMeterRegistry i.m.c.m.m.MeterRegistryFactory.compositeMeterRegistry#compositeMeterRegistry([List<MeterRegistry> registries], List<MeterRegistryConfigurer<MeterRegistry>> configurers)
Environment Information
Reproducible in all environments with Micronaut 4.9.0 or later.
Example Application
Please find an example application attached: otlp-meter-registry-dependency-demo.zip
…though the attached project is produced by creating a project with the CLI invocation given above and applying the patch included above.
Version
Micronaut 4.9.0 or later