Skip to content

spring-boot-metrics with micrometer-registry-otlp throws exception if spring-boot-opentelemetry is missing #46303

@wilkinsona

Description

@wilkinsona

See #46229 (comment) for some background. In addition to management.opentelemetry.resource-attributes affecting the resource attributes that are included when exported metrics over OTLP, we also have a problem with conditions at the moment.

With these three dependencies:

implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-metrics'
runtimeOnly 'io.micrometer:micrometer-registry-otlp'

An app will fail to start with the following exception:

java.lang.IllegalArgumentException: Could not find class [org.springframework.boot.opentelemetry.autoconfigure.OpenTelemetryProperties]
        at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:353) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:451) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:384) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.core.annotation.TypeMappedAnnotation.asMap(TypeMappedAnnotation.java:273) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.core.annotation.AbstractMergedAnnotation.asAnnotationAttributes(AbstractMergedAnnotation.java:191) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:143) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:110) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.registerBeanDefinitionForImportedConfigurationClass(ConfigurationClassBeanDefinitionReader.java:167) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:147) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:126) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:446) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:306) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:781) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:599) ~[spring-context-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) ~[spring-boot-4.0.0-SNAPSHOT.jar:4.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435) ~[spring-boot-4.0.0-SNAPSHOT.jar:4.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-4.0.0-SNAPSHOT.jar:4.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1344) ~[spring-boot-4.0.0-SNAPSHOT.jar:4.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1333) ~[spring-boot-4.0.0-SNAPSHOT.jar:4.0.0-SNAPSHOT]
        at com.example.gh_46229.Gh46229Application.main(Gh46229Application.java:10) ~[main/:na]
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.opentelemetry.autoconfigure.OpenTelemetryProperties
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) ~[na:na]
        at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
        at java.base/java.lang.Class.forName(Class.java:534) ~[na:na]
        at java.base/java.lang.Class.forName(Class.java:513) ~[na:na]
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:302) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:343) ~[spring-core-7.0.0-SNAPSHOT.jar:7.0.0-SNAPSHOT]
        ... 21 common frames omitted

The code in spring-boot-metrics that deals with OTLP currently assumes that spring-boot-opentelemetry will also be on the classpath but that may not be the case. Making it a required dependency would require introducing a new module as spring-boot-metrics itself should not have a required dependency on spring-boot-opentelemetry. Leaving it optional but with appropriate conditions in place would address the CNFE above but may add to the confusion about the different between OTLP and OpenTelemetry and when the management.opentelemetry properties will and will not have an effect.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions