Skip to content
Open
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
5b1236d
autoconfigure and smoke
jaydeluca Nov 25, 2025
38d6dc4
progress
jaydeluca Nov 25, 2025
ba32a8d
kafka
jaydeluca Nov 26, 2025
6c13ecb
kafka working
jaydeluca Nov 26, 2025
330cd89
most things working
jaydeluca Nov 26, 2025
f100658
fix more tests, exclude tests from latestdeps
jaydeluca Nov 26, 2025
9c6f987
micrometer fix
jaydeluca Nov 26, 2025
79629d2
add kafka test
jaydeluca Nov 26, 2025
30d0e2c
native and another micrometer issue
jaydeluca Nov 26, 2025
be14d94
fix codeql
jaydeluca Nov 26, 2025
6757a63
fix test on java 25
jaydeluca Nov 27, 2025
25b980b
Merge branch 'main' into spring-boot-4-autoconfigure
jaydeluca Nov 27, 2025
6562745
ignore transient kafka startup errors
jaydeluca Nov 27, 2025
7e75966
Merge branch 'spring-boot-4-autoconfigure' of github.com:jaydeluca/op…
jaydeluca Nov 27, 2025
f37f691
Merge branch 'main' into spring-boot-4-autoconfigure
jaydeluca Nov 27, 2025
a37c8a5
register both mongo configs
jaydeluca Nov 27, 2025
a406382
more smoke test changes
jaydeluca Nov 27, 2025
3113936
test fix
jaydeluca Nov 27, 2025
f86e06e
missing mongo
jaydeluca Nov 27, 2025
bc3519d
avoid using common to fix dependency issues
jaydeluca Nov 27, 2025
fcf6bce
add propagators and app file
jaydeluca Nov 27, 2025
cbc8b1e
only run native tests on java 25+
jaydeluca Nov 28, 2025
1a83d20
cleanup
jaydeluca Nov 28, 2025
c2d5230
cleanup
jaydeluca Nov 28, 2025
9ce1a80
Merge branch 'main' into spring-boot-4-autoconfigure
jaydeluca Nov 28, 2025
d17fed1
fix comment line breaks
jaydeluca Nov 28, 2025
36c991a
switch to using conditionalOnClass
jaydeluca Nov 29, 2025
10fef8c
abstract incompatible class
jaydeluca Nov 29, 2025
103cecb
start refactoring common test module
jaydeluca Dec 2, 2025
153195e
finish common testing module
jaydeluca Dec 2, 2025
e6a8ae4
create spring 2 suite to avoid exlusions
jaydeluca Dec 2, 2025
7ac8f91
refactor smoke tests to avoid duplication for kafka and mongo, jfr as…
jaydeluca Dec 2, 2025
59994b7
further reduce test duplication
jaydeluca Dec 2, 2025
c7d5de8
fix
jaydeluca Dec 2, 2025
0a5806f
add dependency
jaydeluca Dec 3, 2025
c8516d7
japi cmp
jaydeluca Dec 3, 2025
d88ceef
fix kafka separation of configs
jaydeluca Dec 3, 2025
e375143
Merge branch 'main' into spring-boot-4-autoconfigure
jaydeluca Dec 3, 2025
8f75f72
revert jApiCmd
jaydeluca Dec 3, 2025
fc726fe
fix conditionals
jaydeluca Dec 3, 2025
0c6e263
extending wrong test classes
jaydeluca Dec 4, 2025
088b920
Merge branch 'main' into spring-boot-4-autoconfigure
laurit Dec 5, 2025
3b18b94
fix jApiCmp
laurit Dec 5, 2025
24aac9a
update fossa configuration
laurit Dec 5, 2025
879cdde
review
laurit Dec 5, 2025
41879d3
fix graal tests
jaydeluca Dec 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .fossa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,9 @@ targets:
- type: gradle
path: ./
target: ':instrumentation:spring:spring-boot-actuator-autoconfigure-2.0:javaagent'
- type: gradle
path: ./
target: ':instrumentation:spring:spring-boot-autoconfigure:testing'
- type: gradle
path: ./
target: ':instrumentation:spring:spring-boot-resources:javaagent'
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ jobs:
./gradlew assemble -x javadoc
-x :smoke-tests-otel-starter:spring-boot-3:collectReachabilityMetadata
-x :smoke-tests-otel-starter:spring-boot-3.2:collectReachabilityMetadata
-x :smoke-tests-otel-starter:spring-boot-4:collectReachabilityMetadata
-x :smoke-tests-otel-starter:spring-boot-reactive-3:collectReachabilityMetadata
--no-build-cache --no-daemon

Expand Down
114 changes: 105 additions & 9 deletions instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,20 @@ sourceSets {
setSrcDirs(listOf("src/main/javaSpring3"))
}
}
create("javaSpring4") {
java {
setSrcDirs(listOf("src/main/javaSpring4"))
}
}
}

configurations {
named("javaSpring3CompileOnly") {
extendsFrom(configurations["compileOnly"])
}
named("javaSpring4CompileOnly") {
extendsFrom(configurations["compileOnly"])
}
}

dependencies {
Expand Down Expand Up @@ -99,6 +107,9 @@ dependencies {
testImplementation("io.opentelemetry:opentelemetry-exporter-otlp")
testImplementation("io.opentelemetry:opentelemetry-exporter-zipkin")
testImplementation(project(":instrumentation-annotations"))
testImplementation(project(":instrumentation:spring:spring-boot-autoconfigure:testing"))

latestDepTestLibrary("org.springframework.boot:spring-boot-starter-micrometer-metrics:latest.release")

// needed for the Spring Boot 3 support
implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library"))
Expand All @@ -110,15 +121,19 @@ dependencies {
add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-web:spring-web-3.1:library"))
add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library"))

// tests don't work with spring boot 4 yet
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-test:3.+") // documented limitation
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-actuator:3.+") // documented limitation
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-aop:3.+") // documented limitation
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-web:3.+") // documented limitation
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-webflux:3.+") // documented limitation
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-data-mongodb:3.+") // documented limitation
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-data-r2dbc:3.+") // documented limitation
latestDepTestLibrary("org.springframework.boot:spring-boot-starter-data-jdbc:3.+") // documented limitation
// Spring Boot 4
add("javaSpring4CompileOnly", files(sourceSets.main.get().output.classesDirs))
add("javaSpring4CompileOnly", "org.springframework.boot:spring-boot-starter-kafka:4.0.0")
add("javaSpring4CompileOnly", "org.springframework.boot:spring-boot-autoconfigure:4.0.0")
add("javaSpring4CompileOnly", "org.springframework.boot:spring-boot-jdbc:4.0.0")
add("javaSpring4CompileOnly", "org.springframework.boot:spring-boot-starter-jdbc:4.0.0")
add("javaSpring4CompileOnly", "org.springframework.boot:spring-boot-restclient:4.0.0")
add("javaSpring4CompileOnly", "org.springframework.boot:spring-boot-starter-data-mongodb:4.0.0")
add("javaSpring4CompileOnly", "org.springframework.boot:spring-boot-starter-micrometer-metrics:4.0.0")
add("javaSpring4CompileOnly", project(":instrumentation:kafka:kafka-clients:kafka-clients-2.6:library"))
add("javaSpring4CompileOnly", project(":instrumentation:spring:spring-kafka-2.7:library"))
add("javaSpring4CompileOnly", project(":instrumentation:mongo:mongo-3.1:library"))
add("javaSpring4CompileOnly", project(":instrumentation:micrometer:micrometer-1.5:library"))
}

val latestDepTest = findProperty("testLatestDeps") as Boolean
Expand Down Expand Up @@ -172,6 +187,24 @@ testing {
}
}

val testSpring2 by registering(JvmTestSuite::class) {
dependencies {
implementation(project())
implementation("io.opentelemetry:opentelemetry-sdk")
implementation("io.opentelemetry:opentelemetry-sdk-testing")
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
implementation(project(":instrumentation-api"))
implementation(project(":instrumentation:micrometer:micrometer-1.5:library"))
implementation(project(":instrumentation:spring:spring-boot-autoconfigure:testing"))
implementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") {
exclude("org.junit.vintage", "junit-vintage-engine")
}
implementation("javax.servlet:javax.servlet-api:3.1.0")
runtimeOnly("com.h2database:h2:1.4.197")
runtimeOnly("io.r2dbc:r2dbc-h2:1.0.0.RELEASE")
}
}

val testSpring3 by registering(JvmTestSuite::class) {
dependencies {
implementation(project())
Expand All @@ -186,6 +219,29 @@ testing {
}
}

val testSpring4 by registering(JvmTestSuite::class) {
dependencies {
implementation(project())
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
implementation("org.springframework.boot:spring-boot-starter-jdbc:4.0.0")
implementation("org.springframework.boot:spring-boot-restclient:4.0.0")
implementation("org.springframework.boot:spring-boot-starter-kafka:4.0.0")
implementation("org.springframework.boot:spring-boot-starter-actuator:4.0.0")
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc:4.0.0")
implementation("org.springframework.boot:spring-boot-starter-micrometer-metrics:4.0.0")
implementation("io.opentelemetry:opentelemetry-sdk")
implementation("io.opentelemetry:opentelemetry-sdk-testing")
implementation(project(":instrumentation-api"))
implementation(project(":instrumentation:micrometer:micrometer-1.5:library"))
implementation(project(":instrumentation:spring:spring-boot-autoconfigure:testing"))
implementation("org.springframework.boot:spring-boot-starter-test:4.0.0") {
exclude("org.junit.vintage", "junit-vintage-engine")
}
runtimeOnly("com.h2database:h2:1.4.197")
runtimeOnly("io.r2dbc:r2dbc-h2:1.0.0.RELEASE")
}
}

val testDeclarativeConfig by registering(JvmTestSuite::class) {
dependencies {
implementation(project())
Expand All @@ -204,6 +260,18 @@ configurations.configureEach {
if (name.contains("testLogbackMissing")) {
exclude("ch.qos.logback", "logback-classic")
}
// testSpring2: configure Spring Boot 3.x dependencies for latest dep testing
if (name == "testSpring2Implementation") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this does not involve any latest dep checks this will bump the version to latest spring 3 even in regular tests?

dependencies {
add(name, "org.springframework.boot:spring-boot-starter-web:3.+")
add(name, "org.springframework.boot:spring-boot-starter-jdbc:3.+")
add(name, "org.springframework.boot:spring-boot-starter-actuator:3.+")
add(name, "org.springframework.boot:spring-boot-starter-data-r2dbc:3.+")
add(name, "org.springframework.kafka:spring-kafka:3.+")
add(name, project(":instrumentation:kafka:kafka-clients:kafka-clients-2.6:library"))
add(name, project(":instrumentation:spring:spring-kafka-2.7:library"))
}
}
}

tasks {
Expand All @@ -225,22 +293,50 @@ tasks {
options.release.set(17)
}

named<JavaCompile>("compileTestSpring2Java") {
sourceCompatibility = "17"
targetCompatibility = "17"
options.release.set(17)
}

named<JavaCompile>("compileTestSpring3Java") {
sourceCompatibility = "17"
targetCompatibility = "17"
options.release.set(17)
}

named<Test>("testSpring2") {
isEnabled = testSpring3
}

named<Test>("testSpring3") {
isEnabled = testSpring3
}

named<JavaCompile>("compileJavaSpring4Java") {
sourceCompatibility = "17"
targetCompatibility = "17"
options.release.set(17)
}

named<JavaCompile>("compileTestSpring4Java") {
sourceCompatibility = "17"
targetCompatibility = "17"
options.release.set(17)
}

named<Test>("testSpring4") {
isEnabled = testSpring3 // same condition as Spring 3 (requires Java 17+)
}

named<Jar>("jar") {
from(sourceSets["javaSpring3"].output)
from(sourceSets["javaSpring4"].output)
}

named<Jar>("sourcesJar") {
from(sourceSets["javaSpring3"].java)
from(sourceSets["javaSpring4"].java)
}

val testStableSemconv by registering(Test::class) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
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.ConditionalOnClass;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -23,6 +24,7 @@
@ConditionalOnEnabledInstrumentation(module = "jdbc")
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@ConditionalOnBean({DataSource.class})
@ConditionalOnClass(DataSourceAutoConfiguration.class) // module changed in Spring Boot 4
@Configuration(proxyBeanMethods = false)
public class JdbcInstrumentationAutoConfiguration {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@

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.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.kafka.DefaultKafkaProducerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
Expand All @@ -27,17 +25,12 @@
@ConditionalOnClass({
KafkaTemplate.class,
ConcurrentKafkaListenerContainerFactory.class,
DefaultKafkaProducerFactoryCustomizer.class
})
@Configuration
public class KafkaInstrumentationAutoConfiguration {

@Bean
DefaultKafkaProducerFactoryCustomizer otelKafkaProducerFactoryCustomizer(
OpenTelemetry openTelemetry) {
KafkaTelemetry kafkaTelemetry = KafkaTelemetry.create(openTelemetry);
return producerFactory -> producerFactory.addPostProcessor(kafkaTelemetry::wrap);
}
// For error prone
public KafkaInstrumentationAutoConfiguration() {}

@Bean
static SpringKafkaTelemetry getTelemetry(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.kafkaclients.v2_6.KafkaTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.kafka.DefaultKafkaProducerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
@ConditionalOnEnabledInstrumentation(module = "kafka")
// package changed in Spring Boot 4
@ConditionalOnClass({
DefaultKafkaProducerFactoryCustomizer.class,
DefaultKafkaProducerFactory.class
})
@Configuration
public class ProducerFactoryCustomizerConfiguration {
@Bean
DefaultKafkaProducerFactoryCustomizer otelKafkaProducerFactoryCustomizer(
OpenTelemetry openTelemetry) {
KafkaTelemetry kafkaTelemetry = KafkaTelemetry.create(openTelemetry);
return producerFactory -> producerFactory.addPostProcessor(kafkaTelemetry::wrap);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@AutoConfigureAfter({MetricsAutoConfiguration.class, OpenTelemetryAutoConfiguration.class})
@AutoConfigureBefore(CompositeMeterRegistryAutoConfiguration.class)
@ConditionalOnBean(Clock.class)
@ConditionalOnClass(MeterRegistry.class)
@ConditionalOnClass(MeterRegistry.class) // module changed in Spring Boot 4
@Configuration
public class MicrometerBridgeAutoConfiguration {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
@ConditionalOnClass({MongoClientSettings.class, MongoClientSettingsBuilderCustomizer.class})
@ConditionalOnClass({
MongoClientSettings.class,
MongoClientSettingsBuilderCustomizer.class
}) // module changed in Spring Boot 4
@ConditionalOnEnabledInstrumentation(module = "mongo")
@Configuration
public class MongoClientInstrumentationAutoConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.web.client.RestTemplate;

final class RestTemplateBeanPostProcessor implements BeanPostProcessor {
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public final class RestTemplateBeanPostProcessor implements BeanPostProcessor {

private final ObjectProvider<OpenTelemetry> openTelemetryProvider;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.ConditionalOnClass;
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)
@ConditionalOnClass(DataSourceAutoConfiguration.class)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

condition looks identical to boot 3

public class JdbcInstrumentationSpringBoot4AutoConfiguration {

// For error prone
public JdbcInstrumentationSpringBoot4AutoConfiguration() {}

@Bean
// static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really for this PR but I suspect that (proxyBeanMethods = false) has the same effect as making the method static. If I remember correctly the warning was triggered by proxying the configuration class methods.

Copy link
Member

Choose a reason for hiding this comment

The 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);
}
}
Loading
Loading