-
Notifications
You must be signed in to change notification settings - Fork 1k
[Spring Starter] Spring boot 4 support #15459
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
base: main
Are you sure you want to change the base?
Changes from 25 commits
5b1236d
38d6dc4
ba32a8d
6c13ecb
330cd89
f100658
9c6f987
79629d2
30d0e2c
be14d94
6757a63
25b980b
6562745
7e75966
f37f691
a37c8a5
a406382
3113936
f86e06e
bc3519d
fcf6bce
cbc8b1e
1a83d20
c2d5230
9ce1a80
d17fed1
36c991a
10fef8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc; | ||
|
|
||
| import io.opentelemetry.api.OpenTelemetry; | ||
| import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; | ||
| import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; | ||
| import javax.sql.DataSource; | ||
| import org.springframework.beans.factory.ObjectProvider; | ||
| import org.springframework.boot.autoconfigure.AutoConfiguration; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; | ||
| import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| /** | ||
| * This class is internal and is hence not for public use. Its APIs are unstable and can change at | ||
| * any time. | ||
| */ | ||
| @ConditionalOnEnabledInstrumentation(module = "jdbc") | ||
| @AutoConfiguration(after = DataSourceAutoConfiguration.class) | ||
| @ConditionalOnBean({DataSource.class}) | ||
| @Configuration(proxyBeanMethods = false) | ||
| @ConditionalOnMissingClass( | ||
zeitlinger marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration") // Spring Boot 2 & 3 | ||
| public class JdbcInstrumentationSpringBoot4AutoConfiguration { | ||
zeitlinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // For error prone | ||
| public JdbcInstrumentationSpringBoot4AutoConfiguration() {} | ||
|
|
||
| @Bean | ||
| // static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really for this PR but I suspect that
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're right - that would be a nice follow-up PR |
||
| static DataSourcePostProcessor dataSourcePostProcessor( | ||
| ObjectProvider<OpenTelemetry> openTelemetryProvider, | ||
| ObjectProvider<InstrumentationConfig> configProvider) { | ||
| return new DataSourcePostProcessor(openTelemetryProvider, configProvider); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.kafka; | ||
|
|
||
| import io.opentelemetry.api.OpenTelemetry; | ||
| import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; | ||
| import io.opentelemetry.instrumentation.kafkaclients.v2_6.KafkaTelemetry; | ||
| import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; | ||
| import io.opentelemetry.instrumentation.spring.kafka.v2_7.SpringKafkaTelemetry; | ||
| import org.springframework.beans.factory.ObjectProvider; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| import org.springframework.boot.kafka.autoconfigure.DefaultKafkaProducerFactoryCustomizer; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; | ||
| import org.springframework.kafka.core.KafkaTemplate; | ||
|
|
||
| /** | ||
| * This class is internal and is hence not for public use. Its APIs are unstable and can change at | ||
| * any time. | ||
| */ | ||
| @ConditionalOnEnabledInstrumentation(module = "kafka") | ||
| @ConditionalOnClass({ | ||
| KafkaTemplate.class, | ||
| ConcurrentKafkaListenerContainerFactory.class, | ||
| DefaultKafkaProducerFactoryCustomizer.class | ||
| }) | ||
| @ConditionalOnMissingBean(name = "otelKafkaProducerFactoryCustomizer") | ||
| @ConditionalOnMissingClass( | ||
| "org.springframework.boot.autoconfigure.kafka.DefaultKafkaProducerFactoryCustomizer") // Spring | ||
| // Boot 2 | ||
| // & 3 | ||
| @Configuration | ||
| public class KafkaInstrumentationSpringBoot4AutoConfiguration { | ||
|
|
||
| @Bean | ||
| DefaultKafkaProducerFactoryCustomizer otelKafkaProducerFactoryCustomizer( | ||
| OpenTelemetry openTelemetry) { | ||
| KafkaTelemetry kafkaTelemetry = KafkaTelemetry.create(openTelemetry); | ||
| return producerFactory -> producerFactory.addPostProcessor(kafkaTelemetry::wrap); | ||
| } | ||
|
Comment on lines
+37
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually only this bean is different for spring boot 4. Wondering whether it would make sense to move this bean into separate (maybe nested?) configuration class so that the other beans wouldn't need to be copy-pasted. Or is that too much effort?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| @Bean | ||
| static SpringKafkaTelemetry getTelemetry( | ||
| ObjectProvider<OpenTelemetry> openTelemetryProvider, | ||
| ObjectProvider<InstrumentationConfig> configProvider) { | ||
| return SpringKafkaTelemetry.builder(openTelemetryProvider.getObject()) | ||
| .setCaptureExperimentalSpanAttributes( | ||
| configProvider | ||
| .getObject() | ||
| .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) | ||
| .build(); | ||
| } | ||
|
|
||
| // static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning | ||
| @Bean | ||
| @ConditionalOnProperty( | ||
| name = "otel.instrumentation.kafka.autoconfigure-interceptor", | ||
| havingValue = "true", | ||
| matchIfMissing = true) | ||
| @ConditionalOnMissingBean | ||
| static ConcurrentKafkaListenerContainerFactoryPostProcessor | ||
| otelKafkaListenerContainerFactoryBeanPostProcessor( | ||
| ObjectProvider<OpenTelemetry> openTelemetryProvider, | ||
| ObjectProvider<InstrumentationConfig> configProvider) { | ||
| return new ConcurrentKafkaListenerContainerFactoryPostProcessor( | ||
| () -> getTelemetry(openTelemetryProvider, configProvider)); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.micrometer; | ||
|
|
||
| import io.micrometer.core.instrument.Clock; | ||
| import io.micrometer.core.instrument.MeterRegistry; | ||
| import io.opentelemetry.api.OpenTelemetry; | ||
| import io.opentelemetry.instrumentation.micrometer.v1_5.OpenTelemetryMeterRegistry; | ||
| import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; | ||
| import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; | ||
| import org.springframework.boot.autoconfigure.AutoConfigureAfter; | ||
| import org.springframework.boot.autoconfigure.AutoConfigureBefore; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
| import org.springframework.boot.micrometer.metrics.autoconfigure.CompositeMeterRegistryAutoConfiguration; | ||
| import org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| /** | ||
| * This class is internal and is hence not for public use. Its APIs are unstable and can change at | ||
| * any time. | ||
| */ | ||
| @ConditionalOnEnabledInstrumentation(module = "micrometer", enabledByDefault = false) | ||
| @AutoConfigureAfter({MetricsAutoConfiguration.class, OpenTelemetryAutoConfiguration.class}) | ||
| @AutoConfigureBefore(CompositeMeterRegistryAutoConfiguration.class) | ||
| @ConditionalOnBean(Clock.class) | ||
| @ConditionalOnClass({MeterRegistry.class, MetricsAutoConfiguration.class}) | ||
| @Configuration | ||
| public class MicrometerBridgeSpringBoot4AutoConfiguration { | ||
|
|
||
| @Bean | ||
| MeterRegistry otelMeterRegistry(OpenTelemetry openTelemetry, Clock micrometerClock) { | ||
| return OpenTelemetryMeterRegistry.builder(openTelemetry).setClock(micrometerClock).build(); | ||
| } | ||
| } |

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes when we have a separate suite for new version we limit the latest dep in base version to
1.+and in version2suite either set the version to2.0orlatest.releasedepending on the latest dep flag. Would that also work here? Or maybe it would help if these tests were moved to a separate suite and the main test directory would only contain tests that work on all versions?