import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.trace.export.SpanExporter;
/**
* As of SpringBoot 3.0.2 the inclusion of io.micrometer:micrometer-tracing-bridge-otel and
* io.opentelemetry:opentelemetry-exporter-otlp is not sufficient to bootstrap the SpanExporter. Adding
* io.opentelemetry:opentelemetry-sdk-extension-autoconfigure also does not help. Hence this solution which will
* probably be redundant one day.
*/
@Configuration
public class OpenTelemetryConfig {
@Value("${otel.exporter.otlp.traces.endpoint:http://localhost:4317}")
private String tracesEndpoint;
@Bean
public SpanExporter spanExporter() {
return OtlpGrpcSpanExporter.builder().setEndpoint(tracesEndpoint).build();
}
}
I also found the following necessary if you want to use io.opentelemetry.instrumentation:opentelemetry-jdbc (and probably others) as it relies on GlobalOpenTelemetry.get(). This is forcing it to be the instance produced by the micrometer-tracing-bridge-otel.
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
@Configuration
public class GlobalOpenTelemetrySetter implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof OpenTelemetry openTelemetry) {
GlobalOpenTelemetry.set(openTelemetry);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
I worry that this could have startup race conditions but is working for me at the moment. I hope the Spring team can provide proper clarification at some point.