Skip to content

Commit 6fe884f

Browse files
committed
./gradlew spotlessApply
1 parent 54241b8 commit 6fe884f

File tree

2 files changed

+75
-68
lines changed

2 files changed

+75
-68
lines changed

instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
16
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc;
27

38
import com.google.errorprone.annotations.CanIgnoreReturnValue;
49
import io.opentelemetry.api.OpenTelemetry;
510
import io.opentelemetry.instrumentation.jdbc.datasource.JdbcTelemetry;
611
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil;
712
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
8-
913
import javax.annotation.Nonnull;
1014
import javax.annotation.Nullable;
1115
import javax.sql.DataSource;
12-
1316
import org.aopalliance.intercept.MethodInterceptor;
1417
import org.aopalliance.intercept.MethodInvocation;
1518
import org.springframework.aop.framework.ProxyFactory;
@@ -46,65 +49,67 @@ private static boolean isRoutingDatasource(Object bean) {
4649
}
4750

4851
@CanIgnoreReturnValue
49-
@Override
50-
public Object postProcessAfterInitialization(Object bean, String beanName) {
51-
// Exclude scoped proxy beans to avoid double wrapping
52-
if (bean instanceof DataSource
53-
&& !isRoutingDatasource(bean)
54-
&& !ScopedProxyUtils.isScopedTarget(beanName)) {
55-
DataSource dataSource = (DataSource) bean;
52+
@Override
53+
public Object postProcessAfterInitialization(Object bean, String beanName) {
54+
// Exclude scoped proxy beans to avoid double wrapping
55+
if (bean instanceof DataSource
56+
&& !isRoutingDatasource(bean)
57+
&& !ScopedProxyUtils.isScopedTarget(beanName)) {
58+
DataSource dataSource = (DataSource) bean;
5659

57-
// Wrap the original DataSource with OpenTelemetry instrumentation
58-
DataSource wrapped = JdbcTelemetry.builder(openTelemetryProvider.getObject())
59-
.setStatementSanitizationEnabled(
60-
InstrumentationConfigUtil.isStatementSanitizationEnabled(
61-
configPropertiesProvider.getObject(),
62-
"otel.instrumentation.jdbc.statement-sanitizer.enabled"))
63-
.setCaptureQueryParameters(
64-
configPropertiesProvider
65-
.getObject()
66-
.getBoolean(
67-
"otel.instrumentation.jdbc.experimental.capture-query-parameters", false))
68-
.setTransactionInstrumenterEnabled(
69-
configPropertiesProvider
70-
.getObject()
71-
.getBoolean("otel.instrumentation.jdbc.experimental.transaction.enabled", false))
72-
.build()
73-
.wrap(dataSource);
60+
// Wrap the original DataSource with OpenTelemetry instrumentation
61+
DataSource wrapped =
62+
JdbcTelemetry.builder(openTelemetryProvider.getObject())
63+
.setStatementSanitizationEnabled(
64+
InstrumentationConfigUtil.isStatementSanitizationEnabled(
65+
configPropertiesProvider.getObject(),
66+
"otel.instrumentation.jdbc.statement-sanitizer.enabled"))
67+
.setCaptureQueryParameters(
68+
configPropertiesProvider
69+
.getObject()
70+
.getBoolean(
71+
"otel.instrumentation.jdbc.experimental.capture-query-parameters", false))
72+
.setTransactionInstrumenterEnabled(
73+
configPropertiesProvider
74+
.getObject()
75+
.getBoolean(
76+
"otel.instrumentation.jdbc.experimental.transaction.enabled", false))
77+
.build()
78+
.wrap(dataSource);
7479

75-
/**
76-
* Spring Boot's configuration binding and rebinding mechanisms (such as those triggered by
77-
* Nacos configuration refresh) may attempt to reconstruct beans using their concrete class
78-
* constructors. If a custom DataSource implementation (such as OpenTelemetryDataSource)
79-
* is returned directly, Spring may not find a suitable constructor during rebinding, resulting
80-
* in errors like "ExistingValue must be an instance of com.zaxxer.hikari.HikariDataSource".
81-
*
82-
* To prevent this, we create a JDK dynamic proxy implementing only the DataSource interface.
83-
* The proxy delegates all method calls to the wrapped (instrumented) DataSource.
84-
* This approach "hides" the actual implementation class and ensures that Spring interacts only
85-
* with the DataSource interface, avoiding issues related to constructor resolution or type casting
86-
* during bean rebinding.
87-
*/
88-
ProxyFactory proxyFactory = new ProxyFactory(DataSource.class);
89-
// Set the original bean as the target (important for AOP and bean lifecycle)
90-
proxyFactory.setTarget(bean);
91-
// Delegate all method calls to the wrapped, instrumented DataSource
92-
proxyFactory.addAdvice(
93-
new MethodInterceptor() {
94-
@Nullable
95-
@Override
96-
public Object invoke(@Nonnull MethodInvocation invocation) throws Throwable {
97-
return AopUtils.invokeJoinpointUsingReflection(
98-
wrapped, invocation.getMethod(), invocation.getArguments());
99-
}
100-
});
80+
/**
81+
* Spring Boot's configuration binding and rebinding mechanisms (such as those triggered by
82+
* Nacos configuration refresh) may attempt to reconstruct beans using their concrete class
83+
* constructors. If a custom DataSource implementation (such as OpenTelemetryDataSource) is
84+
* returned directly, Spring may not find a suitable constructor during rebinding, resulting
85+
* in errors like "ExistingValue must be an instance of com.zaxxer.hikari.HikariDataSource".
86+
*
87+
* <p>To prevent this, we create a JDK dynamic proxy implementing only the DataSource
88+
* interface. The proxy delegates all method calls to the wrapped (instrumented) DataSource.
89+
* This approach "hides" the actual implementation class and ensures that Spring interacts
90+
* only with the DataSource interface, avoiding issues related to constructor resolution or
91+
* type casting during bean rebinding.
92+
*/
93+
ProxyFactory proxyFactory = new ProxyFactory(DataSource.class);
94+
// Set the original bean as the target (important for AOP and bean lifecycle)
95+
proxyFactory.setTarget(bean);
96+
// Delegate all method calls to the wrapped, instrumented DataSource
97+
proxyFactory.addAdvice(
98+
new MethodInterceptor() {
99+
@Nullable
100+
@Override
101+
public Object invoke(@Nonnull MethodInvocation invocation) throws Throwable {
102+
return AopUtils.invokeJoinpointUsingReflection(
103+
wrapped, invocation.getMethod(), invocation.getArguments());
104+
}
105+
});
101106

102-
// Return the proxy instead of the instrumented DataSource instance
103-
// This ensures proper interaction with Spring's bean lifecycle and rebinding
104-
return proxyFactory.getProxy();
107+
// Return the proxy instead of the instrumented DataSource instance
108+
// This ensures proper interaction with Spring's bean lifecycle and rebinding
109+
return proxyFactory.getProxy();
110+
}
111+
return bean;
105112
}
106-
return bean;
107-
}
108113

109114
// To be one of the first bean post-processors to be executed
110115
@Override

instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessorContextTest.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
16
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc;
27

8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.mockito.Mockito.*;
10+
311
import io.opentelemetry.api.OpenTelemetry;
412
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
13+
import java.sql.Connection;
14+
import javax.sql.DataSource;
515
import org.junit.jupiter.api.Test;
616
import org.springframework.beans.factory.ObjectProvider;
7-
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
8-
9-
import javax.sql.DataSource;
10-
import java.sql.Connection;
11-
12-
import static org.assertj.core.api.Assertions.assertThat;
13-
import static org.mockito.Mockito.*;
1417

1518
class DataSourcePostProcessorTest {
1619

@@ -41,9 +44,8 @@ void shouldWrapDataSourceWithProxy() throws Exception {
4144
ObjectProvider<OpenTelemetry> openTelemetryProvider = () -> openTelemetry;
4245
ObjectProvider<ConfigProperties> configPropertiesProvider = () -> configProperties;
4346

44-
DataSourcePostProcessor postProcessor = new DataSourcePostProcessor(
45-
openTelemetryProvider, configPropertiesProvider
46-
);
47+
DataSourcePostProcessor postProcessor =
48+
new DataSourcePostProcessor(openTelemetryProvider, configPropertiesProvider);
4749

4850
// Act
4951
Object processed = postProcessor.postProcessAfterInitialization(original, "myDataSource");
@@ -63,4 +65,4 @@ void shouldWrapDataSourceWithProxy() throws Exception {
6365
verify(wrapped, times(1)).getConnection();
6466
}
6567
}
66-
}
68+
}

0 commit comments

Comments
 (0)