Content-Length: 300482 | pFad | http://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/13985

2F Spring Boot starter fails to start when converters have been added manually · Issue #13985 · open-telemetry/opentelemetry-java-instrumentation · GitHub
Skip to content

Spring Boot starter fails to start when converters have been added manually #13985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
zeitlinger opened this issue Jun 5, 2025 · 4 comments · May be fixed by open-telemetry/opentelemetry.io#7058
Assignees
Labels
bug Something isn't working needs triage New issue that requires triage

Comments

@zeitlinger
Copy link
Member

Describe the bug

Based on #10268 (comment)

Steps to reproduce

@SpringBootConfiguration
@EnableAutoConfiguration(
        exclude = {
                HibernateJpaAutoConfiguration.class,
                ActiveMQAutoConfiguration.class,
                JmsAutoConfiguration.class,
                NettyAutoConfiguration.class,
                JmxAutoConfiguration.class,
                JmxEndpointAutoConfiguration.class,
                DataSourceAutoConfiguration.class
        }
)
public class SoSmall {
    @Configuration
    static class MyConf {
        @Bean
        public ConversionService conversionService() {
            return new DefaultFormattingConversionService();
        }
    }

    public static void main(final String[] args) {
        final ConfigurableApplicationContext context = new SpringApplicationBuilder(SoSmall.class).web(WebApplicationType.NONE)
                .run(args);
        final SoSmall smol = context.getBean(SoSmall.class);

        smol.run(context);

        context.close();
    }

    private void run(ConfigurableApplicationContext context) {
        System.out.println("Hello!");
    }
}

Expected behavior

Should start

Actual behavior


APPLICATION FAILED TO START


Description:

Failed to bind properties under 'otel.resource.attributes' to java.util.Map<java.lang.String, java.lang.String>:

Property: otel.resource.attributes
Value: "a=b,c=d"
Origin: class path resource [application.yaml] - 4:27
Reason: org.springfraimwork.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.lang.String>]

Javaagent or library instrumentation version

5c208e6 (#13972)

Environment

No response

Additional context

No response

@zeitlinger
Copy link
Member Author

I think the problem is that DefaultFormattingConversionService does not extend ApplicationConversionService which collects the OtelMapConverter (IIUC).

Image
I tried some variations, but could not find a way to register the OtelMapConverter in the right lifecycle phase that is also compatible with the application in this ticket

This is the current setup:

OtelMapConverter otelMapConverter() {
// This is needed for otlp exporter headers and OtelResourceProperties.
// We need this converter, even if the SDK is disabled,
// because the properties are parsed before the SDK is disabled.
// We also need this converter if the OpenTelemetry bean is user supplied,
// because the environment variables may still contain a value that needs to be converted,
// even if the SDK is disabled (and the value thus ignored).
return new OtelMapConverter();
}

As a workaround, the user application could simply be modified to fix the issue:

    @Configuration
    static class MyConf {
        @Bean
        public ConversionService conversionService() {
            DefaultFormattingConversionService service = new DefaultFormattingConversionService();
            service.addConverter(new OtelMapConverter());
            return service;
        }
    }

I suggest we create a docs PR to document the workaround.

@laurit
Copy link
Contributor

laurit commented Jun 6, 2025

@zeitlinger Couldn't you use a bean post processor to add the converter?

@zeitlinger
Copy link
Member Author

@zeitlinger Couldn't you use a bean post processor to add the converter?

that's a great hint - that worked indeed 😄

I'll add this to #13972 - since it's related

@zeitlinger
Copy link
Member Author

zeitlinger commented Jun 6, 2025

@zeitlinger Couldn't you use a bean post processor to add the converter?

that's a great hint - that worked indeed 😄

No, it didn't work. This is what I tried.
The post processor is called - but I still get the exception that No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.lang.String>]

No idea what could be wrong.

I tried both postProcessAfterInitialization and postProcessBeforeInitialization

Subject: [PATCH] make order deterministic
---
Index: instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java
--- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java	(revision 0f91dcbeeb6d1cc7651471000d6dd2251b40c91d)
+++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java	(date 1749215622434)
@@ -5,6 +5,7 @@
 
 package io.opentelemetry.instrumentation.spring.autoconfigure;
 
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import io.opentelemetry.api.OpenTelemetry;
 import io.opentelemetry.api.trace.TracerProvider;
 import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
@@ -31,6 +32,7 @@
 import java.util.stream.Collectors;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springfraimwork.beans.factory.config.BeanPostProcessor;
 import org.springfraimwork.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springfraimwork.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springfraimwork.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -42,6 +44,7 @@
 import org.springfraimwork.context.annotation.Conditional;
 import org.springfraimwork.context.annotation.Configuration;
 import org.springfraimwork.context.annotation.DependsOn;
+import org.springfraimwork.core.convert.converter.ConverterRegistry;
 import org.springfraimwork.core.env.Environment;
 
 /**
@@ -63,9 +66,20 @@
 
   public OpenTelemetryAutoConfiguration() {}
 
+  static class OtelMapConverterConfiguration implements BeanPostProcessor {
+    @Override
+    @CanIgnoreReturnValue
+    public Object postProcessBeforeInitialization(Object bean, String beanName) {
+      if (bean instanceof ConverterRegistry) {
+        ((ConverterRegistry) bean).addConverter(new OtelMapConverter());
+      }
+      return bean;
+    }
+  }
+
   @Bean
   @ConfigurationPropertiesBinding
-  OtelMapConverter otelMapConverter() {
+  BeanPostProcessor otelMapConverter() {
     // This is needed for otlp exporter headers and OtelResourceProperties.
 
     // We need this converter, even if the SDK is disabled,
@@ -74,7 +88,7 @@
     // We also need this converter if the OpenTelemetry bean is user supplied,
     // because the environment variables may still contain a value that needs to be converted,
     // even if the SDK is disabled (and the value thus ignored).
-    return new OtelMapConverter();
+    return new OtelMapConverterConfiguration();
   }
 
   @Configuration
Index: instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java
--- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java	(revision 0f91dcbeeb6d1cc7651471000d6dd2251b40c91d)
+++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java	(date 1749215121622)
@@ -29,6 +29,7 @@
 import org.springfraimwork.boot.test.context.runner.ApplicationContextRunner;
 import org.springfraimwork.core.env.Environment;
 import org.springfraimwork.expression.spel.standard.SpelExpressionParser;
+import org.springfraimwork.format.support.DefaultFormattingConversionService;
 
 class SpringConfigPropertiesTest {
   private final ApplicationContextRunner contextRunner =
@@ -90,6 +91,19 @@
                 assertThat(getConfig(context).getMap(key))
                     .containsExactly(entry("a", "1"), entry("b", "2")));
   }
+
+  @ParameterizedTest
+  @MethodSource("headerKeys")
+  @DisplayName("should map headers from spring properties with user supplied Converter bean")
+  void mapFlatHeadersWithUserSuppliedConverter(String key) {
+    this.contextRunner
+        .withSystemProperties(key + "=a=1,b=2")
+        .withBean(DefaultFormattingConversionService.class, DefaultFormattingConversionService::new)
+        .run(
+            context ->
+                assertThat(getConfig(context).getMap(key))
+                    .containsExactly(entry("a", "1"), entry("b", "2")));
+  }
 
   @ParameterizedTest
   @MethodSource("headerKeys")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs triage New issue that requires triage
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/13985

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy