diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/async/TraceAsyncDefaultAutoConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/async/TraceAsyncDefaultAutoConfiguration.java
index 72feab40a..18fb2fbdf 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/async/TraceAsyncDefaultAutoConfiguration.java
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/async/TraceAsyncDefaultAutoConfiguration.java
@@ -1,153 +1,153 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.async;
-
-import java.util.concurrent.Executor;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.springframework.aop.interceptor.AsyncExecutionAspectSupport;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.NoSuchBeanDefinitionException;
-import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.sleuth.SpanNamer;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
-import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor;
-import org.springframework.cloud.sleuth.instrument.async.TraceAsyncAspect;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Role;
-import org.springframework.core.task.SimpleAsyncTaskExecutor;
-import org.springframework.core.task.TaskExecutor;
-import org.springframework.scheduling.annotation.AsyncConfigurer;
-import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
-
-/**
- * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
- * Auto-configuration} enabling async related processing.
- *
- * @author Dave Syer
- * @author Marcin Grzejszczak
- * @since 1.0.0
- * @see LazyTraceExecutor
- * @see TraceAsyncAspect
- */
-@Configuration(proxyBeanMethods = false)
-@EnableConfigurationProperties(SleuthAsyncProperties.class)
-@ConditionalOnProperty(value = "spring.sleuth.async.enabled", matchIfMissing = true)
-@ConditionalOnBean(Tracer.class)
-@AutoConfigureAfter(BraveAutoConfiguration.class)
-public class TraceAsyncDefaultAutoConfiguration {
-
- @Bean
- @ConditionalOnProperty(value = "spring.sleuth.scheduled.enabled", matchIfMissing = true)
- static ExecutorBeanPostProcessor executorBeanPostProcessor(BeanFactory beanFactory) {
- return new ExecutorBeanPostProcessor(beanFactory);
- }
-
- @Bean
- TraceAsyncAspect traceAsyncAspect(Tracer tracer, SpanNamer spanNamer) {
- return new TraceAsyncAspect(tracer, spanNamer);
- }
-
- /**
- * Wrapper for the async executor.
- */
- @Configuration(proxyBeanMethods = false)
- @ConditionalOnClass(AsyncConfigurer.class)
- @ConditionalOnMissingBean(AsyncConfigurer.class)
- @ConditionalOnProperty(value = "spring.sleuth.async.configurer.enabled", matchIfMissing = true)
- @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
- static class DefaultAsyncConfigurerSupport extends AsyncConfigurerSupport {
-
- private static final Log log = LogFactory.getLog(DefaultAsyncConfigurerSupport.class);
-
- @Autowired
- private BeanFactory beanFactory;
-
- @Override
- public Executor getAsyncExecutor() {
- Executor delegate = getDefaultExecutor();
- return new LazyTraceExecutor(this.beanFactory, delegate);
- }
-
- /**
- * Retrieve or build a default executor for this advice instance. An executor
- * returned from here will be cached for further use.
- *
- * The default implementation searches for a unique {@link TaskExecutor} bean in
- * the context, or for an {@link Executor} bean named "taskExecutor" otherwise. If
- * neither of the two is resolvable, this implementation will return {@code null}.
- * @return the default executor, or {@code null} if none available
- * @see AsyncExecutionAspectSupport#getDefaultExecutor(org.springframework.beans.factory.BeanFactory)
- */
- private Executor getDefaultExecutor() {
- try {
- // Search for TaskExecutor bean... not plain Executor since that would
- // match with ScheduledExecutorService as well, which is unusable for
- // our purposes here. TaskExecutor is more clearly designed for it.
- return this.beanFactory.getBean(TaskExecutor.class);
- }
- catch (NoUniqueBeanDefinitionException ex) {
- if (log.isDebugEnabled()) {
- log.debug("Could not find unique TaskExecutor bean", ex);
- }
- try {
- return this.beanFactory.getBean(AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME,
- Executor.class);
- }
- catch (NoSuchBeanDefinitionException ex2) {
- if (log.isInfoEnabled()) {
- log.info("More than one TaskExecutor bean found within the context, and none is named "
- + "'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly "
- + "as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
- }
- }
- }
- catch (NoSuchBeanDefinitionException ex) {
- log.debug("Could not find default TaskExecutor bean", ex);
- try {
- return this.beanFactory.getBean(AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME,
- Executor.class);
- }
- catch (NoSuchBeanDefinitionException ex2) {
- log.info("No task executor bean found for async processing: "
- + "no bean of type TaskExecutor and no bean named 'taskExecutor' either");
- }
- // Giving up -> either using local default executor or none at all...
- }
- // backward compatibility
- if (log.isInfoEnabled()) {
- log.info(
- "For backward compatibility, will fallback to the default, SimpleAsyncTaskExecutor implementation");
- }
- return new SimpleAsyncTaskExecutor();
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.async;
+
+import java.util.concurrent.Executor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.aop.interceptor.AsyncExecutionAspectSupport;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.sleuth.SpanNamer;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor;
+import org.springframework.cloud.sleuth.instrument.async.TraceAsyncAspect;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Role;
+import org.springframework.core.task.SimpleAsyncTaskExecutor;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
+
+/**
+ * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
+ * Auto-configuration} enabling async related processing.
+ *
+ * @author Dave Syer
+ * @author Marcin Grzejszczak
+ * @since 1.0.0
+ * @see LazyTraceExecutor
+ * @see TraceAsyncAspect
+ */
+@Configuration(proxyBeanMethods = false)
+@EnableConfigurationProperties(SleuthAsyncProperties.class)
+@ConditionalOnProperty(value = "spring.sleuth.async.enabled", matchIfMissing = true)
+@ConditionalOnBean(Tracer.class)
+@AutoConfigureAfter(BraveAutoConfiguration.class)
+public class TraceAsyncDefaultAutoConfiguration {
+
+ @Bean
+ @ConditionalOnProperty(value = "spring.sleuth.scheduled.enabled", matchIfMissing = true)
+ static ExecutorBeanPostProcessor executorBeanPostProcessor(BeanFactory beanFactory) {
+ return new ExecutorBeanPostProcessor(beanFactory);
+ }
+
+ @Bean
+ TraceAsyncAspect traceAsyncAspect(Tracer tracer, SpanNamer spanNamer) {
+ return new TraceAsyncAspect(tracer, spanNamer);
+ }
+
+ /**
+ * Wrapper for the async executor.
+ */
+ @Configuration(proxyBeanMethods = false)
+ @ConditionalOnClass(AsyncConfigurer.class)
+ @ConditionalOnMissingBean(AsyncConfigurer.class)
+ @ConditionalOnProperty(value = "spring.sleuth.async.configurer.enabled", matchIfMissing = true)
+ @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+ static class DefaultAsyncConfigurerSupport extends AsyncConfigurerSupport {
+
+ private static final Log log = LogFactory.getLog(DefaultAsyncConfigurerSupport.class);
+
+ @Autowired
+ private BeanFactory beanFactory;
+
+ @Override
+ public Executor getAsyncExecutor() {
+ Executor delegate = getDefaultExecutor();
+ return new LazyTraceExecutor(this.beanFactory, delegate);
+ }
+
+ /**
+ * Retrieve or build a default executor for this advice instance. An executor
+ * returned from here will be cached for further use.
+ *
+ * The default implementation searches for a unique {@link TaskExecutor} bean in
+ * the context, or for an {@link Executor} bean named "taskExecutor" otherwise. If
+ * neither of the two is resolvable, this implementation will return {@code null}.
+ * @return the default executor, or {@code null} if none available
+ * @see AsyncExecutionAspectSupport#getDefaultExecutor(org.springframework.beans.factory.BeanFactory)
+ */
+ private Executor getDefaultExecutor() {
+ try {
+ // Search for TaskExecutor bean... not plain Executor since that would
+ // match with ScheduledExecutorService as well, which is unusable for
+ // our purposes here. TaskExecutor is more clearly designed for it.
+ return this.beanFactory.getBean(TaskExecutor.class);
+ }
+ catch (NoUniqueBeanDefinitionException ex) {
+ if (log.isDebugEnabled()) {
+ log.debug("Could not find unique TaskExecutor bean", ex);
+ }
+ try {
+ return this.beanFactory.getBean(AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME,
+ Executor.class);
+ }
+ catch (NoSuchBeanDefinitionException ex2) {
+ if (log.isInfoEnabled()) {
+ log.info("More than one TaskExecutor bean found within the context, and none is named "
+ + "'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly "
+ + "as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
+ }
+ }
+ }
+ catch (NoSuchBeanDefinitionException ex) {
+ log.debug("Could not find default TaskExecutor bean", ex);
+ try {
+ return this.beanFactory.getBean(AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME,
+ Executor.class);
+ }
+ catch (NoSuchBeanDefinitionException ex2) {
+ log.info("No task executor bean found for async processing: "
+ + "no bean of type TaskExecutor and no bean named 'taskExecutor' either");
+ }
+ // Giving up -> either using local default executor or none at all...
+ }
+ // backward compatibility
+ if (log.isInfoEnabled()) {
+ log.info(
+ "For backward compatibility, will fallback to the default, SimpleAsyncTaskExecutor implementation");
+ }
+ return new SimpleAsyncTaskExecutor();
+ }
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceProxyConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceProxyConfiguration.java
index 944e74fa7..876efc38c 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceProxyConfiguration.java
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceProxyConfiguration.java
@@ -1,112 +1,111 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.ttddyy.dsproxy.listener.MethodExecutionListener;
-import net.ttddyy.dsproxy.listener.QueryCountStrategy;
-import net.ttddyy.dsproxy.listener.QueryExecutionListener;
-import net.ttddyy.dsproxy.proxy.GlobalConnectionIdManager;
-import net.ttddyy.dsproxy.proxy.ResultSetProxyLogicFactory;
-import net.ttddyy.dsproxy.proxy.SimpleResultSetProxyLogicFactory;
-import net.ttddyy.dsproxy.support.ProxyDataSource;
-import net.ttddyy.dsproxy.transform.ParameterTransformer;
-import net.ttddyy.dsproxy.transform.QueryTransformer;
-
-import org.springframework.beans.BeanUtils;
-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.ConditionalOnProperty;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyBuilderCustomizer;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyConnectionIdManagerProvider;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyDataSourceDecorator;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyProperties;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceListenerStrategySpanCustomizer;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceQueryExecutionListener;
-import org.springframework.context.annotation.Bean;
-
-/**
- * Configuration for integration with datasource-proxy, allows to use define custom
- * {@link QueryExecutionListener}, {@link ParameterTransformer} and
- * {@link QueryTransformer}.
- *
- * @author Arthur Gavlyukovskiy
- */
-@ConditionalOnClass(ProxyDataSource.class)
-@ConditionalOnProperty(name = "spring.sleuth.jdbc.datasource-proxy.enabled", havingValue = "true", matchIfMissing = true)
-class DataSourceProxyConfiguration {
-
- @Bean
- @ConditionalOnMissingBean
- DataSourceProxyConnectionIdManagerProvider traceConnectionIdManagerProvider() {
- return GlobalConnectionIdManager::new;
- }
-
- @Bean
- DataSourceProxyBuilderCustomizer proxyDataSourceBuilderConfigurer(
- ObjectProvider queryCountStrategy,
- ObjectProvider> listeners,
- ObjectProvider> methodExecutionListeners,
- ObjectProvider parameterTransformer,
- ObjectProvider queryTransformer,
- ObjectProvider resultSetProxyLogicFactory,
- ObjectProvider dataSourceProxyConnectionIdManagerProvider,
- TraceJdbcProperties traceJdbcProperties) {
- return new DataSourceProxyBuilderCustomizer(queryCountStrategy.getIfAvailable(() -> null),
- listeners.getIfAvailable(() -> null), methodExecutionListeners.getIfAvailable(() -> null),
- parameterTransformer.getIfAvailable(() -> null), queryTransformer.getIfAvailable(() -> null),
- resultSetProxyLogicFactory.getIfAvailable(() -> null),
- dataSourceProxyConnectionIdManagerProvider.getIfAvailable(() -> null),
- props(traceJdbcProperties));
- }
-
- private DataSourceProxyProperties props(TraceJdbcProperties traceJdbcProperties) {
- TraceJdbcProperties.DataSourceProxyProperties originalProxy = traceJdbcProperties
- .getDatasourceProxy();
- DataSourceProxyProperties props = new DataSourceProxyProperties();
- BeanUtils.copyProperties(originalProxy, props);
- props.setLogging(DataSourceProxyProperties.DataSourceProxyLogging.valueOf(originalProxy.getLogging().name()));
- return props;
- }
-
- @Bean
- DataSourceProxyDataSourceDecorator proxyDataSourceDecorator(
- DataSourceProxyBuilderCustomizer dataSourceProxyBuilderCustomizer,
- DataSourceNameResolver dataSourceNameResolver) {
- return new DataSourceProxyDataSourceDecorator(dataSourceProxyBuilderCustomizer, dataSourceNameResolver);
- }
-
- @Bean
- TraceQueryExecutionListener traceQueryExecutionListener(Tracer tracer,
- TraceJdbcProperties dataSourceDecoratorProperties,
- ObjectProvider> customizers) {
- return new TraceQueryExecutionListener(tracer, dataSourceDecoratorProperties.getIncludes(),
- customizers.getIfAvailable(ArrayList::new));
- }
-
- @Bean
- @ConditionalOnMissingBean
- ResultSetProxyLogicFactory traceResultSetProxyLogicFactory() {
- return new SimpleResultSetProxyLogicFactory();
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.ttddyy.dsproxy.listener.MethodExecutionListener;
+import net.ttddyy.dsproxy.listener.QueryCountStrategy;
+import net.ttddyy.dsproxy.listener.QueryExecutionListener;
+import net.ttddyy.dsproxy.proxy.GlobalConnectionIdManager;
+import net.ttddyy.dsproxy.proxy.ResultSetProxyLogicFactory;
+import net.ttddyy.dsproxy.proxy.SimpleResultSetProxyLogicFactory;
+import net.ttddyy.dsproxy.support.ProxyDataSource;
+import net.ttddyy.dsproxy.transform.ParameterTransformer;
+import net.ttddyy.dsproxy.transform.QueryTransformer;
+
+import org.springframework.beans.BeanUtils;
+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.ConditionalOnProperty;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyBuilderCustomizer;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyConnectionIdManagerProvider;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyDataSourceDecorator;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyProperties;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceListenerStrategySpanCustomizer;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceQueryExecutionListener;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * Configuration for integration with datasource-proxy, allows to use define custom
+ * {@link QueryExecutionListener}, {@link ParameterTransformer} and
+ * {@link QueryTransformer}.
+ *
+ * @author Arthur Gavlyukovskiy
+ */
+@ConditionalOnClass(ProxyDataSource.class)
+@ConditionalOnProperty(name = "spring.sleuth.jdbc.datasource-proxy.enabled", havingValue = "true",
+ matchIfMissing = true)
+class DataSourceProxyConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ DataSourceProxyConnectionIdManagerProvider traceConnectionIdManagerProvider() {
+ return GlobalConnectionIdManager::new;
+ }
+
+ @Bean
+ DataSourceProxyBuilderCustomizer proxyDataSourceBuilderConfigurer(
+ ObjectProvider queryCountStrategy,
+ ObjectProvider> listeners,
+ ObjectProvider> methodExecutionListeners,
+ ObjectProvider parameterTransformer,
+ ObjectProvider queryTransformer,
+ ObjectProvider resultSetProxyLogicFactory,
+ ObjectProvider dataSourceProxyConnectionIdManagerProvider,
+ TraceJdbcProperties traceJdbcProperties) {
+ return new DataSourceProxyBuilderCustomizer(queryCountStrategy.getIfAvailable(() -> null),
+ listeners.getIfAvailable(() -> null), methodExecutionListeners.getIfAvailable(() -> null),
+ parameterTransformer.getIfAvailable(() -> null), queryTransformer.getIfAvailable(() -> null),
+ resultSetProxyLogicFactory.getIfAvailable(() -> null),
+ dataSourceProxyConnectionIdManagerProvider.getIfAvailable(() -> null), props(traceJdbcProperties));
+ }
+
+ private DataSourceProxyProperties props(TraceJdbcProperties traceJdbcProperties) {
+ TraceJdbcProperties.DataSourceProxyProperties originalProxy = traceJdbcProperties.getDatasourceProxy();
+ DataSourceProxyProperties props = new DataSourceProxyProperties();
+ BeanUtils.copyProperties(originalProxy, props);
+ props.setLogging(DataSourceProxyProperties.DataSourceProxyLogging.valueOf(originalProxy.getLogging().name()));
+ return props;
+ }
+
+ @Bean
+ DataSourceProxyDataSourceDecorator proxyDataSourceDecorator(
+ DataSourceProxyBuilderCustomizer dataSourceProxyBuilderCustomizer,
+ DataSourceNameResolver dataSourceNameResolver) {
+ return new DataSourceProxyDataSourceDecorator(dataSourceProxyBuilderCustomizer, dataSourceNameResolver);
+ }
+
+ @Bean
+ TraceQueryExecutionListener traceQueryExecutionListener(Tracer tracer,
+ TraceJdbcProperties dataSourceDecoratorProperties,
+ ObjectProvider> customizers) {
+ return new TraceQueryExecutionListener(tracer, dataSourceDecoratorProperties.getIncludes(),
+ customizers.getIfAvailable(ArrayList::new));
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ ResultSetProxyLogicFactory traceResultSetProxyLogicFactory() {
+ return new SimpleResultSetProxyLogicFactory();
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfiguration.java
index b38bd2d85..68f05063e 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfiguration.java
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfiguration.java
@@ -1,78 +1,78 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.p6spy.engine.event.JdbcEventListener;
-import com.p6spy.engine.spy.DefaultJdbcEventListenerFactory;
-import com.p6spy.engine.spy.JdbcEventListenerFactory;
-import com.p6spy.engine.spy.P6DataSource;
-
-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.ConditionalOnProperty;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
-import org.springframework.cloud.sleuth.instrument.jdbc.P6SpyContextJdbcEventListenerFactory;
-import org.springframework.cloud.sleuth.instrument.jdbc.P6SpyDataSourceDecorator;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceJdbcEventListener;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceListenerStrategySpanCustomizer;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.context.annotation.Bean;
-
-/**
- * Configuration for integration with p6spy, allows to define custom
- * {@link JdbcEventListener}.
- *
- * @author Arthur Gavlyukovskiy
- */
-@ConditionalOnClass(P6DataSource.class)
-@ConditionalOnProperty(name = "spring.sleuth.jdbc.p6spy.enabled", havingValue = "true", matchIfMissing = true)
-class P6SpyConfiguration {
-
- @Bean
- static P6SpyPropertiesSetter p6SpyPropertiesSetter(ConfigurableApplicationContext context) {
- return new P6SpyPropertiesSetter(context);
- }
-
- @Bean
- @ConditionalOnMissingBean
- JdbcEventListenerFactory traceJdbcEventListenerFactory(ObjectProvider> listeners) {
- JdbcEventListenerFactory jdbcEventListenerFactory = new DefaultJdbcEventListenerFactory();
- List listenerList = listeners.getIfAvailable(() -> null);
- return listenerList != null ? new P6SpyContextJdbcEventListenerFactory(jdbcEventListenerFactory, listenerList)
- : jdbcEventListenerFactory;
- }
-
- @Bean
- P6SpyDataSourceDecorator p6SpyDataSourceDecorator(JdbcEventListenerFactory jdbcEventListenerFactory) {
- return new P6SpyDataSourceDecorator(jdbcEventListenerFactory);
- }
-
- @Bean
- TraceJdbcEventListener tracingJdbcEventListener(Tracer tracer, DataSourceNameResolver dataSourceNameResolver,
- TraceJdbcProperties traceJdbcProperties,
- ObjectProvider> customizers) {
- return new TraceJdbcEventListener(tracer, dataSourceNameResolver, traceJdbcProperties.getIncludes(),
- traceJdbcProperties.getP6spy().getTracing().isIncludeParameterValues(),
- customizers.getIfAvailable(ArrayList::new));
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.p6spy.engine.event.JdbcEventListener;
+import com.p6spy.engine.spy.DefaultJdbcEventListenerFactory;
+import com.p6spy.engine.spy.JdbcEventListenerFactory;
+import com.p6spy.engine.spy.P6DataSource;
+
+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.ConditionalOnProperty;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
+import org.springframework.cloud.sleuth.instrument.jdbc.P6SpyContextJdbcEventListenerFactory;
+import org.springframework.cloud.sleuth.instrument.jdbc.P6SpyDataSourceDecorator;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceJdbcEventListener;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceListenerStrategySpanCustomizer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * Configuration for integration with p6spy, allows to define custom
+ * {@link JdbcEventListener}.
+ *
+ * @author Arthur Gavlyukovskiy
+ */
+@ConditionalOnClass(P6DataSource.class)
+@ConditionalOnProperty(name = "spring.sleuth.jdbc.p6spy.enabled", havingValue = "true", matchIfMissing = true)
+class P6SpyConfiguration {
+
+ @Bean
+ static P6SpyPropertiesSetter p6SpyPropertiesSetter(ConfigurableApplicationContext context) {
+ return new P6SpyPropertiesSetter(context);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ JdbcEventListenerFactory traceJdbcEventListenerFactory(ObjectProvider> listeners) {
+ JdbcEventListenerFactory jdbcEventListenerFactory = new DefaultJdbcEventListenerFactory();
+ List listenerList = listeners.getIfAvailable(() -> null);
+ return listenerList != null ? new P6SpyContextJdbcEventListenerFactory(jdbcEventListenerFactory, listenerList)
+ : jdbcEventListenerFactory;
+ }
+
+ @Bean
+ P6SpyDataSourceDecorator p6SpyDataSourceDecorator(JdbcEventListenerFactory jdbcEventListenerFactory) {
+ return new P6SpyDataSourceDecorator(jdbcEventListenerFactory);
+ }
+
+ @Bean
+ TraceJdbcEventListener tracingJdbcEventListener(Tracer tracer, DataSourceNameResolver dataSourceNameResolver,
+ TraceJdbcProperties traceJdbcProperties,
+ ObjectProvider> customizers) {
+ return new TraceJdbcEventListener(tracer, dataSourceNameResolver, traceJdbcProperties.getIncludes(),
+ traceJdbcProperties.getP6spy().getTracing().isIncludeParameterValues(),
+ customizers.getIfAvailable(ArrayList::new));
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyPropertiesSetter.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyPropertiesSetter.java
index f12826584..b5633a019 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyPropertiesSetter.java
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyPropertiesSetter.java
@@ -1,187 +1,188 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import com.p6spy.engine.logging.P6LogFactory;
-import com.p6spy.engine.spy.P6ModuleManager;
-import com.p6spy.engine.spy.P6SpyFactory;
-import com.p6spy.engine.spy.option.EnvironmentVariables;
-import com.p6spy.engine.spy.option.P6OptionsSource;
-import com.p6spy.engine.spy.option.SpyDotProperties;
-import com.p6spy.engine.spy.option.SystemProperties;
-import org.slf4j.Logger;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.core.env.ConfigurableEnvironment;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Sets p6spy properties to / from system properties.
- *
- * @author Arthur Gavlyukovskiy
- * @since 3.1.0
- */
-class P6SpyPropertiesSetter implements BeanDefinitionRegistryPostProcessor, Closeable {
-
- private static final Logger log = getLogger(P6SpyPropertiesSetter.class);
-
- private final ConfigurableApplicationContext context;
-
- private final Map initialP6SpyOptions;
-
- P6SpyPropertiesSetter(ConfigurableApplicationContext context) {
- this.context = context;
- this.initialP6SpyOptions = findDefinedOptions();
- }
-
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- ConfigurableEnvironment environment = this.context.getEnvironment();
- String customModuleList = initialP6SpyOptions.get("modulelist");
- boolean isEnableLogging = environment.getProperty("spring.sleuth.jdbc.p6spy.enable-logging", Boolean.class,
- true);
- if (customModuleList != null) {
- log.info("P6Spy modulelist is overridden, some p6spy configuration features will not be applied");
- }
- else {
- List moduleList = new ArrayList<>();
- // default factory, holds P6Spy configuration
- moduleList.add(P6SpyFactory.class.getName());
- if (isEnableLogging) {
- moduleList.add(P6LogFactory.class.getName());
- }
- System.setProperty("p6spy.config.modulelist", String.join(",", moduleList));
- }
- if (!initialP6SpyOptions.containsKey("logMessageFormat")) {
- String logFormat = logFormat(environment);
- boolean isMultiline = multiLine(environment);
- if (logFormat != null) {
- System.setProperty("p6spy.config.logMessageFormat", "com.p6spy.engine.spy.appender.CustomLineFormat");
- System.setProperty("p6spy.config.customLogMessageFormat", logFormat);
- }
- else if (isMultiline) {
- System.setProperty("p6spy.config.logMessageFormat", "com.p6spy.engine.spy.appender.MultiLineFormat");
- }
- }
- if (isEnableLogging && !initialP6SpyOptions.containsKey("appender")) {
- TraceJdbcProperties.P6SpyProperties.P6SpyLogging logging = TraceJdbcProperties.P6SpyProperties.P6SpyLogging
- .valueOf(environment
- .getProperty("spring.sleuth.jdbc.p6spy.logging", String.class,
- TraceJdbcProperties.P6SpyProperties.P6SpyLogging.SLF4J.toString())
- .toUpperCase());
- switch (logging) {
- case SYSOUT:
- System.setProperty("p6spy.config.appender", "com.p6spy.engine.spy.appender.StdoutLogger");
- break;
- case SLF4J:
- System.setProperty("p6spy.config.appender", "com.p6spy.engine.spy.appender.Slf4JLogger");
- break;
- case FILE:
- System.setProperty("p6spy.config.appender", "com.p6spy.engine.spy.appender.FileLogger");
- break;
- case CUSTOM:
- String customAppender = environment.getProperty("spring.sleuth.jdbc.p6spy.custom-appender-class",
- String.class, "");
- System.setProperty("p6spy.config.appender", customAppender);
- break;
- }
- }
- if (!initialP6SpyOptions.containsKey("logfile")) {
- String logFile = environment.getProperty("spring.sleuth.jdbc.p6spy.log-file", String.class, "spy.log");
- System.setProperty("p6spy.config.logfile", logFile);
- }
- String pattern = environment.getProperty("spring.sleuth.jdbc.p6spy.log-filter.pattern", String.class);
- if (pattern != null) {
- System.setProperty("p6spy.config.filter", "true");
- System.setProperty("p6spy.config.sqlexpression", pattern);
- }
- // If factories were loaded before this method is initialized changing properties
- // will not be applied
- // Changes done in this method could not override anything user specified,
- // therefore it is safe to call reload
- P6ModuleManager.getInstance().reload();
- }
-
- private Boolean multiLine(ConfigurableEnvironment environment) {
- return environment.getProperty("spring.sleuth.jdbc.p6spy.multiline", Boolean.class, true);
- }
-
- private String logFormat(ConfigurableEnvironment environment) {
- return environment.getProperty("spring.sleuth.jdbc.p6spy.log-format", String.class);
- }
-
- @Override
- public void close() throws IOException {
- if (!initialP6SpyOptions.containsKey("modulelist")) {
- System.clearProperty("p6spy.config.modulelist");
- }
- if (!initialP6SpyOptions.containsKey("logMessageFormat")) {
- ConfigurableEnvironment environment = this.context.getEnvironment();
- String logFormat = logFormat(environment);
- boolean isMultiline = multiLine(environment);
- if (logFormat != null) {
- System.clearProperty("p6spy.config.logMessageFormat");
- System.clearProperty("p6spy.config.customLogMessageFormat");
- }
- else if (isMultiline) {
- System.clearProperty("p6spy.config.logMessageFormat");
- }
- }
- if (!initialP6SpyOptions.containsKey("appender")) {
- System.clearProperty("p6spy.config.appender");
- }
- if (!initialP6SpyOptions.containsKey("logfile")) {
- System.clearProperty("p6spy.config.logfile");
- }
- P6ModuleManager.getInstance().reload();
- }
-
- private Map findDefinedOptions() {
- SpyDotProperties spyDotProperties = null;
- try {
- spyDotProperties = new SpyDotProperties();
- }
- catch (IOException ignored) {
- }
- return Stream.of(spyDotProperties, new EnvironmentVariables(), new SystemProperties()).filter(Objects::nonNull)
- .map(P6OptionsSource::getOptions).filter(Objects::nonNull)
- .flatMap(options -> options.entrySet().stream())
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
- // always using value from the first P6OptionsSource
- (value1, value2) -> value1));
- }
-
- @Override
- public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.p6spy.engine.logging.P6LogFactory;
+import com.p6spy.engine.spy.P6ModuleManager;
+import com.p6spy.engine.spy.P6SpyFactory;
+import com.p6spy.engine.spy.option.EnvironmentVariables;
+import com.p6spy.engine.spy.option.P6OptionsSource;
+import com.p6spy.engine.spy.option.SpyDotProperties;
+import com.p6spy.engine.spy.option.SystemProperties;
+import org.slf4j.Logger;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Sets p6spy properties to / from system properties.
+ *
+ * @author Arthur Gavlyukovskiy
+ * @since 3.1.0
+ */
+class P6SpyPropertiesSetter implements BeanDefinitionRegistryPostProcessor, Closeable {
+
+ private static final Logger log = getLogger(P6SpyPropertiesSetter.class);
+
+ private final ConfigurableApplicationContext context;
+
+ private final Map initialP6SpyOptions;
+
+ P6SpyPropertiesSetter(ConfigurableApplicationContext context) {
+ this.context = context;
+ this.initialP6SpyOptions = findDefinedOptions();
+ }
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ ConfigurableEnvironment environment = this.context.getEnvironment();
+ String customModuleList = initialP6SpyOptions.get("modulelist");
+ boolean isEnableLogging = environment.getProperty("spring.sleuth.jdbc.p6spy.enable-logging", Boolean.class,
+ true);
+ if (customModuleList != null) {
+ log.info("P6Spy modulelist is overridden, some p6spy configuration features will not be applied");
+ }
+ else {
+ List moduleList = new ArrayList<>();
+ // default factory, holds P6Spy configuration
+ moduleList.add(P6SpyFactory.class.getName());
+ if (isEnableLogging) {
+ moduleList.add(P6LogFactory.class.getName());
+ }
+ System.setProperty("p6spy.config.modulelist", String.join(",", moduleList));
+ }
+ if (!initialP6SpyOptions.containsKey("logMessageFormat")) {
+ String logFormat = logFormat(environment);
+ boolean isMultiline = multiLine(environment);
+ if (logFormat != null) {
+ System.setProperty("p6spy.config.logMessageFormat", "com.p6spy.engine.spy.appender.CustomLineFormat");
+ System.setProperty("p6spy.config.customLogMessageFormat", logFormat);
+ }
+ else if (isMultiline) {
+ System.setProperty("p6spy.config.logMessageFormat", "com.p6spy.engine.spy.appender.MultiLineFormat");
+ }
+ }
+ if (isEnableLogging && !initialP6SpyOptions.containsKey("appender")) {
+ TraceJdbcProperties.P6SpyProperties.P6SpyLogging logging = TraceJdbcProperties.P6SpyProperties.P6SpyLogging
+ .valueOf(
+ environment
+ .getProperty("spring.sleuth.jdbc.p6spy.logging", String.class,
+ TraceJdbcProperties.P6SpyProperties.P6SpyLogging.SLF4J.toString())
+ .toUpperCase());
+ switch (logging) {
+ case SYSOUT:
+ System.setProperty("p6spy.config.appender", "com.p6spy.engine.spy.appender.StdoutLogger");
+ break;
+ case SLF4J:
+ System.setProperty("p6spy.config.appender", "com.p6spy.engine.spy.appender.Slf4JLogger");
+ break;
+ case FILE:
+ System.setProperty("p6spy.config.appender", "com.p6spy.engine.spy.appender.FileLogger");
+ break;
+ case CUSTOM:
+ String customAppender = environment.getProperty("spring.sleuth.jdbc.p6spy.custom-appender-class",
+ String.class, "");
+ System.setProperty("p6spy.config.appender", customAppender);
+ break;
+ }
+ }
+ if (!initialP6SpyOptions.containsKey("logfile")) {
+ String logFile = environment.getProperty("spring.sleuth.jdbc.p6spy.log-file", String.class, "spy.log");
+ System.setProperty("p6spy.config.logfile", logFile);
+ }
+ String pattern = environment.getProperty("spring.sleuth.jdbc.p6spy.log-filter.pattern", String.class);
+ if (pattern != null) {
+ System.setProperty("p6spy.config.filter", "true");
+ System.setProperty("p6spy.config.sqlexpression", pattern);
+ }
+ // If factories were loaded before this method is initialized changing properties
+ // will not be applied
+ // Changes done in this method could not override anything user specified,
+ // therefore it is safe to call reload
+ P6ModuleManager.getInstance().reload();
+ }
+
+ private Boolean multiLine(ConfigurableEnvironment environment) {
+ return environment.getProperty("spring.sleuth.jdbc.p6spy.multiline", Boolean.class, true);
+ }
+
+ private String logFormat(ConfigurableEnvironment environment) {
+ return environment.getProperty("spring.sleuth.jdbc.p6spy.log-format", String.class);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (!initialP6SpyOptions.containsKey("modulelist")) {
+ System.clearProperty("p6spy.config.modulelist");
+ }
+ if (!initialP6SpyOptions.containsKey("logMessageFormat")) {
+ ConfigurableEnvironment environment = this.context.getEnvironment();
+ String logFormat = logFormat(environment);
+ boolean isMultiline = multiLine(environment);
+ if (logFormat != null) {
+ System.clearProperty("p6spy.config.logMessageFormat");
+ System.clearProperty("p6spy.config.customLogMessageFormat");
+ }
+ else if (isMultiline) {
+ System.clearProperty("p6spy.config.logMessageFormat");
+ }
+ }
+ if (!initialP6SpyOptions.containsKey("appender")) {
+ System.clearProperty("p6spy.config.appender");
+ }
+ if (!initialP6SpyOptions.containsKey("logfile")) {
+ System.clearProperty("p6spy.config.logfile");
+ }
+ P6ModuleManager.getInstance().reload();
+ }
+
+ private Map findDefinedOptions() {
+ SpyDotProperties spyDotProperties = null;
+ try {
+ spyDotProperties = new SpyDotProperties();
+ }
+ catch (IOException ignored) {
+ }
+ return Stream.of(spyDotProperties, new EnvironmentVariables(), new SystemProperties()).filter(Objects::nonNull)
+ .map(P6OptionsSource::getOptions).filter(Objects::nonNull)
+ .flatMap(options -> options.entrySet().stream())
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
+ // always using value from the first P6OptionsSource
+ (value1, value2) -> value1));
+ }
+
+ @Override
+ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceDataSourceDecoratorBeanPostProcessor.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceDataSourceDecoratorBeanPostProcessor.java
index 3c1a78142..1788fddeb 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceDataSourceDecoratorBeanPostProcessor.java
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceDataSourceDecoratorBeanPostProcessor.java
@@ -1,140 +1,140 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import javax.sql.DataSource;
-
-import com.zaxxer.hikari.HikariDataSource;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.springframework.aop.scope.ScopedProxyUtils;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceDecorator;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.core.Ordered;
-import org.springframework.core.annotation.AnnotationAwareOrderComparator;
-import org.springframework.util.ClassUtils;
-
-/**
- * {@link BeanPostProcessor} that wraps all data source beans in {@link DataSource}
- * proxies specified in property 'spring.datasource.type'.
- *
- * @author Arthur Gavlyukovskiy
- * @since 3.1.0
- */
-public class TraceDataSourceDecoratorBeanPostProcessor implements BeanPostProcessor, Ordered, ApplicationContextAware {
-
- private static final Log log = LogFactory.getLog(TraceDataSourceDecoratorBeanPostProcessor.class);
-
- private final static boolean HIKARI_AVAILABLE = ClassUtils.isPresent("com.zaxxer.hikari.HikariDataSource",
- DataSourceNameResolver.class.getClassLoader());
-
- private ApplicationContext applicationContext;
-
- private DataSourceNameResolver dataSourceNameResolver;
-
- private final Collection excludedBeans;
-
- public TraceDataSourceDecoratorBeanPostProcessor(Collection excludedBeans) {
- this.excludedBeans = excludedBeans;
- }
-
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
-
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- if (bean instanceof DataSource && !ScopedProxyUtils.isScopedTarget(beanName)
- && !this.excludedBeans.contains(beanName)) {
- // TODO: This might be a problem - it can lead to eager bean init
- Map decorators = this.applicationContext
- .getBeansOfType(DataSourceDecorator.class).entrySet().stream()
- .sorted(Entry.comparingByValue(AnnotationAwareOrderComparator.INSTANCE))
- .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (v1, v2) -> v2, LinkedHashMap::new));
- return decorate((DataSource) bean, getDataSourceName(bean, beanName), decorators);
- }
- else {
- return bean;
- }
- }
-
- private String getDataSourceName(Object bean, String beanName) {
- if (HIKARI_AVAILABLE && bean instanceof HikariDataSource) {
- HikariDataSource hikariDataSource = (HikariDataSource) bean;
- if (hikariDataSource.getPoolName() != null && !hikariDataSource.getPoolName().startsWith("HikariPool-")) {
- return hikariDataSource.getPoolName();
- }
- }
- return beanName;
- }
-
- private DataSource decorate(DataSource dataSource, String name, Map decorators) {
- getDataSourceNameResolver().addDataSource(name, dataSource);
- DataSource decoratedDataSource = dataSource;
- for (Entry decoratorEntry : decorators.entrySet()) {
- String decoratorBeanName = decoratorEntry.getKey();
- DataSourceDecorator decorator = decoratorEntry.getValue();
- DataSource dataSourceBeforeDecorating = decoratedDataSource;
- decoratedDataSource = Objects.requireNonNull(decorator.decorate(name, decoratedDataSource),
- "DataSourceDecorator (" + decoratorBeanName + ", " + decorator + ") should not return null");
- if (dataSourceBeforeDecorating != decoratedDataSource) {
- getDataSourceNameResolver().addDataSource(name, decoratedDataSource);
- }
- }
- if (dataSource != decoratedDataSource) {
- if (log.isDebugEnabled()) {
- log.debug("The decorated data source [" + decoratedDataSource + "] will replace the original one ["
- + dataSource + "]");
- }
- decoratedDataSource = new DataSourceWrapper(dataSource, decoratedDataSource);
- getDataSourceNameResolver().addDataSource(name, decoratedDataSource);
- }
- return decoratedDataSource;
- }
-
- private DataSourceNameResolver getDataSourceNameResolver() {
- if (this.dataSourceNameResolver == null) {
- this.dataSourceNameResolver = this.applicationContext.getBean(DataSourceNameResolver.class);
- }
- return this.dataSourceNameResolver;
- }
-
- @Override
- public int getOrder() {
- return Ordered.LOWEST_PRECEDENCE - 10;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import javax.sql.DataSource;
+
+import com.zaxxer.hikari.HikariDataSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.aop.scope.ScopedProxyUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceDecorator;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.AnnotationAwareOrderComparator;
+import org.springframework.util.ClassUtils;
+
+/**
+ * {@link BeanPostProcessor} that wraps all data source beans in {@link DataSource}
+ * proxies specified in property 'spring.datasource.type'.
+ *
+ * @author Arthur Gavlyukovskiy
+ * @since 3.1.0
+ */
+public class TraceDataSourceDecoratorBeanPostProcessor implements BeanPostProcessor, Ordered, ApplicationContextAware {
+
+ private static final Log log = LogFactory.getLog(TraceDataSourceDecoratorBeanPostProcessor.class);
+
+ private final static boolean HIKARI_AVAILABLE = ClassUtils.isPresent("com.zaxxer.hikari.HikariDataSource",
+ DataSourceNameResolver.class.getClassLoader());
+
+ private ApplicationContext applicationContext;
+
+ private DataSourceNameResolver dataSourceNameResolver;
+
+ private final Collection excludedBeans;
+
+ public TraceDataSourceDecoratorBeanPostProcessor(Collection excludedBeans) {
+ this.excludedBeans = excludedBeans;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof DataSource && !ScopedProxyUtils.isScopedTarget(beanName)
+ && !this.excludedBeans.contains(beanName)) {
+ // TODO: This might be a problem - it can lead to eager bean init
+ Map decorators = this.applicationContext
+ .getBeansOfType(DataSourceDecorator.class).entrySet().stream()
+ .sorted(Entry.comparingByValue(AnnotationAwareOrderComparator.INSTANCE))
+ .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (v1, v2) -> v2, LinkedHashMap::new));
+ return decorate((DataSource) bean, getDataSourceName(bean, beanName), decorators);
+ }
+ else {
+ return bean;
+ }
+ }
+
+ private String getDataSourceName(Object bean, String beanName) {
+ if (HIKARI_AVAILABLE && bean instanceof HikariDataSource) {
+ HikariDataSource hikariDataSource = (HikariDataSource) bean;
+ if (hikariDataSource.getPoolName() != null && !hikariDataSource.getPoolName().startsWith("HikariPool-")) {
+ return hikariDataSource.getPoolName();
+ }
+ }
+ return beanName;
+ }
+
+ private DataSource decorate(DataSource dataSource, String name, Map decorators) {
+ getDataSourceNameResolver().addDataSource(name, dataSource);
+ DataSource decoratedDataSource = dataSource;
+ for (Entry decoratorEntry : decorators.entrySet()) {
+ String decoratorBeanName = decoratorEntry.getKey();
+ DataSourceDecorator decorator = decoratorEntry.getValue();
+ DataSource dataSourceBeforeDecorating = decoratedDataSource;
+ decoratedDataSource = Objects.requireNonNull(decorator.decorate(name, decoratedDataSource),
+ "DataSourceDecorator (" + decoratorBeanName + ", " + decorator + ") should not return null");
+ if (dataSourceBeforeDecorating != decoratedDataSource) {
+ getDataSourceNameResolver().addDataSource(name, decoratedDataSource);
+ }
+ }
+ if (dataSource != decoratedDataSource) {
+ if (log.isDebugEnabled()) {
+ log.debug("The decorated data source [" + decoratedDataSource + "] will replace the original one ["
+ + dataSource + "]");
+ }
+ decoratedDataSource = new DataSourceWrapper(dataSource, decoratedDataSource);
+ getDataSourceNameResolver().addDataSource(name, decoratedDataSource);
+ }
+ return decoratedDataSource;
+ }
+
+ private DataSourceNameResolver getDataSourceNameResolver() {
+ if (this.dataSourceNameResolver == null) {
+ this.dataSourceNameResolver = this.applicationContext.getBean(DataSourceNameResolver.class);
+ }
+ return this.dataSourceNameResolver;
+ }
+
+ @Override
+ public int getOrder() {
+ return Ordered.LOWEST_PRECEDENCE - 10;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcAutoConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcAutoConfiguration.java
index c8c385ba9..80233866e 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcAutoConfiguration.java
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcAutoConfiguration.java
@@ -1,70 +1,71 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import javax.sql.DataSource;
-
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceDecorator;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceHikariListenerStrategySpanCustomizer;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceListenerStrategySpanCustomizer;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
-/**
- * {@link EnableAutoConfiguration Auto-configuration} for proxying DataSource.
- *
- * @author Arthur Gavlyukovskiy
- */
-@Configuration(proxyBeanMethods = false)
-@EnableConfigurationProperties(TraceJdbcProperties.class)
-@ConditionalOnProperty(name = "spring.sleuth.jdbc.enabled", havingValue = "true", matchIfMissing = true)
-@ConditionalOnBean({ DataSource.class, Tracer.class })
-@AutoConfigureAfter(DataSourceAutoConfiguration.class)
-@Import({ P6SpyConfiguration.class, DataSourceProxyConfiguration.class })
-public class TraceJdbcAutoConfiguration {
-
- @Bean
- @ConditionalOnBean(DataSourceDecorator.class)
- static TraceDataSourceDecoratorBeanPostProcessor traceDataSourceDecoratorBeanPostProcessor(
- TraceJdbcProperties dataSourceDecoratorProperties) {
- return new TraceDataSourceDecoratorBeanPostProcessor(dataSourceDecoratorProperties.getExcludedDataSourceBeanNames());
- }
-
- @Bean
- @ConditionalOnMissingBean
- DataSourceNameResolver traceDataSourceNameResolver() {
- return new DataSourceNameResolver();
- }
-
- @Bean
- @ConditionalOnClass(name = "com.zaxxer.hikari.HikariDataSource")
- TraceListenerStrategySpanCustomizer hikariTraceListenerStrategySpanCustomizer() {
- return new TraceHikariListenerStrategySpanCustomizer();
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import javax.sql.DataSource;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceDecorator;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceNameResolver;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceHikariListenerStrategySpanCustomizer;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceListenerStrategySpanCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for proxying DataSource.
+ *
+ * @author Arthur Gavlyukovskiy
+ */
+@Configuration(proxyBeanMethods = false)
+@EnableConfigurationProperties(TraceJdbcProperties.class)
+@ConditionalOnProperty(name = "spring.sleuth.jdbc.enabled", havingValue = "true", matchIfMissing = true)
+@ConditionalOnBean({ DataSource.class, Tracer.class })
+@AutoConfigureAfter(DataSourceAutoConfiguration.class)
+@Import({ P6SpyConfiguration.class, DataSourceProxyConfiguration.class })
+public class TraceJdbcAutoConfiguration {
+
+ @Bean
+ @ConditionalOnBean(DataSourceDecorator.class)
+ static TraceDataSourceDecoratorBeanPostProcessor traceDataSourceDecoratorBeanPostProcessor(
+ TraceJdbcProperties dataSourceDecoratorProperties) {
+ return new TraceDataSourceDecoratorBeanPostProcessor(
+ dataSourceDecoratorProperties.getExcludedDataSourceBeanNames());
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ DataSourceNameResolver traceDataSourceNameResolver() {
+ return new DataSourceNameResolver();
+ }
+
+ @Bean
+ @ConditionalOnClass(name = "com.zaxxer.hikari.HikariDataSource")
+ TraceListenerStrategySpanCustomizer hikariTraceListenerStrategySpanCustomizer() {
+ return new TraceHikariListenerStrategySpanCustomizer();
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcProperties.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcProperties.java
index bd16574da..a0ffa1f4e 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcProperties.java
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/TraceJdbcProperties.java
@@ -1,511 +1,511 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceType;
-
-/**
- * Properties for JDBC instrumentation.
- *
- * @author Arthur Gavlyukovskiy
- * @since 3.1.0
- */
-@ConfigurationProperties(prefix = "spring.sleuth.jdbc")
-public class TraceJdbcProperties {
-
- /**
- * Enables JDBC instrumentation.
- */
- private boolean enabled = true;
-
- /**
- * List of DataSource bean names that will not be decorated.
- */
- private Collection excludedDataSourceBeanNames = Collections.emptyList();
-
- /**
- * Which types of tracing we would like to include.
- */
- private List includes = Arrays.asList(TraceType.CONNECTION, TraceType.QUERY, TraceType.FETCH);
-
- private DataSourceProxyProperties datasourceProxy = new DataSourceProxyProperties();
-
- private P6SpyProperties p6spy = new P6SpyProperties();
-
- public boolean isEnabled() {
- return this.enabled;
- }
-
- public Collection getExcludedDataSourceBeanNames() {
- return this.excludedDataSourceBeanNames;
- }
-
- public List getIncludes() {
- return this.includes;
- }
-
- public void setIncludes(List includes) {
- this.includes = includes;
- }
-
- public DataSourceProxyProperties getDatasourceProxy() {
- return datasourceProxy;
- }
-
- public P6SpyProperties getP6spy() {
- return this.p6spy;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public void setExcludedDataSourceBeanNames(Collection excludedDataSourceBeanNames) {
- this.excludedDataSourceBeanNames = excludedDataSourceBeanNames;
- }
-
- public void setDatasourceProxy(DataSourceProxyProperties datasourceProxy) {
- this.datasourceProxy = datasourceProxy;
- }
-
- public void setP6spy(P6SpyProperties p6spy) {
- this.p6spy = p6spy;
- }
-
- /**
- * Properties for datasource-proxy.
- */
- public static class DataSourceProxyProperties {
-
- /**
- * Should the datasource-proxy tracing be enabled?
- */
- private boolean enabled = true;
-
- /**
- * Logging to use for logging queries.
- */
- private DataSourceProxyLogging logging = DataSourceProxyLogging.SLF4J;
-
- /**
- * Query configuration.
- */
- private Query query = new Query();
-
- /**
- * Slow query configuration.
- */
- private SlowQuery slowQuery = new SlowQuery();
-
- /**
- * Use multiline output for logging query.
- *
- * @see ProxyDataSourceBuilder#multiline()
- */
- private boolean multiline = true;
-
- /**
- * Use json output for logging query.
- *
- * @see ProxyDataSourceBuilder#asJson()
- */
- private boolean jsonFormat = false;
-
- public boolean isEnabled() {
- return this.enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public DataSourceProxyLogging getLogging() {
- return this.logging;
- }
-
- public void setLogging(DataSourceProxyLogging logging) {
- this.logging = logging;
- }
-
- public Query getQuery() {
- return this.query;
- }
-
- public void setQuery(Query query) {
- this.query = query;
- }
-
- public SlowQuery getSlowQuery() {
- return this.slowQuery;
- }
-
- public void setSlowQuery(SlowQuery slowQuery) {
- this.slowQuery = slowQuery;
- }
-
- public boolean isMultiline() {
- return this.multiline;
- }
-
- public void setMultiline(boolean multiline) {
- this.multiline = multiline;
- }
-
- public boolean isJsonFormat() {
- return this.jsonFormat;
- }
-
- public void setJsonFormat(boolean jsonFormat) {
- this.jsonFormat = jsonFormat;
- }
-
- /**
- * Properties to configure query logging listener.
- */
- public static class Query {
-
- /**
- * Enable logging all queries to the log.
- */
- private boolean enableLogging = true;
-
- /**
- * Name of query logger.
- */
- private String loggerName;
-
- /**
- * Severity of query logger.
- */
- private String logLevel = "DEBUG";
-
- public boolean isEnableLogging() {
- return this.enableLogging;
- }
-
- public void setEnableLogging(boolean enableLogging) {
- this.enableLogging = enableLogging;
- }
-
- public String getLoggerName() {
- return this.loggerName;
- }
-
- public void setLoggerName(String loggerName) {
- this.loggerName = loggerName;
- }
-
- public String getLogLevel() {
- return this.logLevel;
- }
-
- public void setLogLevel(String logLevel) {
- this.logLevel = logLevel;
- }
-
- }
-
- /**
- * Properties to configure slow query logging listener.
- */
- public static class SlowQuery {
-
- /**
- * Enable logging slow queries to the log.
- */
- private boolean enableLogging = true;
-
- /**
- * Name of slow query logger.
- */
- private String loggerName;
-
- /**
- * Severity of slow query logger.
- */
- private String logLevel = "WARN";
-
- /**
- * Number of seconds to consider query as slow.
- */
- private long threshold = 300;
-
- boolean isEnableLogging() {
- return enableLogging;
- }
-
- public void setEnableLogging(boolean enableLogging) {
- this.enableLogging = enableLogging;
- }
-
- public String getLoggerName() {
- return loggerName;
- }
-
- public void setLoggerName(String loggerName) {
- this.loggerName = loggerName;
- }
-
- public String getLogLevel() {
- return logLevel;
- }
-
- public void setLogLevel(String logLevel) {
- this.logLevel = logLevel;
- }
-
- public long getThreshold() {
- return threshold;
- }
-
- public void setThreshold(long threshold) {
- this.threshold = threshold;
- }
-
- }
-
- /**
- * Query logging listener is the most used listener that logs executing query with
- * actual parameters to. You can pick one of the following proxy logging
- * mechanisms.
- */
- public enum DataSourceProxyLogging {
-
- /**
- * Log using System.out.
- */
- SYSOUT,
-
- /**
- * Log using SLF4J.
- */
- SLF4J,
-
- /**
- * Log using Commons.
- */
- COMMONS,
-
- /**
- * Log using Java Util Logging.
- */
- JUL
-
- }
-
- }
-
- /**
- * Properties for configuring p6spy.
- */
- public static class P6SpyProperties {
-
- /**
- * Should the p6spy tracing be enabled?
- */
- private boolean enabled = true;
-
- /**
- * Enables logging JDBC events.
- */
- private boolean enableLogging = true;
-
- /**
- * Enables multiline output.
- */
- private boolean multiline = true;
-
- /**
- * Logging to use for logging queries.
- */
- private P6SpyLogging logging = P6SpyLogging.SLF4J;
-
- /**
- * Name of log file to use (only with logging=file).
- */
- private String logFile = "spy.log";
-
- /**
- * Custom log format.
- */
- private String logFormat;
-
- /**
- * Tracing related properties.
- */
- private P6SpyTracing tracing = new P6SpyTracing();
-
- /**
- * Class file to use (only with logging=custom). The class must implement
- * {@link com.p6spy.engine.spy.appender.FormattedLogger}.
- */
- private String customAppenderClass;
-
- /**
- * Log filtering related properties.
- */
- private P6SpyLogFilter logFilter = new P6SpyLogFilter();
-
- public boolean isEnabled() {
- return this.enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public boolean isEnableLogging() {
- return this.enableLogging;
- }
-
- public void setEnableLogging(boolean enableLogging) {
- this.enableLogging = enableLogging;
- }
-
- public boolean isMultiline() {
- return this.multiline;
- }
-
- public void setMultiline(boolean multiline) {
- this.multiline = multiline;
- }
-
- public P6SpyLogging getLogging() {
- return this.logging;
- }
-
- public void setLogging(P6SpyLogging logging) {
- this.logging = logging;
- }
-
- public String getLogFile() {
- return this.logFile;
- }
-
- public void setLogFile(String logFile) {
- this.logFile = logFile;
- }
-
- public String getLogFormat() {
- return this.logFormat;
- }
-
- public void setLogFormat(String logFormat) {
- this.logFormat = logFormat;
- }
-
- public P6SpyTracing getTracing() {
- return this.tracing;
- }
-
- public void setTracing(P6SpyTracing tracing) {
- this.tracing = tracing;
- }
-
- public String getCustomAppenderClass() {
- return this.customAppenderClass;
- }
-
- public void setCustomAppenderClass(String customAppenderClass) {
- this.customAppenderClass = customAppenderClass;
- }
-
- public P6SpyLogFilter getLogFilter() {
- return this.logFilter;
- }
-
- public void setLogFilter(P6SpyLogFilter logFilter) {
- this.logFilter = logFilter;
- }
-
- /**
- * P6Spy logging options.
- */
- public enum P6SpyLogging {
-
- /**
- * Log using System.out.
- */
- SYSOUT,
-
- /**
- * Log using SLF4J.
- */
- SLF4J,
-
- /**
- * Log to file.
- */
- FILE,
-
- /**
- * Custom logging.
- */
- CUSTOM
-
- }
-
- public static class P6SpyTracing {
-
- /**
- * Report the effective sql string (with '?' replaced with real values) to
- * tracing systems.
- *
- * NOTE this setting does not affect the logging message.
- */
- private boolean includeParameterValues = true;
-
- public boolean isIncludeParameterValues() {
- return this.includeParameterValues;
- }
-
- public void setIncludeParameterValues(boolean includeParameterValues) {
- this.includeParameterValues = includeParameterValues;
- }
-
- }
-
- public static class P6SpyLogFilter {
-
- /**
- * Use regex pattern to filter log messages. Only matched messages will be
- * logged.
- */
- private Pattern pattern;
-
- public Pattern getPattern() {
- return this.pattern;
- }
-
- public void setPattern(Pattern pattern) {
- this.pattern = pattern;
- }
-
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceType;
+
+/**
+ * Properties for JDBC instrumentation.
+ *
+ * @author Arthur Gavlyukovskiy
+ * @since 3.1.0
+ */
+@ConfigurationProperties(prefix = "spring.sleuth.jdbc")
+public class TraceJdbcProperties {
+
+ /**
+ * Enables JDBC instrumentation.
+ */
+ private boolean enabled = true;
+
+ /**
+ * List of DataSource bean names that will not be decorated.
+ */
+ private Collection excludedDataSourceBeanNames = Collections.emptyList();
+
+ /**
+ * Which types of tracing we would like to include.
+ */
+ private List includes = Arrays.asList(TraceType.CONNECTION, TraceType.QUERY, TraceType.FETCH);
+
+ private DataSourceProxyProperties datasourceProxy = new DataSourceProxyProperties();
+
+ private P6SpyProperties p6spy = new P6SpyProperties();
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public Collection getExcludedDataSourceBeanNames() {
+ return this.excludedDataSourceBeanNames;
+ }
+
+ public List getIncludes() {
+ return this.includes;
+ }
+
+ public void setIncludes(List includes) {
+ this.includes = includes;
+ }
+
+ public DataSourceProxyProperties getDatasourceProxy() {
+ return datasourceProxy;
+ }
+
+ public P6SpyProperties getP6spy() {
+ return this.p6spy;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public void setExcludedDataSourceBeanNames(Collection excludedDataSourceBeanNames) {
+ this.excludedDataSourceBeanNames = excludedDataSourceBeanNames;
+ }
+
+ public void setDatasourceProxy(DataSourceProxyProperties datasourceProxy) {
+ this.datasourceProxy = datasourceProxy;
+ }
+
+ public void setP6spy(P6SpyProperties p6spy) {
+ this.p6spy = p6spy;
+ }
+
+ /**
+ * Properties for datasource-proxy.
+ */
+ public static class DataSourceProxyProperties {
+
+ /**
+ * Should the datasource-proxy tracing be enabled?
+ */
+ private boolean enabled = true;
+
+ /**
+ * Logging to use for logging queries.
+ */
+ private DataSourceProxyLogging logging = DataSourceProxyLogging.SLF4J;
+
+ /**
+ * Query configuration.
+ */
+ private Query query = new Query();
+
+ /**
+ * Slow query configuration.
+ */
+ private SlowQuery slowQuery = new SlowQuery();
+
+ /**
+ * Use multiline output for logging query.
+ *
+ * @see ProxyDataSourceBuilder#multiline()
+ */
+ private boolean multiline = true;
+
+ /**
+ * Use json output for logging query.
+ *
+ * @see ProxyDataSourceBuilder#asJson()
+ */
+ private boolean jsonFormat = false;
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public DataSourceProxyLogging getLogging() {
+ return this.logging;
+ }
+
+ public void setLogging(DataSourceProxyLogging logging) {
+ this.logging = logging;
+ }
+
+ public Query getQuery() {
+ return this.query;
+ }
+
+ public void setQuery(Query query) {
+ this.query = query;
+ }
+
+ public SlowQuery getSlowQuery() {
+ return this.slowQuery;
+ }
+
+ public void setSlowQuery(SlowQuery slowQuery) {
+ this.slowQuery = slowQuery;
+ }
+
+ public boolean isMultiline() {
+ return this.multiline;
+ }
+
+ public void setMultiline(boolean multiline) {
+ this.multiline = multiline;
+ }
+
+ public boolean isJsonFormat() {
+ return this.jsonFormat;
+ }
+
+ public void setJsonFormat(boolean jsonFormat) {
+ this.jsonFormat = jsonFormat;
+ }
+
+ /**
+ * Properties to configure query logging listener.
+ */
+ public static class Query {
+
+ /**
+ * Enable logging all queries to the log.
+ */
+ private boolean enableLogging = true;
+
+ /**
+ * Name of query logger.
+ */
+ private String loggerName;
+
+ /**
+ * Severity of query logger.
+ */
+ private String logLevel = "DEBUG";
+
+ public boolean isEnableLogging() {
+ return this.enableLogging;
+ }
+
+ public void setEnableLogging(boolean enableLogging) {
+ this.enableLogging = enableLogging;
+ }
+
+ public String getLoggerName() {
+ return this.loggerName;
+ }
+
+ public void setLoggerName(String loggerName) {
+ this.loggerName = loggerName;
+ }
+
+ public String getLogLevel() {
+ return this.logLevel;
+ }
+
+ public void setLogLevel(String logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ }
+
+ /**
+ * Properties to configure slow query logging listener.
+ */
+ public static class SlowQuery {
+
+ /**
+ * Enable logging slow queries to the log.
+ */
+ private boolean enableLogging = true;
+
+ /**
+ * Name of slow query logger.
+ */
+ private String loggerName;
+
+ /**
+ * Severity of slow query logger.
+ */
+ private String logLevel = "WARN";
+
+ /**
+ * Number of seconds to consider query as slow.
+ */
+ private long threshold = 300;
+
+ boolean isEnableLogging() {
+ return enableLogging;
+ }
+
+ public void setEnableLogging(boolean enableLogging) {
+ this.enableLogging = enableLogging;
+ }
+
+ public String getLoggerName() {
+ return loggerName;
+ }
+
+ public void setLoggerName(String loggerName) {
+ this.loggerName = loggerName;
+ }
+
+ public String getLogLevel() {
+ return logLevel;
+ }
+
+ public void setLogLevel(String logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ public long getThreshold() {
+ return threshold;
+ }
+
+ public void setThreshold(long threshold) {
+ this.threshold = threshold;
+ }
+
+ }
+
+ /**
+ * Query logging listener is the most used listener that logs executing query with
+ * actual parameters to. You can pick one of the following proxy logging
+ * mechanisms.
+ */
+ public enum DataSourceProxyLogging {
+
+ /**
+ * Log using System.out.
+ */
+ SYSOUT,
+
+ /**
+ * Log using SLF4J.
+ */
+ SLF4J,
+
+ /**
+ * Log using Commons.
+ */
+ COMMONS,
+
+ /**
+ * Log using Java Util Logging.
+ */
+ JUL
+
+ }
+
+ }
+
+ /**
+ * Properties for configuring p6spy.
+ */
+ public static class P6SpyProperties {
+
+ /**
+ * Should the p6spy tracing be enabled?
+ */
+ private boolean enabled = true;
+
+ /**
+ * Enables logging JDBC events.
+ */
+ private boolean enableLogging = true;
+
+ /**
+ * Enables multiline output.
+ */
+ private boolean multiline = true;
+
+ /**
+ * Logging to use for logging queries.
+ */
+ private P6SpyLogging logging = P6SpyLogging.SLF4J;
+
+ /**
+ * Name of log file to use (only with logging=file).
+ */
+ private String logFile = "spy.log";
+
+ /**
+ * Custom log format.
+ */
+ private String logFormat;
+
+ /**
+ * Tracing related properties.
+ */
+ private P6SpyTracing tracing = new P6SpyTracing();
+
+ /**
+ * Class file to use (only with logging=custom). The class must implement
+ * {@link com.p6spy.engine.spy.appender.FormattedLogger}.
+ */
+ private String customAppenderClass;
+
+ /**
+ * Log filtering related properties.
+ */
+ private P6SpyLogFilter logFilter = new P6SpyLogFilter();
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public boolean isEnableLogging() {
+ return this.enableLogging;
+ }
+
+ public void setEnableLogging(boolean enableLogging) {
+ this.enableLogging = enableLogging;
+ }
+
+ public boolean isMultiline() {
+ return this.multiline;
+ }
+
+ public void setMultiline(boolean multiline) {
+ this.multiline = multiline;
+ }
+
+ public P6SpyLogging getLogging() {
+ return this.logging;
+ }
+
+ public void setLogging(P6SpyLogging logging) {
+ this.logging = logging;
+ }
+
+ public String getLogFile() {
+ return this.logFile;
+ }
+
+ public void setLogFile(String logFile) {
+ this.logFile = logFile;
+ }
+
+ public String getLogFormat() {
+ return this.logFormat;
+ }
+
+ public void setLogFormat(String logFormat) {
+ this.logFormat = logFormat;
+ }
+
+ public P6SpyTracing getTracing() {
+ return this.tracing;
+ }
+
+ public void setTracing(P6SpyTracing tracing) {
+ this.tracing = tracing;
+ }
+
+ public String getCustomAppenderClass() {
+ return this.customAppenderClass;
+ }
+
+ public void setCustomAppenderClass(String customAppenderClass) {
+ this.customAppenderClass = customAppenderClass;
+ }
+
+ public P6SpyLogFilter getLogFilter() {
+ return this.logFilter;
+ }
+
+ public void setLogFilter(P6SpyLogFilter logFilter) {
+ this.logFilter = logFilter;
+ }
+
+ /**
+ * P6Spy logging options.
+ */
+ public enum P6SpyLogging {
+
+ /**
+ * Log using System.out.
+ */
+ SYSOUT,
+
+ /**
+ * Log using SLF4J.
+ */
+ SLF4J,
+
+ /**
+ * Log to file.
+ */
+ FILE,
+
+ /**
+ * Custom logging.
+ */
+ CUSTOM
+
+ }
+
+ public static class P6SpyTracing {
+
+ /**
+ * Report the effective sql string (with '?' replaced with real values) to
+ * tracing systems.
+ *
+ * NOTE this setting does not affect the logging message.
+ */
+ private boolean includeParameterValues = true;
+
+ public boolean isIncludeParameterValues() {
+ return this.includeParameterValues;
+ }
+
+ public void setIncludeParameterValues(boolean includeParameterValues) {
+ this.includeParameterValues = includeParameterValues;
+ }
+
+ }
+
+ public static class P6SpyLogFilter {
+
+ /**
+ * Use regex pattern to filter log messages. Only matched messages will be
+ * logged.
+ */
+ private Pattern pattern;
+
+ public Pattern getPattern() {
+ return this.pattern;
+ }
+
+ public void setPattern(Pattern pattern) {
+ this.pattern = pattern;
+ }
+
+ }
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceNoOpAutoConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceNoOpAutoConfiguration.java
index 491a6ea42..c6ed16337 100644
--- a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceNoOpAutoConfiguration.java
+++ b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceNoOpAutoConfiguration.java
@@ -1,104 +1,103 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.cloud.sleuth.CurrentTraceContext;
-import org.springframework.cloud.sleuth.SpanCustomizer;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
-import org.springframework.cloud.sleuth.autoconfig.instrument.web.ConditionalOnSleuthWeb;
-import org.springframework.cloud.sleuth.autoconfig.instrument.web.client.ConditionalnOnSleuthWebClient;
-import org.springframework.cloud.sleuth.http.HttpClientHandler;
-import org.springframework.cloud.sleuth.http.HttpServerHandler;
-import org.springframework.cloud.sleuth.propagation.Propagator;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
-/**
- * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
- * Auto-configuration} to enable tracing via Spring Cloud Sleuth.
- *
- * @author Spencer Gibb
- * @author Marcin Grzejszczak
- * @author Tim Ysewyn
- * @since 2.0.0
- */
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnSleuth
-@ConditionalOnProperty("spring.sleuth.noop.enabled")
-@AutoConfigureBefore(BraveAutoConfiguration.class)
-@Import(TraceConfiguration.class)
-public class TraceNoOpAutoConfiguration {
-
- @Bean
- @ConditionalOnMissingBean
- Tracer defaultTracer() {
- return new NoOpTracer();
- }
-
- @Bean
- Propagator defaultPropagator() {
- return new NoOpPropagator();
- }
-
- @Bean
- CurrentTraceContext defaultCurrentTraceContext() {
- return new NoOpCurrentTraceContext();
- }
-
- @Bean
- SpanCustomizer defaultSpanCustomizer() {
- return new NoOpSpanCustomizer();
- }
-
- @Configuration(proxyBeanMethods = false)
- static class TraceHttpConfiguration {
-
- @Bean
- @ConditionalnOnSleuthWebClient
- HttpClientHandler defaultHttpClientHandler() {
- return new NoOpHttpClientHandler();
- }
-
- @Bean
- @ConditionalOnSleuthWeb
- HttpServerHandler defaultHttpServerHandler() {
- return new NoOpHttpServerHandler();
- }
-
- }
-}
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.TYPE, ElementType.METHOD })
-@Documented
-@ConditionalOnProperty(value = "spring.sleuth.enabled", matchIfMissing = true)
-@interface ConditionalOnSleuth {
-
-}
-
-
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.sleuth.CurrentTraceContext;
+import org.springframework.cloud.sleuth.SpanCustomizer;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
+import org.springframework.cloud.sleuth.autoconfig.instrument.web.ConditionalOnSleuthWeb;
+import org.springframework.cloud.sleuth.autoconfig.instrument.web.client.ConditionalnOnSleuthWebClient;
+import org.springframework.cloud.sleuth.http.HttpClientHandler;
+import org.springframework.cloud.sleuth.http.HttpServerHandler;
+import org.springframework.cloud.sleuth.propagation.Propagator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
+ * Auto-configuration} to enable tracing via Spring Cloud Sleuth.
+ *
+ * @author Spencer Gibb
+ * @author Marcin Grzejszczak
+ * @author Tim Ysewyn
+ * @since 2.0.0
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnSleuth
+@ConditionalOnProperty("spring.sleuth.noop.enabled")
+@AutoConfigureBefore(BraveAutoConfiguration.class)
+@Import(TraceConfiguration.class)
+public class TraceNoOpAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ Tracer defaultTracer() {
+ return new NoOpTracer();
+ }
+
+ @Bean
+ Propagator defaultPropagator() {
+ return new NoOpPropagator();
+ }
+
+ @Bean
+ CurrentTraceContext defaultCurrentTraceContext() {
+ return new NoOpCurrentTraceContext();
+ }
+
+ @Bean
+ SpanCustomizer defaultSpanCustomizer() {
+ return new NoOpSpanCustomizer();
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class TraceHttpConfiguration {
+
+ @Bean
+ @ConditionalnOnSleuthWebClient
+ HttpClientHandler defaultHttpClientHandler() {
+ return new NoOpHttpClientHandler();
+ }
+
+ @Bean
+ @ConditionalOnSleuthWeb
+ HttpServerHandler defaultHttpServerHandler() {
+ return new NoOpHttpServerHandler();
+ }
+
+ }
+
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Documented
+@ConditionalOnProperty(value = "spring.sleuth.enabled", matchIfMissing = true)
+@interface ConditionalOnSleuth {
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceDecoratorAutoConfigurationTests.java b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceDecoratorAutoConfigurationTests.java
index f2a08a139..f9d79f63c 100644
--- a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceDecoratorAutoConfigurationTests.java
+++ b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/DataSourceDecoratorAutoConfigurationTests.java
@@ -1,371 +1,370 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.logging.Logger;
-
-import javax.sql.DataSource;
-
-import com.p6spy.engine.spy.P6DataSource;
-import com.zaxxer.hikari.HikariDataSource;
-import net.ttddyy.dsproxy.support.ProxyDataSource;
-import org.apache.commons.dbcp2.BasicDataSource;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.beans.DirectFieldAccessor;
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceDecorator;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
-import org.springframework.context.annotation.Scope;
-import org.springframework.context.annotation.ScopedProxyMode;
-import org.springframework.context.support.GenericApplicationContext;
-import org.springframework.test.util.ReflectionTestUtils;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class DataSourceDecoratorAutoConfigurationTests {
-
- private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
- TraceJdbcAutoConfiguration.class, TraceNoOpAutoConfiguration.class,
- PropertyPlaceholderAutoConfiguration.class))
- .withPropertyValues("spring.datasource.initialization-mode=never",
- "spring.sleuth.noop.enabled=true",
- "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt());
-
- @Test
- void testDecoratingInDefaultOrder() {
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
-
- DataSourceWrapper DataSourceWrapper = (DataSourceWrapper) dataSource;
- assertThat(DataSourceWrapper.getDecoratedDataSource()).isInstanceOf(P6DataSource.class);
- P6DataSource p6DataSource = (P6DataSource) DataSourceWrapper.getDecoratedDataSource();
-
- DataSource p6WrappedDataSource = (DataSource) ReflectionTestUtils.getField(p6DataSource, "realDataSource");
- assertThat(p6WrappedDataSource).isInstanceOf(ProxyDataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) p6WrappedDataSource;
- });
- }
-
- @Test
- void testNoDecoratingForExcludeBeans() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.excluded-data-source-bean-names:dataSource");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
-
- assertThat(dataSource).isInstanceOf(HikariDataSource.class);
- });
- }
-
- @Test
- void testDecoratingWhenDefaultProxyProviderNotAvailable() {
- ApplicationContextRunner contextRunner = this.contextRunner;
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
-
- assertThat(((DataSourceWrapper) dataSource).getOriginalDataSource()).isInstanceOf(HikariDataSource.class);
-
- DataSourceWrapper DataSourceWrapper = (DataSourceWrapper) dataSource;
- assertThat(DataSourceWrapper.getDecoratedDataSource()).isInstanceOf(P6DataSource.class);
- P6DataSource p6DataSource = (P6DataSource) DataSourceWrapper.getDecoratedDataSource();
-
- DataSource p6WrappedDataSource = (DataSource) ReflectionTestUtils.getField(p6DataSource, "realDataSource");
- assertThat(p6WrappedDataSource).isInstanceOf(ProxyDataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) p6WrappedDataSource;
-
- DataSource dsProxyWrappedDataSource = (DataSource) ReflectionTestUtils.getField(proxyDataSource,
- "dataSource");
- assertThat(dsProxyWrappedDataSource).isEqualTo(DataSourceWrapper.getOriginalDataSource());
- });
- }
-
- @Test
- void testDecoratedHikariSpecificPropertiesIsSet() {
- ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
- "spring.datasource.type:" + HikariDataSource.class.getName(),
- "spring.datasource.hikari.catalog:test_catalog");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- assertThat(dataSource).isNotNull();
- assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
- DataSource realDataSource = ((DataSourceWrapper) dataSource).getOriginalDataSource();
- assertThat(realDataSource).isInstanceOf(HikariDataSource.class);
- assertThat(((HikariDataSource) realDataSource).getCatalog()).isEqualTo("test_catalog");
- });
- }
-
- @Test
- void testCustomDataSourceIsDecorated() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withUserConfiguration(TestDataSourceConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
- DataSource realDataSource = ((DataSourceWrapper) dataSource).getOriginalDataSource();
- assertThat(realDataSource).isInstanceOf(BasicDataSource.class);
- });
- }
-
- @Test
- void testScopedDataSourceIsNotDecorated() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withUserConfiguration(TestScopedDataSourceConfiguration.class);
-
- contextRunner.run(context -> {
- assertThat(context).getBeanNames(DataSource.class).containsOnly("dataSource", "scopedTarget.dataSource");
- assertThat(context).getBean("dataSource").isInstanceOf(DataSourceWrapper.class);
- assertThat(context).getBean("scopedTarget.dataSource").isNotInstanceOf(DataSourceWrapper.class);
- });
- }
-
- @Test
- void testCustomDataSourceDecoratorApplied() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withUserConfiguration(TestDataSourceDecoratorConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- assertThat(dataSource).isNotNull();
-
- DataSource customDataSource = ((DataSourceWrapper) dataSource).getDecoratedDataSource();
- assertThat(customDataSource).isInstanceOf(CustomDataSourceProxy.class);
-
- DataSource realDataSource = ((DataSourceWrapper) dataSource).getOriginalDataSource();
- assertThat(realDataSource).isInstanceOf(HikariDataSource.class);
-
- assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
-
- DataSourceWrapper DataSourceWrapper = (DataSourceWrapper) dataSource;
-
- assertThat(DataSourceWrapper.getDecoratedDataSource()).isInstanceOf(CustomDataSourceProxy.class);
- CustomDataSourceProxy customDataSourceProxy = (CustomDataSourceProxy) DataSourceWrapper
- .getDecoratedDataSource();
-
- assertThat(customDataSourceProxy.delegate).isInstanceOf(P6DataSource.class);
- P6DataSource p6DataSource = (P6DataSource) customDataSourceProxy.delegate;
-
- DataSource p6WrappedDataSource = (DataSource) ReflectionTestUtils.getField(p6DataSource, "realDataSource");
- assertThat(p6WrappedDataSource).isInstanceOf(ProxyDataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) p6WrappedDataSource;
- });
- }
-
- @Test
- void testDecoratingCanBeDisabled() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.enabled:false");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- assertThat(dataSource).isInstanceOf(HikariDataSource.class);
- });
- }
-
- @Test
- void testDecoratingCanBeDisabledForSpecificBeans() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.excluded-data-source-bean-names:secondDataSource")
- .withUserConfiguration(TestMultiDataSourceConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean("dataSource", DataSource.class);
- assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
-
- DataSource secondDataSource = context.getBean("secondDataSource", DataSource.class);
- assertThat(secondDataSource).isInstanceOf(BasicDataSource.class);
- });
- }
-
- @Test
- void testDecoratingChainBuiltCorrectly() {
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
-
- DataSourceWrapper dataSource1 = context.getBean(DataSourceWrapper.class);
- assertThat(dataSource1).isNotNull();
-
- DataSource p6DataSource = dataSource1.getDecoratedDataSource();
- assertThat(p6DataSource).isNotNull();
- assertThat(p6DataSource).isInstanceOf(P6DataSource.class);
-
- DataSource proxyDataSource = (DataSource) new DirectFieldAccessor(p6DataSource)
- .getPropertyValue("realDataSource");
- assertThat(proxyDataSource).isNotNull();
- assertThat(proxyDataSource).isInstanceOf(ProxyDataSource.class);
- });
- }
-
- @Test
- void testDecorateDynamicallyRegisteredBeans() {
- ApplicationContextRunner contextRunner = this.contextRunner.withInitializer(context -> {
- GenericApplicationContext gac = (GenericApplicationContext) context;
- gac.registerBean("ds1", DataSource.class, () -> new HikariDataSource());
- gac.registerBean("ds2", DataSource.class, () -> new HikariDataSource());
- });
-
- contextRunner.run(context -> {
- DataSource dataSource1 = context.getBean("ds1", DataSource.class);
- assertThat(dataSource1).isNotNull();
- assertThat(dataSource1).isInstanceOf(DataSourceWrapper.class);
-
- DataSource dataSource2 = context.getBean("ds2", DataSource.class);
- assertThat(dataSource2).isNotNull();
- assertThat(dataSource2).isInstanceOf(DataSourceWrapper.class);
- });
- }
-
- @Configuration
- static class TestDataSourceConfiguration {
-
- @Bean
- public DataSource dataSource() {
- BasicDataSource pool = new BasicDataSource();
- pool.setDriverClassName("org.hsqldb.jdbcDriver");
- pool.setUrl("jdbc:hsqldb:target/overridedb");
- pool.setUsername("sa");
- return pool;
- }
-
- }
-
- @Configuration
- static class TestDataSourceDecoratorConfiguration {
-
- @Bean
- public DataSourceDecorator customDataSourceDecorator() {
- return (beanName, dataSource) -> new CustomDataSourceProxy(dataSource);
- }
-
- }
-
- @Configuration
- static class TestMultiDataSourceConfiguration {
-
- @Bean
- @Primary
- public DataSource dataSource() {
- BasicDataSource pool = new BasicDataSource();
- pool.setDriverClassName("org.hsqldb.jdbcDriver");
- pool.setUrl("jdbc:hsqldb:target/db");
- pool.setUsername("sa");
- return pool;
- }
-
- @Bean
- public DataSource secondDataSource() {
- BasicDataSource pool = new BasicDataSource();
- pool.setDriverClassName("org.hsqldb.jdbcDriver");
- pool.setUrl("jdbc:hsqldb:target/db2");
- pool.setUsername("sa");
- return pool;
- }
-
- }
-
- @Configuration
- static class TestScopedDataSourceConfiguration {
-
- @Bean
- @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
- public DataSource dataSource() {
- BasicDataSource pool = new BasicDataSource();
- pool.setDriverClassName("org.hsqldb.jdbcDriver");
- pool.setUrl("jdbc:hsqldb:target/overridedb");
- pool.setUsername("sa");
- return pool;
- }
-
- }
-
- /**
- * Custom proxy data source for tests.
- *
- * @author Arthur Gavlyukovskiy
- */
- static class CustomDataSourceProxy implements DataSource {
-
- private final DataSource delegate;
-
- CustomDataSourceProxy(DataSource delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public Connection getConnection() {
- return null;
- }
-
- @Override
- public Connection getConnection(String username, String password) {
- return null;
- }
-
- @Override
- public T unwrap(Class iface) {
- return null;
- }
-
- @Override
- public boolean isWrapperFor(Class> iface) {
- return false;
- }
-
- @Override
- public PrintWriter getLogWriter() {
- return null;
- }
-
- @Override
- public void setLogWriter(PrintWriter out) {
-
- }
-
- @Override
- public void setLoginTimeout(int seconds) {
-
- }
-
- @Override
- public int getLoginTimeout() {
- return 0;
- }
-
- @Override
- public Logger getParentLogger() {
- return null;
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+import com.p6spy.engine.spy.P6DataSource;
+import com.zaxxer.hikari.HikariDataSource;
+import net.ttddyy.dsproxy.support.ProxyDataSource;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.DirectFieldAccessor;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceDecorator;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class DataSourceDecoratorAutoConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(DataSourceAutoConfiguration.class, TraceJdbcAutoConfiguration.class,
+ TraceNoOpAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class))
+ .withPropertyValues("spring.datasource.initialization-mode=never", "spring.sleuth.noop.enabled=true",
+ "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt());
+
+ @Test
+ void testDecoratingInDefaultOrder() {
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
+
+ DataSourceWrapper DataSourceWrapper = (DataSourceWrapper) dataSource;
+ assertThat(DataSourceWrapper.getDecoratedDataSource()).isInstanceOf(P6DataSource.class);
+ P6DataSource p6DataSource = (P6DataSource) DataSourceWrapper.getDecoratedDataSource();
+
+ DataSource p6WrappedDataSource = (DataSource) ReflectionTestUtils.getField(p6DataSource, "realDataSource");
+ assertThat(p6WrappedDataSource).isInstanceOf(ProxyDataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) p6WrappedDataSource;
+ });
+ }
+
+ @Test
+ void testNoDecoratingForExcludeBeans() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.excluded-data-source-bean-names:dataSource");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+
+ assertThat(dataSource).isInstanceOf(HikariDataSource.class);
+ });
+ }
+
+ @Test
+ void testDecoratingWhenDefaultProxyProviderNotAvailable() {
+ ApplicationContextRunner contextRunner = this.contextRunner;
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+
+ assertThat(((DataSourceWrapper) dataSource).getOriginalDataSource()).isInstanceOf(HikariDataSource.class);
+
+ DataSourceWrapper DataSourceWrapper = (DataSourceWrapper) dataSource;
+ assertThat(DataSourceWrapper.getDecoratedDataSource()).isInstanceOf(P6DataSource.class);
+ P6DataSource p6DataSource = (P6DataSource) DataSourceWrapper.getDecoratedDataSource();
+
+ DataSource p6WrappedDataSource = (DataSource) ReflectionTestUtils.getField(p6DataSource, "realDataSource");
+ assertThat(p6WrappedDataSource).isInstanceOf(ProxyDataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) p6WrappedDataSource;
+
+ DataSource dsProxyWrappedDataSource = (DataSource) ReflectionTestUtils.getField(proxyDataSource,
+ "dataSource");
+ assertThat(dsProxyWrappedDataSource).isEqualTo(DataSourceWrapper.getOriginalDataSource());
+ });
+ }
+
+ @Test
+ void testDecoratedHikariSpecificPropertiesIsSet() {
+ ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
+ "spring.datasource.type:" + HikariDataSource.class.getName(),
+ "spring.datasource.hikari.catalog:test_catalog");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ assertThat(dataSource).isNotNull();
+ assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
+ DataSource realDataSource = ((DataSourceWrapper) dataSource).getOriginalDataSource();
+ assertThat(realDataSource).isInstanceOf(HikariDataSource.class);
+ assertThat(((HikariDataSource) realDataSource).getCatalog()).isEqualTo("test_catalog");
+ });
+ }
+
+ @Test
+ void testCustomDataSourceIsDecorated() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withUserConfiguration(TestDataSourceConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
+ DataSource realDataSource = ((DataSourceWrapper) dataSource).getOriginalDataSource();
+ assertThat(realDataSource).isInstanceOf(BasicDataSource.class);
+ });
+ }
+
+ @Test
+ void testScopedDataSourceIsNotDecorated() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withUserConfiguration(TestScopedDataSourceConfiguration.class);
+
+ contextRunner.run(context -> {
+ assertThat(context).getBeanNames(DataSource.class).containsOnly("dataSource", "scopedTarget.dataSource");
+ assertThat(context).getBean("dataSource").isInstanceOf(DataSourceWrapper.class);
+ assertThat(context).getBean("scopedTarget.dataSource").isNotInstanceOf(DataSourceWrapper.class);
+ });
+ }
+
+ @Test
+ void testCustomDataSourceDecoratorApplied() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withUserConfiguration(TestDataSourceDecoratorConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ assertThat(dataSource).isNotNull();
+
+ DataSource customDataSource = ((DataSourceWrapper) dataSource).getDecoratedDataSource();
+ assertThat(customDataSource).isInstanceOf(CustomDataSourceProxy.class);
+
+ DataSource realDataSource = ((DataSourceWrapper) dataSource).getOriginalDataSource();
+ assertThat(realDataSource).isInstanceOf(HikariDataSource.class);
+
+ assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
+
+ DataSourceWrapper DataSourceWrapper = (DataSourceWrapper) dataSource;
+
+ assertThat(DataSourceWrapper.getDecoratedDataSource()).isInstanceOf(CustomDataSourceProxy.class);
+ CustomDataSourceProxy customDataSourceProxy = (CustomDataSourceProxy) DataSourceWrapper
+ .getDecoratedDataSource();
+
+ assertThat(customDataSourceProxy.delegate).isInstanceOf(P6DataSource.class);
+ P6DataSource p6DataSource = (P6DataSource) customDataSourceProxy.delegate;
+
+ DataSource p6WrappedDataSource = (DataSource) ReflectionTestUtils.getField(p6DataSource, "realDataSource");
+ assertThat(p6WrappedDataSource).isInstanceOf(ProxyDataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) p6WrappedDataSource;
+ });
+ }
+
+ @Test
+ void testDecoratingCanBeDisabled() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.enabled:false");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ assertThat(dataSource).isInstanceOf(HikariDataSource.class);
+ });
+ }
+
+ @Test
+ void testDecoratingCanBeDisabledForSpecificBeans() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.excluded-data-source-bean-names:secondDataSource")
+ .withUserConfiguration(TestMultiDataSourceConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean("dataSource", DataSource.class);
+ assertThat(dataSource).isInstanceOf(DataSourceWrapper.class);
+
+ DataSource secondDataSource = context.getBean("secondDataSource", DataSource.class);
+ assertThat(secondDataSource).isInstanceOf(BasicDataSource.class);
+ });
+ }
+
+ @Test
+ void testDecoratingChainBuiltCorrectly() {
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+
+ DataSourceWrapper dataSource1 = context.getBean(DataSourceWrapper.class);
+ assertThat(dataSource1).isNotNull();
+
+ DataSource p6DataSource = dataSource1.getDecoratedDataSource();
+ assertThat(p6DataSource).isNotNull();
+ assertThat(p6DataSource).isInstanceOf(P6DataSource.class);
+
+ DataSource proxyDataSource = (DataSource) new DirectFieldAccessor(p6DataSource)
+ .getPropertyValue("realDataSource");
+ assertThat(proxyDataSource).isNotNull();
+ assertThat(proxyDataSource).isInstanceOf(ProxyDataSource.class);
+ });
+ }
+
+ @Test
+ void testDecorateDynamicallyRegisteredBeans() {
+ ApplicationContextRunner contextRunner = this.contextRunner.withInitializer(context -> {
+ GenericApplicationContext gac = (GenericApplicationContext) context;
+ gac.registerBean("ds1", DataSource.class, () -> new HikariDataSource());
+ gac.registerBean("ds2", DataSource.class, () -> new HikariDataSource());
+ });
+
+ contextRunner.run(context -> {
+ DataSource dataSource1 = context.getBean("ds1", DataSource.class);
+ assertThat(dataSource1).isNotNull();
+ assertThat(dataSource1).isInstanceOf(DataSourceWrapper.class);
+
+ DataSource dataSource2 = context.getBean("ds2", DataSource.class);
+ assertThat(dataSource2).isNotNull();
+ assertThat(dataSource2).isInstanceOf(DataSourceWrapper.class);
+ });
+ }
+
+ @Configuration
+ static class TestDataSourceConfiguration {
+
+ @Bean
+ public DataSource dataSource() {
+ BasicDataSource pool = new BasicDataSource();
+ pool.setDriverClassName("org.hsqldb.jdbcDriver");
+ pool.setUrl("jdbc:hsqldb:target/overridedb");
+ pool.setUsername("sa");
+ return pool;
+ }
+
+ }
+
+ @Configuration
+ static class TestDataSourceDecoratorConfiguration {
+
+ @Bean
+ public DataSourceDecorator customDataSourceDecorator() {
+ return (beanName, dataSource) -> new CustomDataSourceProxy(dataSource);
+ }
+
+ }
+
+ @Configuration
+ static class TestMultiDataSourceConfiguration {
+
+ @Bean
+ @Primary
+ public DataSource dataSource() {
+ BasicDataSource pool = new BasicDataSource();
+ pool.setDriverClassName("org.hsqldb.jdbcDriver");
+ pool.setUrl("jdbc:hsqldb:target/db");
+ pool.setUsername("sa");
+ return pool;
+ }
+
+ @Bean
+ public DataSource secondDataSource() {
+ BasicDataSource pool = new BasicDataSource();
+ pool.setDriverClassName("org.hsqldb.jdbcDriver");
+ pool.setUrl("jdbc:hsqldb:target/db2");
+ pool.setUsername("sa");
+ return pool;
+ }
+
+ }
+
+ @Configuration
+ static class TestScopedDataSourceConfiguration {
+
+ @Bean
+ @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
+ public DataSource dataSource() {
+ BasicDataSource pool = new BasicDataSource();
+ pool.setDriverClassName("org.hsqldb.jdbcDriver");
+ pool.setUrl("jdbc:hsqldb:target/overridedb");
+ pool.setUsername("sa");
+ return pool;
+ }
+
+ }
+
+ /**
+ * Custom proxy data source for tests.
+ *
+ * @author Arthur Gavlyukovskiy
+ */
+ static class CustomDataSourceProxy implements DataSource {
+
+ private final DataSource delegate;
+
+ CustomDataSourceProxy(DataSource delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Connection getConnection() {
+ return null;
+ }
+
+ @Override
+ public Connection getConnection(String username, String password) {
+ return null;
+ }
+
+ @Override
+ public T unwrap(Class iface) {
+ return null;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> iface) {
+ return false;
+ }
+
+ @Override
+ public PrintWriter getLogWriter() {
+ return null;
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter out) {
+
+ }
+
+ @Override
+ public void setLoginTimeout(int seconds) {
+
+ }
+
+ @Override
+ public int getLoginTimeout() {
+ return 0;
+ }
+
+ @Override
+ public Logger getParentLogger() {
+ return null;
+ }
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfigurationTests.java b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfigurationTests.java
index 0573e862d..2c5a9c551 100644
--- a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfigurationTests.java
+++ b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/P6SpyConfigurationTests.java
@@ -1,280 +1,278 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ThreadLocalRandom;
-
-import javax.sql.DataSource;
-
-import com.p6spy.engine.common.ConnectionInformation;
-import com.p6spy.engine.common.P6LogQuery;
-import com.p6spy.engine.event.CompoundJdbcEventListener;
-import com.p6spy.engine.event.JdbcEventListener;
-import com.p6spy.engine.logging.Category;
-import com.p6spy.engine.logging.LoggingEventListener;
-import com.p6spy.engine.spy.JdbcEventListenerFactory;
-import com.p6spy.engine.spy.P6DataSource;
-import com.p6spy.engine.spy.appender.CustomLineFormat;
-import com.p6spy.engine.spy.appender.FormattedLogger;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.test.context.FilteredClassLoader;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class P6SpyConfigurationTests {
-
- private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
- TraceJdbcAutoConfiguration.class, TraceNoOpAutoConfiguration.class,
- PropertyPlaceholderAutoConfiguration.class))
- .withPropertyValues("spring.datasource.initialization-mode=never",
- "spring.sleuth.noop.enabled=true",
- "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
- .withClassLoader(new FilteredClassLoader("net.ttddyy.dsproxy"));
-
- @BeforeEach
- @AfterEach
- void resetLogAccumulator() {
- LogAccumulator.reset();
- }
-
- @Test
- void testCustomListeners() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withUserConfiguration(CustomListenerConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
- GetCountingListener getCountingListener = context.getBean(GetCountingListener.class);
- ClosingCountingListener closingCountingListener = context.getBean(ClosingCountingListener.class);
- P6DataSource p6DataSource = (P6DataSource) ((DataSourceWrapper) dataSource).getDecoratedDataSource();
- assertThat(p6DataSource).extracting("jdbcEventListenerFactory").isEqualTo(jdbcEventListenerFactory);
-
- CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
- .createJdbcEventListener();
-
- assertThat(jdbcEventListener.getEventListeners()).contains(getCountingListener, closingCountingListener);
- assertThat(getCountingListener.connectionCount).isEqualTo(0);
-
- Connection connection1 = p6DataSource.getConnection();
-
- assertThat(getCountingListener.connectionCount).isEqualTo(1);
- assertThat(closingCountingListener.connectionCount).isEqualTo(0);
-
- Connection connection2 = p6DataSource.getConnection();
-
- assertThat(getCountingListener.connectionCount).isEqualTo(2);
-
- // order matters!
- connection2.close();
-
- assertThat(closingCountingListener.connectionCount).isEqualTo(1);
-
- // order matters!
- connection1.close();
-
- assertThat(closingCountingListener.connectionCount).isEqualTo(2);
- });
- }
-
- @Test
- void testDoesNotRegisterLoggingListenerIfDisabled() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.p6spy.enable-logging=false");
-
- contextRunner.run(context -> {
- JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
- CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
- .createJdbcEventListener();
-
- assertThat(jdbcEventListener.getEventListeners()).extracting("class")
- .doesNotContain(LoggingEventListener.class);
- });
- }
-
- @Test
- void testCanSetCustomLoggingFormat() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.p6spy.log-format:test %{connectionId}");
-
- contextRunner.run(context -> {
- JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
- CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
- .createJdbcEventListener();
-
- assertThat(jdbcEventListener.getEventListeners()).extracting("class").contains(LoggingEventListener.class);
- assertThat(P6LogQuery.getLogger()).extracting("strategy").extracting("class")
- .isEqualTo(CustomLineFormat.class);
- });
- }
-
- @Test
- void testMultilineShouldNotOverrideCustomProperties() {
- System.setProperty("p6spy.config.logMessageFormat", "com.p6spy.engine.spy.appender.CustomLineFormat");
- System.setProperty("p6spy.config.excludecategories", "debug");
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.p6spy.multiline:true");
-
- contextRunner.run(context -> {
- JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
- CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
- .createJdbcEventListener();
-
- assertThat(jdbcEventListener.getEventListeners()).extracting("class").contains(LoggingEventListener.class);
- assertThat(P6LogQuery.getLogger()).extracting("strategy").extracting("class")
- .isEqualTo(CustomLineFormat.class);
- });
- }
-
- @Test
- void testUseCustomLogger() {
- ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
- "spring.sleuth.jdbc.p6spy.logging=custom",
- "spring.sleuth.jdbc.p6spy.custom-appender-class:" + LogAccumulator.class.getName());
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- dataSource.getConnection().close();
-
- assertThat(P6LogQuery.getLogger()).isInstanceOf(LogAccumulator.class);
- });
- }
-
- @Test
- void testLogFilterPattern() {
- ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
- "spring.sleuth.jdbc.p6spy.logging=custom",
- "spring.sleuth.jdbc.p6spy.custom-appender-class:" + LogAccumulator.class.getName(),
- "spring.sleuth.jdbc.p6spy.log-filter.pattern:.*table1.*");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- try (Connection connection = dataSource.getConnection();
- PreparedStatement ps1 = connection.prepareStatement("select 1 /* from table1 */");
- PreparedStatement ps2 = connection.prepareStatement("select 1 /* from table2 */")) {
- ps1.execute();
- ps2.execute();
- }
-
- assertThat(LogAccumulator.MESSAGES).hasSize(1);
- assertThat(LogAccumulator.MESSAGES).allMatch(message -> message.contains("table1"));
- });
- }
-
- @Test
- void testLogFilterPatternMatchAll() {
- ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
- "spring.sleuth.jdbc.p6spy.logging=custom",
- "spring.sleuth.jdbc.p6spy.custom-appender-class:" + LogAccumulator.class.getName(),
- "spring.sleuth.jdbc.p6spy.log-filter.pattern:.*");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- try (Connection connection = dataSource.getConnection();
- PreparedStatement ps1 = connection.prepareStatement("select 1 /* from table1 */");
- PreparedStatement ps2 = connection.prepareStatement("select 1 /* from table2 */")) {
- ps1.execute();
- ps2.execute();
- }
-
- assertThat(LogAccumulator.MESSAGES).hasSize(2);
- });
- }
-
- @Configuration
- static class CustomListenerConfiguration {
-
- @Bean
- public GetCountingListener wrappingCountingListener() {
- return new GetCountingListener();
- }
-
- @Bean
- public ClosingCountingListener closingCountingListener() {
- return new ClosingCountingListener();
- }
-
- }
-
- static class GetCountingListener extends JdbcEventListener {
-
- int connectionCount = 0;
-
- @Override
- public void onAfterGetConnection(ConnectionInformation connectionInformation, SQLException e) {
- connectionCount++;
- }
-
- }
-
- static class ClosingCountingListener extends JdbcEventListener {
-
- int connectionCount = 0;
-
- @Override
- public void onAfterConnectionClose(ConnectionInformation connectionInformation, SQLException e) {
- connectionCount++;
- }
-
- }
-
- public static class LogAccumulator extends FormattedLogger {
-
- static final List MESSAGES = new ArrayList<>();
- static final List EXCEPTIONS = new ArrayList<>();
-
- public static void reset() {
- MESSAGES.clear();
- EXCEPTIONS.clear();
- }
-
- @Override
- public void logException(Exception e) {
- EXCEPTIONS.add(e);
- }
-
- @Override
- public void logText(String text) {
- MESSAGES.add(text);
- }
-
- @Override
- public boolean isCategoryEnabled(Category category) {
- return true;
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.sql.DataSource;
+
+import com.p6spy.engine.common.ConnectionInformation;
+import com.p6spy.engine.common.P6LogQuery;
+import com.p6spy.engine.event.CompoundJdbcEventListener;
+import com.p6spy.engine.event.JdbcEventListener;
+import com.p6spy.engine.logging.Category;
+import com.p6spy.engine.logging.LoggingEventListener;
+import com.p6spy.engine.spy.JdbcEventListenerFactory;
+import com.p6spy.engine.spy.P6DataSource;
+import com.p6spy.engine.spy.appender.CustomLineFormat;
+import com.p6spy.engine.spy.appender.FormattedLogger;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class P6SpyConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(DataSourceAutoConfiguration.class, TraceJdbcAutoConfiguration.class,
+ TraceNoOpAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class))
+ .withPropertyValues("spring.datasource.initialization-mode=never", "spring.sleuth.noop.enabled=true",
+ "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
+ .withClassLoader(new FilteredClassLoader("net.ttddyy.dsproxy"));
+
+ @BeforeEach
+ @AfterEach
+ void resetLogAccumulator() {
+ LogAccumulator.reset();
+ }
+
+ @Test
+ void testCustomListeners() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withUserConfiguration(CustomListenerConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
+ GetCountingListener getCountingListener = context.getBean(GetCountingListener.class);
+ ClosingCountingListener closingCountingListener = context.getBean(ClosingCountingListener.class);
+ P6DataSource p6DataSource = (P6DataSource) ((DataSourceWrapper) dataSource).getDecoratedDataSource();
+ assertThat(p6DataSource).extracting("jdbcEventListenerFactory").isEqualTo(jdbcEventListenerFactory);
+
+ CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
+ .createJdbcEventListener();
+
+ assertThat(jdbcEventListener.getEventListeners()).contains(getCountingListener, closingCountingListener);
+ assertThat(getCountingListener.connectionCount).isEqualTo(0);
+
+ Connection connection1 = p6DataSource.getConnection();
+
+ assertThat(getCountingListener.connectionCount).isEqualTo(1);
+ assertThat(closingCountingListener.connectionCount).isEqualTo(0);
+
+ Connection connection2 = p6DataSource.getConnection();
+
+ assertThat(getCountingListener.connectionCount).isEqualTo(2);
+
+ // order matters!
+ connection2.close();
+
+ assertThat(closingCountingListener.connectionCount).isEqualTo(1);
+
+ // order matters!
+ connection1.close();
+
+ assertThat(closingCountingListener.connectionCount).isEqualTo(2);
+ });
+ }
+
+ @Test
+ void testDoesNotRegisterLoggingListenerIfDisabled() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.p6spy.enable-logging=false");
+
+ contextRunner.run(context -> {
+ JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
+ CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
+ .createJdbcEventListener();
+
+ assertThat(jdbcEventListener.getEventListeners()).extracting("class")
+ .doesNotContain(LoggingEventListener.class);
+ });
+ }
+
+ @Test
+ void testCanSetCustomLoggingFormat() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.p6spy.log-format:test %{connectionId}");
+
+ contextRunner.run(context -> {
+ JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
+ CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
+ .createJdbcEventListener();
+
+ assertThat(jdbcEventListener.getEventListeners()).extracting("class").contains(LoggingEventListener.class);
+ assertThat(P6LogQuery.getLogger()).extracting("strategy").extracting("class")
+ .isEqualTo(CustomLineFormat.class);
+ });
+ }
+
+ @Test
+ void testMultilineShouldNotOverrideCustomProperties() {
+ System.setProperty("p6spy.config.logMessageFormat", "com.p6spy.engine.spy.appender.CustomLineFormat");
+ System.setProperty("p6spy.config.excludecategories", "debug");
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.p6spy.multiline:true");
+
+ contextRunner.run(context -> {
+ JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
+ CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
+ .createJdbcEventListener();
+
+ assertThat(jdbcEventListener.getEventListeners()).extracting("class").contains(LoggingEventListener.class);
+ assertThat(P6LogQuery.getLogger()).extracting("strategy").extracting("class")
+ .isEqualTo(CustomLineFormat.class);
+ });
+ }
+
+ @Test
+ void testUseCustomLogger() {
+ ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
+ "spring.sleuth.jdbc.p6spy.logging=custom",
+ "spring.sleuth.jdbc.p6spy.custom-appender-class:" + LogAccumulator.class.getName());
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ dataSource.getConnection().close();
+
+ assertThat(P6LogQuery.getLogger()).isInstanceOf(LogAccumulator.class);
+ });
+ }
+
+ @Test
+ void testLogFilterPattern() {
+ ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
+ "spring.sleuth.jdbc.p6spy.logging=custom",
+ "spring.sleuth.jdbc.p6spy.custom-appender-class:" + LogAccumulator.class.getName(),
+ "spring.sleuth.jdbc.p6spy.log-filter.pattern:.*table1.*");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement ps1 = connection.prepareStatement("select 1 /* from table1 */");
+ PreparedStatement ps2 = connection.prepareStatement("select 1 /* from table2 */")) {
+ ps1.execute();
+ ps2.execute();
+ }
+
+ assertThat(LogAccumulator.MESSAGES).hasSize(1);
+ assertThat(LogAccumulator.MESSAGES).allMatch(message -> message.contains("table1"));
+ });
+ }
+
+ @Test
+ void testLogFilterPatternMatchAll() {
+ ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
+ "spring.sleuth.jdbc.p6spy.logging=custom",
+ "spring.sleuth.jdbc.p6spy.custom-appender-class:" + LogAccumulator.class.getName(),
+ "spring.sleuth.jdbc.p6spy.log-filter.pattern:.*");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement ps1 = connection.prepareStatement("select 1 /* from table1 */");
+ PreparedStatement ps2 = connection.prepareStatement("select 1 /* from table2 */")) {
+ ps1.execute();
+ ps2.execute();
+ }
+
+ assertThat(LogAccumulator.MESSAGES).hasSize(2);
+ });
+ }
+
+ @Configuration
+ static class CustomListenerConfiguration {
+
+ @Bean
+ public GetCountingListener wrappingCountingListener() {
+ return new GetCountingListener();
+ }
+
+ @Bean
+ public ClosingCountingListener closingCountingListener() {
+ return new ClosingCountingListener();
+ }
+
+ }
+
+ static class GetCountingListener extends JdbcEventListener {
+
+ int connectionCount = 0;
+
+ @Override
+ public void onAfterGetConnection(ConnectionInformation connectionInformation, SQLException e) {
+ connectionCount++;
+ }
+
+ }
+
+ static class ClosingCountingListener extends JdbcEventListener {
+
+ int connectionCount = 0;
+
+ @Override
+ public void onAfterConnectionClose(ConnectionInformation connectionInformation, SQLException e) {
+ connectionCount++;
+ }
+
+ }
+
+ public static class LogAccumulator extends FormattedLogger {
+
+ static final List MESSAGES = new ArrayList<>();
+ static final List EXCEPTIONS = new ArrayList<>();
+
+ public static void reset() {
+ MESSAGES.clear();
+ EXCEPTIONS.clear();
+ }
+
+ @Override
+ public void logException(Exception e) {
+ EXCEPTIONS.add(e);
+ }
+
+ @Override
+ public void logText(String text) {
+ MESSAGES.add(text);
+ }
+
+ @Override
+ public boolean isCategoryEnabled(Category category) {
+ return true;
+ }
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/ProxyDataSourceConfigurationTests.java b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/ProxyDataSourceConfigurationTests.java
index 6b10c2d95..844f34a23 100644
--- a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/ProxyDataSourceConfigurationTests.java
+++ b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/ProxyDataSourceConfigurationTests.java
@@ -1,239 +1,238 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.util.List;
-import java.util.concurrent.ThreadLocalRandom;
-
-import javax.sql.DataSource;
-
-import net.ttddyy.dsproxy.ExecutionInfo;
-import net.ttddyy.dsproxy.QueryInfo;
-import net.ttddyy.dsproxy.listener.ChainListener;
-import net.ttddyy.dsproxy.listener.QueryExecutionListener;
-import net.ttddyy.dsproxy.listener.logging.CommonsQueryLoggingListener;
-import net.ttddyy.dsproxy.listener.logging.CommonsSlowQueryListener;
-import net.ttddyy.dsproxy.listener.logging.JULQueryLoggingListener;
-import net.ttddyy.dsproxy.listener.logging.JULSlowQueryListener;
-import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener;
-import net.ttddyy.dsproxy.listener.logging.SLF4JSlowQueryListener;
-import net.ttddyy.dsproxy.listener.logging.SystemOutQueryLoggingListener;
-import net.ttddyy.dsproxy.listener.logging.SystemOutSlowQueryListener;
-import net.ttddyy.dsproxy.proxy.DefaultConnectionIdManager;
-import net.ttddyy.dsproxy.proxy.GlobalConnectionIdManager;
-import net.ttddyy.dsproxy.support.ProxyDataSource;
-import net.ttddyy.dsproxy.transform.ParameterTransformer;
-import net.ttddyy.dsproxy.transform.QueryTransformer;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.test.context.FilteredClassLoader;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyConnectionIdManagerProvider;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ProxyDataSourceConfigurationTests {
-
- private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
- TraceJdbcAutoConfiguration.class, TraceNoOpAutoConfiguration.class,
- PropertyPlaceholderAutoConfiguration.class))
- .withPropertyValues("spring.datasource.initialization-mode=never",
- "spring.sleuth.noop.enabled=true",
- "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
- .withClassLoader(new FilteredClassLoader("com.p6spy"));
-
- @Test
- void testRegisterLogAndSlowQueryLogByDefaultToSlf4j() {
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
- assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JSlowQueryListener.class);
- assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JQueryLoggingListener.class);
- });
- }
-
- @Test
- void testRegisterLogAndSlowQueryLogByUsingSlf4j() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.datasource-proxy.logging=slf4j");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
- assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JSlowQueryListener.class);
- assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JQueryLoggingListener.class);
- });
- }
-
- @Test
- void testRegisterLogAndSlowQueryLogUsingSystemOut() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.datasource-proxy.logging=sysout");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
- assertThat(chainListener.getListeners()).extracting("class").contains(SystemOutSlowQueryListener.class);
- assertThat(chainListener.getListeners()).extracting("class").contains(SystemOutQueryLoggingListener.class);
- });
- }
-
- @Test
- void testRegisterLogAndSlowQueryLogUsingJUL() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.datasourceProxy.logging=jul");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
- assertThat(chainListener.getListeners()).extracting("class").contains(JULSlowQueryListener.class);
- assertThat(chainListener.getListeners()).extracting("class").contains(JULQueryLoggingListener.class);
- });
- }
-
- @Test
- void testRegisterLogAndSlowQueryLogUsingApacheCommons() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withPropertyValues("spring.sleuth.jdbc.datasourceProxy.logging=commons");
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
- assertThat(chainListener.getListeners()).extracting("class").contains(CommonsSlowQueryListener.class);
- assertThat(chainListener.getListeners()).extracting("class").contains(CommonsQueryLoggingListener.class);
- });
- }
-
- @Test
- void testCustomParameterAndQueryTransformer() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withUserConfiguration(CustomDataSourceProxyConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- ParameterTransformer parameterTransformer = context.getBean(ParameterTransformer.class);
- QueryTransformer queryTransformer = context.getBean(QueryTransformer.class);
- assertThat(proxyDataSource.getProxyConfig().getParameterTransformer()).isSameAs(parameterTransformer);
- assertThat(proxyDataSource.getProxyConfig().getQueryTransformer()).isSameAs(queryTransformer);
- });
- }
-
- @Test
- void testCustomListeners() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withUserConfiguration(CustomListenerConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- QueryExecutionListener queryExecutionListener = context.getBean(QueryExecutionListener.class);
-
- ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
- assertThat(chainListener.getListeners()).contains(queryExecutionListener);
- });
- }
-
- @Test
- void testGlobalConnectionIdManagerByDefault() {
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
-
- assertThat(proxyDataSource.getConnectionIdManager()).isInstanceOf(GlobalConnectionIdManager.class);
- });
- }
-
- @Test
- void testCustomConnectionIdManager() {
- ApplicationContextRunner contextRunner = this.contextRunner
- .withUserConfiguration(CustomDataSourceProxyConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
-
- assertThat(proxyDataSource.getConnectionIdManager()).isInstanceOf(DefaultConnectionIdManager.class);
- });
- }
-
- @Configuration
- static class CustomDataSourceProxyConfiguration {
-
- @Bean
- public ParameterTransformer parameterTransformer() {
- return (replacer, transformInfo) -> {
- };
- }
-
- @Bean
- public QueryTransformer queryTransformer() {
- return (transformInfo) -> "TestQuery";
- }
-
- @Bean
- public DataSourceProxyConnectionIdManagerProvider connectionIdManagerProvider() {
- return DefaultConnectionIdManager::new;
- }
-
- }
-
- @Configuration
- static class CustomListenerConfiguration {
-
- @Bean
- @Primary
- public QueryExecutionListener queryExecutionListener() {
- return new QueryExecutionListener() {
- @Override
- public void beforeQuery(ExecutionInfo execInfo, List queryInfoList) {
- System.out.println("beforeQuery");
- }
-
- @Override
- public void afterQuery(ExecutionInfo execInfo, List queryInfoList) {
- System.out.println("afterQuery");
- }
- };
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.sql.DataSource;
+
+import net.ttddyy.dsproxy.ExecutionInfo;
+import net.ttddyy.dsproxy.QueryInfo;
+import net.ttddyy.dsproxy.listener.ChainListener;
+import net.ttddyy.dsproxy.listener.QueryExecutionListener;
+import net.ttddyy.dsproxy.listener.logging.CommonsQueryLoggingListener;
+import net.ttddyy.dsproxy.listener.logging.CommonsSlowQueryListener;
+import net.ttddyy.dsproxy.listener.logging.JULQueryLoggingListener;
+import net.ttddyy.dsproxy.listener.logging.JULSlowQueryListener;
+import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener;
+import net.ttddyy.dsproxy.listener.logging.SLF4JSlowQueryListener;
+import net.ttddyy.dsproxy.listener.logging.SystemOutQueryLoggingListener;
+import net.ttddyy.dsproxy.listener.logging.SystemOutSlowQueryListener;
+import net.ttddyy.dsproxy.proxy.DefaultConnectionIdManager;
+import net.ttddyy.dsproxy.proxy.GlobalConnectionIdManager;
+import net.ttddyy.dsproxy.support.ProxyDataSource;
+import net.ttddyy.dsproxy.transform.ParameterTransformer;
+import net.ttddyy.dsproxy.transform.QueryTransformer;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceProxyConnectionIdManagerProvider;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ProxyDataSourceConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(DataSourceAutoConfiguration.class, TraceJdbcAutoConfiguration.class,
+ TraceNoOpAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class))
+ .withPropertyValues("spring.datasource.initialization-mode=never", "spring.sleuth.noop.enabled=true",
+ "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
+ .withClassLoader(new FilteredClassLoader("com.p6spy"));
+
+ @Test
+ void testRegisterLogAndSlowQueryLogByDefaultToSlf4j() {
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
+ assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JSlowQueryListener.class);
+ assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JQueryLoggingListener.class);
+ });
+ }
+
+ @Test
+ void testRegisterLogAndSlowQueryLogByUsingSlf4j() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.datasource-proxy.logging=slf4j");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
+ assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JSlowQueryListener.class);
+ assertThat(chainListener.getListeners()).extracting("class").contains(SLF4JQueryLoggingListener.class);
+ });
+ }
+
+ @Test
+ void testRegisterLogAndSlowQueryLogUsingSystemOut() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.datasource-proxy.logging=sysout");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
+ assertThat(chainListener.getListeners()).extracting("class").contains(SystemOutSlowQueryListener.class);
+ assertThat(chainListener.getListeners()).extracting("class").contains(SystemOutQueryLoggingListener.class);
+ });
+ }
+
+ @Test
+ void testRegisterLogAndSlowQueryLogUsingJUL() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.datasourceProxy.logging=jul");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
+ assertThat(chainListener.getListeners()).extracting("class").contains(JULSlowQueryListener.class);
+ assertThat(chainListener.getListeners()).extracting("class").contains(JULQueryLoggingListener.class);
+ });
+ }
+
+ @Test
+ void testRegisterLogAndSlowQueryLogUsingApacheCommons() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withPropertyValues("spring.sleuth.jdbc.datasourceProxy.logging=commons");
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
+ assertThat(chainListener.getListeners()).extracting("class").contains(CommonsSlowQueryListener.class);
+ assertThat(chainListener.getListeners()).extracting("class").contains(CommonsQueryLoggingListener.class);
+ });
+ }
+
+ @Test
+ void testCustomParameterAndQueryTransformer() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withUserConfiguration(CustomDataSourceProxyConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ ParameterTransformer parameterTransformer = context.getBean(ParameterTransformer.class);
+ QueryTransformer queryTransformer = context.getBean(QueryTransformer.class);
+ assertThat(proxyDataSource.getProxyConfig().getParameterTransformer()).isSameAs(parameterTransformer);
+ assertThat(proxyDataSource.getProxyConfig().getQueryTransformer()).isSameAs(queryTransformer);
+ });
+ }
+
+ @Test
+ void testCustomListeners() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withUserConfiguration(CustomListenerConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ QueryExecutionListener queryExecutionListener = context.getBean(QueryExecutionListener.class);
+
+ ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
+ assertThat(chainListener.getListeners()).contains(queryExecutionListener);
+ });
+ }
+
+ @Test
+ void testGlobalConnectionIdManagerByDefault() {
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+
+ assertThat(proxyDataSource.getConnectionIdManager()).isInstanceOf(GlobalConnectionIdManager.class);
+ });
+ }
+
+ @Test
+ void testCustomConnectionIdManager() {
+ ApplicationContextRunner contextRunner = this.contextRunner
+ .withUserConfiguration(CustomDataSourceProxyConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+
+ assertThat(proxyDataSource.getConnectionIdManager()).isInstanceOf(DefaultConnectionIdManager.class);
+ });
+ }
+
+ @Configuration
+ static class CustomDataSourceProxyConfiguration {
+
+ @Bean
+ public ParameterTransformer parameterTransformer() {
+ return (replacer, transformInfo) -> {
+ };
+ }
+
+ @Bean
+ public QueryTransformer queryTransformer() {
+ return (transformInfo) -> "TestQuery";
+ }
+
+ @Bean
+ public DataSourceProxyConnectionIdManagerProvider connectionIdManagerProvider() {
+ return DefaultConnectionIdManager::new;
+ }
+
+ }
+
+ @Configuration
+ static class CustomListenerConfiguration {
+
+ @Bean
+ @Primary
+ public QueryExecutionListener queryExecutionListener() {
+ return new QueryExecutionListener() {
+ @Override
+ public void beforeQuery(ExecutionInfo execInfo, List queryInfoList) {
+ System.out.println("beforeQuery");
+ }
+
+ @Override
+ public void afterQuery(ExecutionInfo execInfo, List queryInfoList) {
+ System.out.println("afterQuery");
+ }
+ };
+ }
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthP6SpyListenerAutoConfigurationTests.java b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthP6SpyListenerAutoConfigurationTests.java
index 0d1153ef0..af03d9335 100644
--- a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthP6SpyListenerAutoConfigurationTests.java
+++ b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthP6SpyListenerAutoConfigurationTests.java
@@ -1,66 +1,65 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-import com.p6spy.engine.event.CompoundJdbcEventListener;
-import com.p6spy.engine.spy.JdbcEventListenerFactory;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.test.context.FilteredClassLoader;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceJdbcEventListener;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class SleuthP6SpyListenerAutoConfigurationTests {
-
- private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
- TraceJdbcAutoConfiguration.class, TraceNoOpAutoConfiguration.class,
- PropertyPlaceholderAutoConfiguration.class))
- .withPropertyValues("spring.datasource.initialization-mode=never",
- "spring.sleuth.noop.enabled=true",
- "spring.datasource.url=jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
- .withClassLoader(new FilteredClassLoader("net.ttddyy.dsproxy"));
-
- @Test
- void testAddsP6SpyListener() {
- contextRunner.run(context -> {
- JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
- CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
- .createJdbcEventListener();
- assertThat(jdbcEventListener.getEventListeners()).extracting("class")
- .contains(TraceJdbcEventListener.class);
- });
- }
-
- @Test
- void testDoesNotAddP6SpyListenerIfNoTracer() {
- ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues("spring.sleuth.enabled=false");
-
- contextRunner.run(context -> {
- assertThat(context).doesNotHaveBean(JdbcEventListenerFactory.class);
- });
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import com.p6spy.engine.event.CompoundJdbcEventListener;
+import com.p6spy.engine.spy.JdbcEventListenerFactory;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceJdbcEventListener;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class SleuthP6SpyListenerAutoConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(DataSourceAutoConfiguration.class, TraceJdbcAutoConfiguration.class,
+ TraceNoOpAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class))
+ .withPropertyValues("spring.datasource.initialization-mode=never", "spring.sleuth.noop.enabled=true",
+ "spring.datasource.url=jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
+ .withClassLoader(new FilteredClassLoader("net.ttddyy.dsproxy"));
+
+ @Test
+ void testAddsP6SpyListener() {
+ contextRunner.run(context -> {
+ JdbcEventListenerFactory jdbcEventListenerFactory = context.getBean(JdbcEventListenerFactory.class);
+ CompoundJdbcEventListener jdbcEventListener = (CompoundJdbcEventListener) jdbcEventListenerFactory
+ .createJdbcEventListener();
+ assertThat(jdbcEventListener.getEventListeners()).extracting("class")
+ .contains(TraceJdbcEventListener.class);
+ });
+ }
+
+ @Test
+ void testDoesNotAddP6SpyListenerIfNoTracer() {
+ ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues("spring.sleuth.enabled=false");
+
+ contextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(JdbcEventListenerFactory.class);
+ });
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthProxyDataSourceListenerAutoConfigurationTests.java b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthProxyDataSourceListenerAutoConfigurationTests.java
index 9380ce316..1bc7cd052 100644
--- a/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthProxyDataSourceListenerAutoConfigurationTests.java
+++ b/spring-cloud-sleuth-autoconfigure/src/test/java/org/springframework/cloud/sleuth/autoconfig/instrument/jdbc/SleuthProxyDataSourceListenerAutoConfigurationTests.java
@@ -1,69 +1,68 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-import javax.sql.DataSource;
-
-import net.ttddyy.dsproxy.listener.ChainListener;
-import net.ttddyy.dsproxy.support.ProxyDataSource;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.test.context.FilteredClassLoader;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
-import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
-import org.springframework.cloud.sleuth.instrument.jdbc.TraceQueryExecutionListener;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class SleuthProxyDataSourceListenerAutoConfigurationTests {
-
- private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
- TraceJdbcAutoConfiguration.class, TraceNoOpAutoConfiguration.class,
- PropertyPlaceholderAutoConfiguration.class))
- .withPropertyValues("spring.datasource.initialization-mode=never",
- "spring.sleuth.noop.enabled=true",
- "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
- .withClassLoader(new FilteredClassLoader("com.p6spy"));
-
- @Test
- void testAddsDatasourceProxyListener() {
- contextRunner.run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
- .getDecoratedDataSource();
- ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
- assertThat(chainListener.getListeners()).extracting("class").contains(TraceQueryExecutionListener.class);
- });
- }
-
- @Test
- void testDoesNotAddDatasourceProxyListenerIfNoTracer() {
- ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues("spring.sleuth.enabled:false");
-
- contextRunner.run(context -> {
- assertThat(context).doesNotHaveBean(DataSourceWrapper.class);
- });
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.autoconfig.instrument.jdbc;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.sql.DataSource;
+
+import net.ttddyy.dsproxy.listener.ChainListener;
+import net.ttddyy.dsproxy.support.ProxyDataSource;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.autoconfig.TraceNoOpAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.jdbc.DataSourceWrapper;
+import org.springframework.cloud.sleuth.instrument.jdbc.TraceQueryExecutionListener;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class SleuthProxyDataSourceListenerAutoConfigurationTests {
+
+ private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(DataSourceAutoConfiguration.class, TraceJdbcAutoConfiguration.class,
+ TraceNoOpAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class))
+ .withPropertyValues("spring.datasource.initialization-mode=never", "spring.sleuth.noop.enabled=true",
+ "spring.datasource.url:jdbc:h2:mem:testdb-" + ThreadLocalRandom.current().nextInt())
+ .withClassLoader(new FilteredClassLoader("com.p6spy"));
+
+ @Test
+ void testAddsDatasourceProxyListener() {
+ contextRunner.run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ ProxyDataSource proxyDataSource = (ProxyDataSource) ((DataSourceWrapper) dataSource)
+ .getDecoratedDataSource();
+ ChainListener chainListener = proxyDataSource.getProxyConfig().getQueryListener();
+ assertThat(chainListener.getListeners()).extracting("class").contains(TraceQueryExecutionListener.class);
+ });
+ }
+
+ @Test
+ void testDoesNotAddDatasourceProxyListenerIfNoTracer() {
+ ApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues("spring.sleuth.enabled:false");
+
+ contextRunner.run(context -> {
+ assertThat(context).doesNotHaveBean(DataSourceWrapper.class);
+ });
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceListenerStrategySpanCustomizer.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceListenerStrategySpanCustomizer.java
index 3fd40e9d5..52fe0ae6b 100644
--- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceListenerStrategySpanCustomizer.java
+++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceListenerStrategySpanCustomizer.java
@@ -1,43 +1,43 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.instrument.jdbc;
-
-import javax.sql.CommonDataSource;
-
-import org.springframework.cloud.sleuth.Span;
-
-/**
- * Customizer for {@link TraceListenerStrategy} client span.
- *
- * @author Marcin Grzejszczak
- * @since 3.1.0
- */
-public interface TraceListenerStrategySpanCustomizer {
-
- /**
- * Customizes the client database span.
- * @param spanBuilder span builder
- */
- void customizeConnectionSpan(T dataSource, Span.Builder spanBuilder);
-
- /**
- * @param dataSource data source for which we're building the span
- * @return {@code true} when this customizer can be applied
- */
- boolean isApplicable(CommonDataSource dataSource);
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.instrument.jdbc;
+
+import javax.sql.CommonDataSource;
+
+import org.springframework.cloud.sleuth.Span;
+
+/**
+ * Customizer for {@link TraceListenerStrategy} client span.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.1.0
+ */
+public interface TraceListenerStrategySpanCustomizer {
+
+ /**
+ * Customizes the client database span.
+ * @param spanBuilder span builder
+ */
+ void customizeConnectionSpan(T dataSource, Span.Builder spanBuilder);
+
+ /**
+ * @param dataSource data source for which we're building the span
+ * @return {@code true} when this customizer can be applied
+ */
+ boolean isApplicable(CommonDataSource dataSource);
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceType.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceType.java
index 2348ae3fc..cef75651a 100644
--- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceType.java
+++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TraceType.java
@@ -1,39 +1,39 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.instrument.jdbc;
-
-/**
- * Trace types.
- */
-public enum TraceType {
-
- /**
- * Related to JDBC connections.
- */
- CONNECTION,
-
- /**
- * Related to query executions.
- */
- QUERY,
-
- /**
- * Related to ResultSets.
- */
- FETCH
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.instrument.jdbc;
+
+/**
+ * Trace types.
+ */
+public enum TraceType {
+
+ /**
+ * Related to JDBC connections.
+ */
+ CONNECTION,
+
+ /**
+ * Related to query executions.
+ */
+ QUERY,
+
+ /**
+ * Related to ResultSets.
+ */
+ FETCH
+
+}
diff --git a/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingJdbcEventListenerTests.java b/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingJdbcEventListenerTests.java
index 96b6c08aa..0abe1b11e 100644
--- a/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingJdbcEventListenerTests.java
+++ b/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingJdbcEventListenerTests.java
@@ -1,60 +1,60 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.brave.instrument.jdbc;
-
-import brave.sampler.Sampler;
-
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
-import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
-import org.springframework.cloud.sleuth.test.TestSpanHandler;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-public class TracingJdbcEventListenerTests
- extends org.springframework.cloud.sleuth.instrument.jdbc.TracingJdbcEventListenerTests {
-
- @Override
- protected Class autoConfiguration() {
- return BraveAutoConfiguration.class;
- }
-
- @Override
- protected Class testConfiguration() {
- return Config.class;
- }
-
- @Configuration(proxyBeanMethods = false)
- static class Config {
-
- @Bean
- TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
- return new BraveTestSpanHandler(testSpanHandler);
- }
-
- @Bean
- Sampler alwaysSampler() {
- return Sampler.ALWAYS_SAMPLE;
- }
-
- @Bean
- brave.test.TestSpanHandler braveTestSpanHandler() {
- return new brave.test.TestSpanHandler();
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.brave.instrument.jdbc;
+
+import brave.sampler.Sampler;
+
+import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
+import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
+import org.springframework.cloud.sleuth.test.TestSpanHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+public class TracingJdbcEventListenerTests
+ extends org.springframework.cloud.sleuth.instrument.jdbc.TracingJdbcEventListenerTests {
+
+ @Override
+ protected Class autoConfiguration() {
+ return BraveAutoConfiguration.class;
+ }
+
+ @Override
+ protected Class testConfiguration() {
+ return Config.class;
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class Config {
+
+ @Bean
+ TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
+ return new BraveTestSpanHandler(testSpanHandler);
+ }
+
+ @Bean
+ Sampler alwaysSampler() {
+ return Sampler.ALWAYS_SAMPLE;
+ }
+
+ @Bean
+ brave.test.TestSpanHandler braveTestSpanHandler() {
+ return new brave.test.TestSpanHandler();
+ }
+
+ }
+
+}
diff --git a/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingQueryExecutionListenerTests.java b/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingQueryExecutionListenerTests.java
index c2a442054..e9bacd2b8 100644
--- a/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingQueryExecutionListenerTests.java
+++ b/tests/brave/spring-cloud-sleuth-instrumentation-jdbc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/jdbc/TracingQueryExecutionListenerTests.java
@@ -1,60 +1,60 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.brave.instrument.jdbc;
-
-import brave.sampler.Sampler;
-
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
-import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
-import org.springframework.cloud.sleuth.test.TestSpanHandler;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-public class TracingQueryExecutionListenerTests
- extends org.springframework.cloud.sleuth.instrument.jdbc.TracingQueryExecutionListenerTests {
-
- @Override
- protected Class autoConfiguration() {
- return BraveAutoConfiguration.class;
- }
-
- @Override
- protected Class testConfiguration() {
- return Config.class;
- }
-
- @Configuration(proxyBeanMethods = false)
- static class Config {
-
- @Bean
- TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
- return new BraveTestSpanHandler(testSpanHandler);
- }
-
- @Bean
- Sampler alwaysSampler() {
- return Sampler.ALWAYS_SAMPLE;
- }
-
- @Bean
- brave.test.TestSpanHandler braveTestSpanHandler() {
- return new brave.test.TestSpanHandler();
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.brave.instrument.jdbc;
+
+import brave.sampler.Sampler;
+
+import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
+import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
+import org.springframework.cloud.sleuth.test.TestSpanHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+public class TracingQueryExecutionListenerTests
+ extends org.springframework.cloud.sleuth.instrument.jdbc.TracingQueryExecutionListenerTests {
+
+ @Override
+ protected Class autoConfiguration() {
+ return BraveAutoConfiguration.class;
+ }
+
+ @Override
+ protected Class testConfiguration() {
+ return Config.class;
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class Config {
+
+ @Bean
+ TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
+ return new BraveTestSpanHandler(testSpanHandler);
+ }
+
+ @Bean
+ Sampler alwaysSampler() {
+ return Sampler.ALWAYS_SAMPLE;
+ }
+
+ @Bean
+ brave.test.TestSpanHandler braveTestSpanHandler() {
+ return new brave.test.TestSpanHandler();
+ }
+
+ }
+
+}
diff --git a/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceAsyncIntegrationTests.java b/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceAsyncIntegrationTests.java
index 5ebdeb20d..e24da75ef 100644
--- a/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceAsyncIntegrationTests.java
+++ b/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/TraceAsyncIntegrationTests.java
@@ -1,237 +1,238 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.brave.instrument.web;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
-import brave.Span;
-import brave.Tracer;
-import brave.handler.MutableSpan;
-import brave.handler.SpanHandler;
-import brave.sampler.Sampler;
-import brave.test.TestSpanHandler;
-import org.awaitility.Awaitility;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.cloud.sleuth.SpanName;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.task.SimpleAsyncTaskExecutor;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.scheduling.annotation.EnableAsync;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.assertj.core.api.BDDAssertions.then;
-
-@SpringBootTest(classes = { TraceAsyncIntegrationTests.TraceAsyncITestConfiguration.class })
-public class TraceAsyncIntegrationTests {
-
- @Autowired
- ClassPerformingAsyncLogic classPerformingAsyncLogic;
-
- @Autowired
- Tracer tracer;
-
- @Autowired
- TestSpanHandler spans;
-
- @BeforeEach
- public void cleanup() {
- this.spans.clear();
- this.classPerformingAsyncLogic.clear();
- }
-
- @Test
- public void should_set_span_on_an_async_annotated_method() {
- whenAsyncProcessingTakesPlace();
-
- thenANewAsyncSpanGetsCreated();
- }
-
- @Test
- public void should_set_span_with_custom_method_on_an_async_annotated_method() {
- whenAsyncProcessingTakesPlaceWithCustomSpanName();
-
- thenAsyncSpanHasCustomName();
- }
-
- @Test
- public void should_continue_a_span_on_an_async_annotated_method() {
- Span span = givenASpanInCurrentThread();
-
- try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
- whenAsyncProcessingTakesPlace();
- }
- finally {
- span.finish();
- }
-
- thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(span);
- }
-
- @Test
- public void should_continue_a_span_with_custom_method_on_an_async_annotated_method() {
- Span span = givenASpanInCurrentThread();
-
- try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
- whenAsyncProcessingTakesPlaceWithCustomSpanName();
- }
- finally {
- span.finish();
- }
-
- thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(span);
- }
-
- private Span givenASpanInCurrentThread() {
- return this.tracer.nextSpan().name("http:existing");
- }
-
- private void whenAsyncProcessingTakesPlace() {
- this.classPerformingAsyncLogic.invokeAsynchronousLogic();
- }
-
- private void whenAsyncProcessingTakesPlaceWithCustomSpanName() {
- this.classPerformingAsyncLogic.customNameInvokeAsynchronousLogic();
- }
-
- private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(final Span span) {
- Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
- then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan().context().traceId())
- .isEqualTo(span.context().traceId());
- List webSpans = this.spans.spans().stream().filter(mutableSpan -> mutableSpan.traceId().equalsIgnoreCase(span.context().traceIdString()))
- .collect(Collectors.toList());
- then(webSpans).hasSize(2);
- // HTTP
- then(webSpans.get(0).name()).isEqualTo("http:existing");
- // ASYNC
- then(webSpans.get(1).tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
- "invokeAsynchronousLogic");
- });
- }
-
- private void thenANewAsyncSpanGetsCreated() {
- Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
- then(this.spans).hasSize(1);
- MutableSpan storedSpan = this.spans.get(0);
- then(storedSpan.name()).isEqualTo("invoke-asynchronous-logic");
- then(storedSpan.tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
- "invokeAsynchronousLogic");
- });
- }
-
- private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(final Span span) {
- Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
- then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan()).isNotNull();
- then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan().context().traceId())
- .isEqualTo(span.context().traceId());
- then(this.spans).hasSize(2);
- // HTTP
- then(this.spans.get(0).name()).isEqualTo("http:existing");
- // ASYNC
- then(this.spans.get(1).tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
- "customNameInvokeAsynchronousLogic");
- });
- }
-
- private void thenAsyncSpanHasCustomName() {
- Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
- then(this.spans).hasSize(1);
- MutableSpan storedSpan = this.spans.get(0);
- then(storedSpan.name()).isEqualTo("foo");
- then(storedSpan.tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
- "customNameInvokeAsynchronousLogic");
- });
- }
-
- @AfterEach
- public void cleanTrace() {
- this.spans.clear();
- }
-
- @EnableAutoConfiguration
- @EnableAsync
- @Configuration(proxyBeanMethods = false)
- static class TraceAsyncITestConfiguration {
-
- @Bean
- ClassPerformingAsyncLogic asyncClass(Tracer tracer) {
- return new ClassPerformingAsyncLogic(tracer);
- }
-
- @Bean
- Sampler defaultSampler() {
- return Sampler.ALWAYS_SAMPLE;
- }
-
- @Bean
- SpanHandler testSpanHandler() {
- return new TestSpanHandler();
- }
-
- @Bean
- Executor fooExecutor() {
- return new SimpleAsyncTaskExecutor();
- }
-
- @Bean
- Executor barExecutor() {
- return new SimpleAsyncTaskExecutor();
- }
-
- }
-
- static class ClassPerformingAsyncLogic {
-
- private final Tracer tracer;
-
- AtomicReference span = new AtomicReference<>();
-
- ClassPerformingAsyncLogic(Tracer tracer) {
- this.tracer = tracer;
- }
-
- @Async("fooExecutor")
- public void invokeAsynchronousLogic() {
- this.span.set(this.tracer.currentSpan());
- }
-
- @Async
- @SpanName("foo")
- public void customNameInvokeAsynchronousLogic() {
- this.span.set(this.tracer.currentSpan());
- }
-
- public Span getSpan() {
- return this.span.get();
- }
-
- public void clear() {
- this.span.set(null);
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.brave.instrument.web;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+import brave.Span;
+import brave.Tracer;
+import brave.handler.MutableSpan;
+import brave.handler.SpanHandler;
+import brave.sampler.Sampler;
+import brave.test.TestSpanHandler;
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.sleuth.SpanName;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.SimpleAsyncTaskExecutor;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.assertj.core.api.BDDAssertions.then;
+
+@SpringBootTest(classes = { TraceAsyncIntegrationTests.TraceAsyncITestConfiguration.class })
+public class TraceAsyncIntegrationTests {
+
+ @Autowired
+ ClassPerformingAsyncLogic classPerformingAsyncLogic;
+
+ @Autowired
+ Tracer tracer;
+
+ @Autowired
+ TestSpanHandler spans;
+
+ @BeforeEach
+ public void cleanup() {
+ this.spans.clear();
+ this.classPerformingAsyncLogic.clear();
+ }
+
+ @Test
+ public void should_set_span_on_an_async_annotated_method() {
+ whenAsyncProcessingTakesPlace();
+
+ thenANewAsyncSpanGetsCreated();
+ }
+
+ @Test
+ public void should_set_span_with_custom_method_on_an_async_annotated_method() {
+ whenAsyncProcessingTakesPlaceWithCustomSpanName();
+
+ thenAsyncSpanHasCustomName();
+ }
+
+ @Test
+ public void should_continue_a_span_on_an_async_annotated_method() {
+ Span span = givenASpanInCurrentThread();
+
+ try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
+ whenAsyncProcessingTakesPlace();
+ }
+ finally {
+ span.finish();
+ }
+
+ thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(span);
+ }
+
+ @Test
+ public void should_continue_a_span_with_custom_method_on_an_async_annotated_method() {
+ Span span = givenASpanInCurrentThread();
+
+ try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
+ whenAsyncProcessingTakesPlaceWithCustomSpanName();
+ }
+ finally {
+ span.finish();
+ }
+
+ thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(span);
+ }
+
+ private Span givenASpanInCurrentThread() {
+ return this.tracer.nextSpan().name("http:existing");
+ }
+
+ private void whenAsyncProcessingTakesPlace() {
+ this.classPerformingAsyncLogic.invokeAsynchronousLogic();
+ }
+
+ private void whenAsyncProcessingTakesPlaceWithCustomSpanName() {
+ this.classPerformingAsyncLogic.customNameInvokeAsynchronousLogic();
+ }
+
+ private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(final Span span) {
+ Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
+ then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan().context().traceId())
+ .isEqualTo(span.context().traceId());
+ List webSpans = this.spans.spans().stream()
+ .filter(mutableSpan -> mutableSpan.traceId().equalsIgnoreCase(span.context().traceIdString()))
+ .collect(Collectors.toList());
+ then(webSpans).hasSize(2);
+ // HTTP
+ then(webSpans.get(0).name()).isEqualTo("http:existing");
+ // ASYNC
+ then(webSpans.get(1).tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
+ "invokeAsynchronousLogic");
+ });
+ }
+
+ private void thenANewAsyncSpanGetsCreated() {
+ Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
+ then(this.spans).hasSize(1);
+ MutableSpan storedSpan = this.spans.get(0);
+ then(storedSpan.name()).isEqualTo("invoke-asynchronous-logic");
+ then(storedSpan.tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
+ "invokeAsynchronousLogic");
+ });
+ }
+
+ private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(final Span span) {
+ Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
+ then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan()).isNotNull();
+ then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan().context().traceId())
+ .isEqualTo(span.context().traceId());
+ then(this.spans).hasSize(2);
+ // HTTP
+ then(this.spans.get(0).name()).isEqualTo("http:existing");
+ // ASYNC
+ then(this.spans.get(1).tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
+ "customNameInvokeAsynchronousLogic");
+ });
+ }
+
+ private void thenAsyncSpanHasCustomName() {
+ Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
+ then(this.spans).hasSize(1);
+ MutableSpan storedSpan = this.spans.get(0);
+ then(storedSpan.name()).isEqualTo("foo");
+ then(storedSpan.tags()).containsEntry("class", "ClassPerformingAsyncLogic").containsEntry("method",
+ "customNameInvokeAsynchronousLogic");
+ });
+ }
+
+ @AfterEach
+ public void cleanTrace() {
+ this.spans.clear();
+ }
+
+ @EnableAutoConfiguration
+ @EnableAsync
+ @Configuration(proxyBeanMethods = false)
+ static class TraceAsyncITestConfiguration {
+
+ @Bean
+ ClassPerformingAsyncLogic asyncClass(Tracer tracer) {
+ return new ClassPerformingAsyncLogic(tracer);
+ }
+
+ @Bean
+ Sampler defaultSampler() {
+ return Sampler.ALWAYS_SAMPLE;
+ }
+
+ @Bean
+ SpanHandler testSpanHandler() {
+ return new TestSpanHandler();
+ }
+
+ @Bean
+ Executor fooExecutor() {
+ return new SimpleAsyncTaskExecutor();
+ }
+
+ @Bean
+ Executor barExecutor() {
+ return new SimpleAsyncTaskExecutor();
+ }
+
+ }
+
+ static class ClassPerformingAsyncLogic {
+
+ private final Tracer tracer;
+
+ AtomicReference span = new AtomicReference<>();
+
+ ClassPerformingAsyncLogic(Tracer tracer) {
+ this.tracer = tracer;
+ }
+
+ @Async("fooExecutor")
+ public void invokeAsynchronousLogic() {
+ this.span.set(this.tracer.currentSpan());
+ }
+
+ @Async
+ @SpanName("foo")
+ public void customNameInvokeAsynchronousLogic() {
+ this.span.set(this.tracer.currentSpan());
+ }
+
+ public Span getSpan() {
+ return this.span.get();
+ }
+
+ public void clear() {
+ this.span.set(null);
+ }
+
+ }
+
+}
diff --git a/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/view/Issue469Tests.java b/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/view/Issue469Tests.java
index 9f12664e7..530b1e496 100644
--- a/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/view/Issue469Tests.java
+++ b/tests/brave/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/brave/instrument/web/view/Issue469Tests.java
@@ -1,60 +1,60 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.brave.instrument.web.view;
-
-import brave.test.TestSpanHandler;
-import org.awaitility.Awaitility;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.core.env.Environment;
-import org.springframework.test.context.TestPropertySource;
-import org.springframework.web.client.RestTemplate;
-
-import static org.assertj.core.api.BDDAssertions.then;
-
-@SpringBootTest(classes = Issue469.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@TestPropertySource(properties = { "spring.mvc.view.prefix=/WEB-INF/jsp/", "spring.mvc.view.suffix=.jsp" })
-public class Issue469Tests {
-
- @Autowired
- TestSpanHandler spans;
-
- @Autowired
- Environment environment;
-
- RestTemplate restTemplate = new RestTemplate();
-
- @Test
- public void should_not_result_in_tracing_exceptions_when_using_view_controllers() {
- try {
- this.restTemplate.getForObject("http://localhost:" + port() + "/welcome", String.class);
- }
- catch (Exception e) {
- // JSPs are not rendered
- then(e).hasMessageContaining("404");
- }
-
- Awaitility.await().untilAsserted(() -> then(this.spans).isNotEmpty());
- }
-
- private int port() {
- return this.environment.getProperty("local.server.port", Integer.class);
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.brave.instrument.web.view;
+
+import brave.test.TestSpanHandler;
+import org.awaitility.Awaitility;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.core.env.Environment;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.web.client.RestTemplate;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+@SpringBootTest(classes = Issue469.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@TestPropertySource(properties = { "spring.mvc.view.prefix=/WEB-INF/jsp/", "spring.mvc.view.suffix=.jsp" })
+public class Issue469Tests {
+
+ @Autowired
+ TestSpanHandler spans;
+
+ @Autowired
+ Environment environment;
+
+ RestTemplate restTemplate = new RestTemplate();
+
+ @Test
+ public void should_not_result_in_tracing_exceptions_when_using_view_controllers() {
+ try {
+ this.restTemplate.getForObject("http://localhost:" + port() + "/welcome", String.class);
+ }
+ catch (Exception e) {
+ // JSPs are not rendered
+ then(e).hasMessageContaining("404");
+ }
+
+ Awaitility.await().untilAsserted(() -> then(this.spans).isNotEmpty());
+ }
+
+ private int port() {
+ return this.environment.getProperty("local.server.port", Integer.class);
+ }
+
+}
diff --git a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingJdbcEventListenerTests.java b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingJdbcEventListenerTests.java
index ac0cf1b03..776dd5aa1 100644
--- a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingJdbcEventListenerTests.java
+++ b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingJdbcEventListenerTests.java
@@ -1,79 +1,78 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.instrument.jdbc;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-
-import javax.sql.DataSource;
-
-import brave.handler.MutableSpan;
-import brave.test.TestSpanHandler;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.test.context.FilteredClassLoader;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.autoconfig.instrument.jdbc.TraceJdbcAutoConfiguration;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public abstract class TracingJdbcEventListenerTests extends TracingListenerStrategyTests {
-
- protected final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
- TraceJdbcAutoConfiguration.class, autoConfiguration(),
- PropertyPlaceholderAutoConfiguration.class))
- .withUserConfiguration(testConfiguration())
- .withPropertyValues("spring.datasource.initialization-mode=never",
- "spring.datasource.url=jdbc:h2:mem:testdb-baz", "spring.datasource.hikari.pool-name=test")
- .withClassLoader(new FilteredClassLoader("net.ttddyy.dsproxy"));
-
- @Override
- ApplicationContextRunner parentContextRunner() {
- return this.contextRunner;
- }
-
- @Test
- void testShouldUsePlaceholderInSqlTagOfSpansForPreparedStatementIfIncludeParameterValuesIsSetToFalse() {
- contextRunner.withPropertyValues("spring.sleuth.jdbc.p6spy.tracing.include-parameter-values=false")
- .run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- PreparedStatement preparedStatement = connection
- .prepareStatement("UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = ? WHERE 0 = ?");
- preparedStatement.setString(1, "");
- preparedStatement.setInt(2, 1);
- preparedStatement.executeUpdate();
- connection.close();
-
- assertThat(spanReporter.spans()).hasSize(2);
- MutableSpan connectionSpan = spanReporter.spans().get(1);
- MutableSpan statementSpan = spanReporter.spans().get(0);
- assertThat(connectionSpan.name()).isEqualTo("connection");
- assertThat(statementSpan.name()).isEqualTo("update");
- assertThat(statementSpan.tags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
- "UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = ? WHERE 0 = ?");
- assertThat(statementSpan.tags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "0");
- });
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.instrument.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+
+import javax.sql.DataSource;
+
+import brave.handler.MutableSpan;
+import brave.test.TestSpanHandler;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.autoconfig.instrument.jdbc.TraceJdbcAutoConfiguration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public abstract class TracingJdbcEventListenerTests extends TracingListenerStrategyTests {
+
+ protected final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
+ TraceJdbcAutoConfiguration.class, autoConfiguration(), PropertyPlaceholderAutoConfiguration.class))
+ .withUserConfiguration(testConfiguration())
+ .withPropertyValues("spring.datasource.initialization-mode=never",
+ "spring.datasource.url=jdbc:h2:mem:testdb-baz", "spring.datasource.hikari.pool-name=test")
+ .withClassLoader(new FilteredClassLoader("net.ttddyy.dsproxy"));
+
+ @Override
+ ApplicationContextRunner parentContextRunner() {
+ return this.contextRunner;
+ }
+
+ @Test
+ void testShouldUsePlaceholderInSqlTagOfSpansForPreparedStatementIfIncludeParameterValuesIsSetToFalse() {
+ contextRunner.withPropertyValues("spring.sleuth.jdbc.p6spy.tracing.include-parameter-values=false")
+ .run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ PreparedStatement preparedStatement = connection
+ .prepareStatement("UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = ? WHERE 0 = ?");
+ preparedStatement.setString(1, "");
+ preparedStatement.setInt(2, 1);
+ preparedStatement.executeUpdate();
+ connection.close();
+
+ assertThat(spanReporter.spans()).hasSize(2);
+ MutableSpan connectionSpan = spanReporter.spans().get(1);
+ MutableSpan statementSpan = spanReporter.spans().get(0);
+ assertThat(connectionSpan.name()).isEqualTo("connection");
+ assertThat(statementSpan.name()).isEqualTo("update");
+ assertThat(statementSpan.tags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
+ "UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = ? WHERE 0 = ?");
+ assertThat(statementSpan.tags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "0");
+ });
+ }
+
+}
diff --git a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingListenerStrategyTests.java b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingListenerStrategyTests.java
index de201d45d..a598e9504 100644
--- a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingListenerStrategyTests.java
+++ b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingListenerStrategyTests.java
@@ -1,743 +1,744 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.instrument.jdbc;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-import javax.sql.DataSource;
-
-import com.zaxxer.hikari.HikariDataSource;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.exporter.FinishedSpan;
-import org.springframework.cloud.sleuth.test.TestSpanHandler;
-import org.springframework.context.annotation.Bean;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-abstract class TracingListenerStrategyTests {
-
- public static final String SPAN_SQL_QUERY_TAG_NAME = "jdbc.query";
-
- public static final String SPAN_ROW_COUNT_TAG_NAME = "jdbc.row-count";
-
- abstract ApplicationContextRunner parentContextRunner();
-
- protected abstract Class autoConfiguration();
-
- protected abstract Class testConfiguration();
-
- @Test
- void testShouldAddSpanForConnection() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- connection.commit();
- connection.rollback();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(1);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(connectionSpan.getRemoteServiceName()).isEqualTo("TESTDB-BAZ");
- assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.commit");
- assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.rollback");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldAddSpanForConnectionWithFixedRemoteServiceName() {
- parentContextRunner().withPropertyValues("spring.datasource.url:jdbc:h2:mem:testdb-baz?sleuthServiceName=aaaabbbb")
- .run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- connection.commit();
- connection.rollback();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(1);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(connectionSpan.getRemoteServiceName()).isEqualTo("aaaabbbb");
- assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.commit");
- assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.rollback");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldAddSpanForPreparedStatementExecute() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- connection.prepareStatement("SELECT NOW()").execute();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(statementSpan.getRemoteServiceName()).isEqualTo("TESTDB-BAZ");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldAddSpanForPreparedStatementExecuteUpdate() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- connection.prepareStatement("UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1")
- .executeUpdate();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("update");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
- "UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "0");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldAddSpanForStatementExecuteUpdate() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- connection.createStatement()
- .executeUpdate("UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1");
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("update");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
- "UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "0");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldAddSpanForPreparedStatementExecuteQueryIncludingTimeToCloseResultSet() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- ResultSet resultSet = connection.prepareStatement("SELECT NOW() UNION ALL select NOW()").executeQuery();
- resultSet.next();
- resultSet.next();
- resultSet.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
- "SELECT NOW() UNION ALL select NOW()");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(resultSetSpan.getRemoteServiceName()).isEqualTo("TESTDB-BAZ");
- if (isP6Spy(context)) {
- assertThat(resultSetSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "2");
- }
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldAddSpanForStatementAndResultSet() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- ResultSet resultSet = connection.createStatement().executeQuery("SELECT NOW()");
- resultSet.next();
- Thread.sleep(200L);
- resultSet.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- if (isP6Spy(context)) {
- assertThat(resultSetSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "1");
- }
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenStatementIsClosedWihoutResultSet() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- resultSet.next();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenConnectionIsClosedWihoutResultSet() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- resultSet.next();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenResultSetNextWasNotCalled() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenResourceIsAlreadyClosed() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- resultSet.next();
- resultSet.close();
- resultSet.close();
- statement.close();
- statement.close();
- connection.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenResourceIsAlreadyClosed2() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- assertThatThrownBy(() -> {
- connection.close();
- connection.prepareStatement("SELECT NOW()");
- }).isInstanceOf(SQLException.class);
-
- assertThat(spanReporter.reportedSpans()).hasSize(1);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenResourceIsAlreadyClosed3() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- assertThatThrownBy(() -> {
- statement.close();
- statement.executeQuery("SELECT NOW()");
- }).isInstanceOf(SQLException.class);
- connection.close();
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenResourceIsAlreadyClosed4() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- assertThatThrownBy(() -> {
- resultSet.close();
- resultSet.next();
- }).isInstanceOf(SQLException.class);
- statement.close();
- connection.close();
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailToCloseSpanForTwoConsecutiveConnections() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection1 = dataSource.getConnection();
- Connection connection2 = dataSource.getConnection();
- connection2.close();
- connection1.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan connection1Span = spanReporter.reportedSpans().get(0);
- FinishedSpan connection2Span = spanReporter.reportedSpans().get(1);
- assertThat(connection1Span.getName()).isEqualTo("connection");
- assertThat(connection2Span.getName()).isEqualTo("connection");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenClosedInReversedOrder() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- resultSet.next();
- connection.close();
- statement.close();
- resultSet.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- @SuppressWarnings("unchecked")
- void testShouldNotCauseMemoryLeakOnTomcatPool() {
- parentContextRunner().withPropertyValues("spring.datasource.type:org.apache.tomcat.jdbc.pool.DataSource")
- .run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- Object listener = isP6Spy(context) ? context.getBean(TraceJdbcEventListener.class)
- : context.getBean(TraceQueryExecutionListener.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(listener).extracting("strategy").extracting("openConnections")
- .isInstanceOfSatisfying(Map.class, map -> assertThat(map).isEmpty());
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- private boolean isP6Spy(AssertableApplicationContext context) {
- if (context.getBeansOfType(TraceJdbcEventListener.class).size() == 1) {
- return true;
- }
- else if (context.getBeansOfType(TraceQueryExecutionListener.class).size() == 1) {
- return false;
- }
- else {
- throw new IllegalStateException("Expected exactly 1 tracing listener bean in the context.");
- }
- }
-
- @Test
- void testSingleConnectionAcrossMultipleThreads() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- IntStream.range(0, 5).mapToObj(i -> CompletableFuture.runAsync(() -> {
- try {
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- resultSet.next();
- statement.close();
- resultSet.close();
- }
- catch (SQLException e) {
- throw new IllegalStateException(e);
- }
- })).collect(Collectors.toList()).forEach(CompletableFuture::join);
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(1 + 2 * 5);
- assertThat(spanReporter.reportedSpans()).extracting("name").contains("select", "result-set", "connection");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldIncludeOnlyConnectionTraces() {
- parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: connection").run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(1);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldIncludeOnlyQueryTraces() {
- parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: query").run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldIncludeOnlyFetchTraces() {
- parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: fetch").run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(1);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(0);
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldIncludeOnlyConnectionAndQueryTraces() {
- parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: connection, query").run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldIncludeOnlyConnectionAndFetchTraces() {
- parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: connection, fetch").run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldIncludeOnlyQueryAndFetchTraces() {
- parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: query, fetch").run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
- resultSet.next();
- resultSet.close();
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotOverrideExceptionWhenConnectionWasClosedBeforeExecutingQuery() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- PreparedStatement statement = connection.prepareStatement("SELECT NOW()");
- connection.close();
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
-
- assertThatThrownBy(statement::executeQuery).isInstanceOf(SQLException.class);
-
- assertThat(spanReporter.reportedSpans()).hasSize(1);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotOverrideExceptionWhenStatementWasClosedBeforeExecutingQuery() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- PreparedStatement statement = connection.prepareStatement("SELECT NOW()");
- statement.close();
- assertThatThrownBy(statement::executeQuery).isInstanceOf(SQLException.class);
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(2);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotOverrideExceptionWhenResultSetWasClosedBeforeNext() {
- parentContextRunner().run(context -> {
- DataSource dataSource = context.getBean(DataSource.class);
- TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
-
- Connection connection = dataSource.getConnection();
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("SELECT NOW()");
- resultSet.close();
- assertThatThrownBy(resultSet::next).isInstanceOf(SQLException.class);
- statement.close();
- connection.close();
-
- assertThat(spanReporter.reportedSpans()).hasSize(3);
- FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
- FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
- FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
- assertThat(connectionSpan.getName()).isEqualTo("connection");
- assertThat(statementSpan.getName()).isEqualTo("select");
- assertThat(resultSetSpan.getName()).isEqualTo("result-set");
- assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
- assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
- });
- }
-
- @Test
- void testShouldNotFailWhenClosingConnectionFromDifferentDataSource() {
- ApplicationContextRunner contextRunner = parentContextRunner()
- .withUserConfiguration(MultiDataSourceConfiguration.class);
-
- contextRunner.run(context -> {
- DataSource dataSource1 = context.getBean("test1", DataSource.class);
- DataSource dataSource2 = context.getBean("test2", DataSource.class);
-
- dataSource1.getConnection().close();
- dataSource2.getConnection().close();
-
- CompletableFuture future = CompletableFuture.runAsync(() -> {
- try {
- Connection connection1 = dataSource1.getConnection();
- PreparedStatement statement = connection1.prepareStatement("SELECT NOW()");
- ResultSet resultSet = statement.executeQuery();
- Thread.sleep(200);
- resultSet.close();
- statement.close();
- connection1.close();
- }
- catch (SQLException | InterruptedException e) {
- throw new IllegalStateException(e);
- }
- });
- Thread.sleep(100);
- Connection connection2 = dataSource2.getConnection();
- Thread.sleep(300);
- connection2.close();
-
- future.join();
- });
- }
-
- private static class MultiDataSourceConfiguration {
-
- @Bean
- public HikariDataSource test1() {
- HikariDataSource dataSource = new HikariDataSource();
- dataSource.setJdbcUrl("jdbc:h2:mem:testdb-1-foo");
- dataSource.setPoolName("test1");
- return dataSource;
- }
-
- @Bean
- public HikariDataSource test2() {
- HikariDataSource dataSource = new HikariDataSource();
- dataSource.setJdbcUrl("jdbc:h2:mem:testdb-2-bar");
- dataSource.setPoolName("test2");
- return dataSource;
- }
-
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.instrument.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.sql.DataSource;
+
+import com.zaxxer.hikari.HikariDataSource;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.exporter.FinishedSpan;
+import org.springframework.cloud.sleuth.test.TestSpanHandler;
+import org.springframework.context.annotation.Bean;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+abstract class TracingListenerStrategyTests {
+
+ public static final String SPAN_SQL_QUERY_TAG_NAME = "jdbc.query";
+
+ public static final String SPAN_ROW_COUNT_TAG_NAME = "jdbc.row-count";
+
+ abstract ApplicationContextRunner parentContextRunner();
+
+ protected abstract Class autoConfiguration();
+
+ protected abstract Class testConfiguration();
+
+ @Test
+ void testShouldAddSpanForConnection() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ connection.commit();
+ connection.rollback();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(connectionSpan.getRemoteServiceName()).isEqualTo("TESTDB-BAZ");
+ assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.commit");
+ assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.rollback");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldAddSpanForConnectionWithFixedRemoteServiceName() {
+ parentContextRunner()
+ .withPropertyValues("spring.datasource.url:jdbc:h2:mem:testdb-baz?sleuthServiceName=aaaabbbb")
+ .run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ connection.commit();
+ connection.rollback();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(connectionSpan.getRemoteServiceName()).isEqualTo("aaaabbbb");
+ assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.commit");
+ assertThat(connectionSpan.getEvents()).extracting("value").contains("jdbc.rollback");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldAddSpanForPreparedStatementExecute() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ connection.prepareStatement("SELECT NOW()").execute();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(statementSpan.getRemoteServiceName()).isEqualTo("TESTDB-BAZ");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldAddSpanForPreparedStatementExecuteUpdate() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ connection.prepareStatement("UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1")
+ .executeUpdate();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("update");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
+ "UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "0");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldAddSpanForStatementExecuteUpdate() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ connection.createStatement()
+ .executeUpdate("UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1");
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("update");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
+ "UPDATE INFORMATION_SCHEMA.TABLES SET table_Name = '' WHERE 0 = 1");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "0");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldAddSpanForPreparedStatementExecuteQueryIncludingTimeToCloseResultSet() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ ResultSet resultSet = connection.prepareStatement("SELECT NOW() UNION ALL select NOW()").executeQuery();
+ resultSet.next();
+ resultSet.next();
+ resultSet.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME,
+ "SELECT NOW() UNION ALL select NOW()");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(resultSetSpan.getRemoteServiceName()).isEqualTo("TESTDB-BAZ");
+ if (isP6Spy(context)) {
+ assertThat(resultSetSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "2");
+ }
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldAddSpanForStatementAndResultSet() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ ResultSet resultSet = connection.createStatement().executeQuery("SELECT NOW()");
+ resultSet.next();
+ Thread.sleep(200L);
+ resultSet.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ if (isP6Spy(context)) {
+ assertThat(resultSetSpan.getTags()).containsEntry(SPAN_ROW_COUNT_TAG_NAME, "1");
+ }
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenStatementIsClosedWihoutResultSet() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ resultSet.next();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenConnectionIsClosedWihoutResultSet() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ resultSet.next();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenResultSetNextWasNotCalled() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenResourceIsAlreadyClosed() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ resultSet.next();
+ resultSet.close();
+ resultSet.close();
+ statement.close();
+ statement.close();
+ connection.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenResourceIsAlreadyClosed2() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ assertThatThrownBy(() -> {
+ connection.close();
+ connection.prepareStatement("SELECT NOW()");
+ }).isInstanceOf(SQLException.class);
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenResourceIsAlreadyClosed3() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ assertThatThrownBy(() -> {
+ statement.close();
+ statement.executeQuery("SELECT NOW()");
+ }).isInstanceOf(SQLException.class);
+ connection.close();
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenResourceIsAlreadyClosed4() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ assertThatThrownBy(() -> {
+ resultSet.close();
+ resultSet.next();
+ }).isInstanceOf(SQLException.class);
+ statement.close();
+ connection.close();
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailToCloseSpanForTwoConsecutiveConnections() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection1 = dataSource.getConnection();
+ Connection connection2 = dataSource.getConnection();
+ connection2.close();
+ connection1.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan connection1Span = spanReporter.reportedSpans().get(0);
+ FinishedSpan connection2Span = spanReporter.reportedSpans().get(1);
+ assertThat(connection1Span.getName()).isEqualTo("connection");
+ assertThat(connection2Span.getName()).isEqualTo("connection");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenClosedInReversedOrder() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ resultSet.next();
+ connection.close();
+ statement.close();
+ resultSet.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ void testShouldNotCauseMemoryLeakOnTomcatPool() {
+ parentContextRunner().withPropertyValues("spring.datasource.type:org.apache.tomcat.jdbc.pool.DataSource")
+ .run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ Object listener = isP6Spy(context) ? context.getBean(TraceJdbcEventListener.class)
+ : context.getBean(TraceQueryExecutionListener.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(listener).extracting("strategy").extracting("openConnections")
+ .isInstanceOfSatisfying(Map.class, map -> assertThat(map).isEmpty());
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ private boolean isP6Spy(AssertableApplicationContext context) {
+ if (context.getBeansOfType(TraceJdbcEventListener.class).size() == 1) {
+ return true;
+ }
+ else if (context.getBeansOfType(TraceQueryExecutionListener.class).size() == 1) {
+ return false;
+ }
+ else {
+ throw new IllegalStateException("Expected exactly 1 tracing listener bean in the context.");
+ }
+ }
+
+ @Test
+ void testSingleConnectionAcrossMultipleThreads() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ IntStream.range(0, 5).mapToObj(i -> CompletableFuture.runAsync(() -> {
+ try {
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ resultSet.next();
+ statement.close();
+ resultSet.close();
+ }
+ catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ })).collect(Collectors.toList()).forEach(CompletableFuture::join);
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1 + 2 * 5);
+ assertThat(spanReporter.reportedSpans()).extracting("name").contains("select", "result-set", "connection");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldIncludeOnlyConnectionTraces() {
+ parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: connection").run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldIncludeOnlyQueryTraces() {
+ parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: query").run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldIncludeOnlyFetchTraces() {
+ parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: fetch").run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(0);
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldIncludeOnlyConnectionAndQueryTraces() {
+ parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: connection, query").run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldIncludeOnlyConnectionAndFetchTraces() {
+ parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: connection, fetch").run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldIncludeOnlyQueryAndFetchTraces() {
+ parentContextRunner().withPropertyValues("spring.sleuth.jdbc.includes: query, fetch").run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select 1 FROM dual");
+ resultSet.next();
+ resultSet.close();
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotOverrideExceptionWhenConnectionWasClosedBeforeExecutingQuery() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ PreparedStatement statement = connection.prepareStatement("SELECT NOW()");
+ connection.close();
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+
+ assertThatThrownBy(statement::executeQuery).isInstanceOf(SQLException.class);
+
+ assertThat(spanReporter.reportedSpans()).hasSize(1);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotOverrideExceptionWhenStatementWasClosedBeforeExecutingQuery() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ PreparedStatement statement = connection.prepareStatement("SELECT NOW()");
+ statement.close();
+ assertThatThrownBy(statement::executeQuery).isInstanceOf(SQLException.class);
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(2);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotOverrideExceptionWhenResultSetWasClosedBeforeNext() {
+ parentContextRunner().run(context -> {
+ DataSource dataSource = context.getBean(DataSource.class);
+ TestSpanHandler spanReporter = context.getBean(TestSpanHandler.class);
+
+ Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SELECT NOW()");
+ resultSet.close();
+ assertThatThrownBy(resultSet::next).isInstanceOf(SQLException.class);
+ statement.close();
+ connection.close();
+
+ assertThat(spanReporter.reportedSpans()).hasSize(3);
+ FinishedSpan connectionSpan = spanReporter.reportedSpans().get(2);
+ FinishedSpan resultSetSpan = spanReporter.reportedSpans().get(1);
+ FinishedSpan statementSpan = spanReporter.reportedSpans().get(0);
+ assertThat(connectionSpan.getName()).isEqualTo("connection");
+ assertThat(statementSpan.getName()).isEqualTo("select");
+ assertThat(resultSetSpan.getName()).isEqualTo("result-set");
+ assertThat(statementSpan.getTags()).containsEntry(SPAN_SQL_QUERY_TAG_NAME, "SELECT NOW()");
+ assertThat(context.getBean(Tracer.class).currentSpan()).isNull();
+ });
+ }
+
+ @Test
+ void testShouldNotFailWhenClosingConnectionFromDifferentDataSource() {
+ ApplicationContextRunner contextRunner = parentContextRunner()
+ .withUserConfiguration(MultiDataSourceConfiguration.class);
+
+ contextRunner.run(context -> {
+ DataSource dataSource1 = context.getBean("test1", DataSource.class);
+ DataSource dataSource2 = context.getBean("test2", DataSource.class);
+
+ dataSource1.getConnection().close();
+ dataSource2.getConnection().close();
+
+ CompletableFuture future = CompletableFuture.runAsync(() -> {
+ try {
+ Connection connection1 = dataSource1.getConnection();
+ PreparedStatement statement = connection1.prepareStatement("SELECT NOW()");
+ ResultSet resultSet = statement.executeQuery();
+ Thread.sleep(200);
+ resultSet.close();
+ statement.close();
+ connection1.close();
+ }
+ catch (SQLException | InterruptedException e) {
+ throw new IllegalStateException(e);
+ }
+ });
+ Thread.sleep(100);
+ Connection connection2 = dataSource2.getConnection();
+ Thread.sleep(300);
+ connection2.close();
+
+ future.join();
+ });
+ }
+
+ private static class MultiDataSourceConfiguration {
+
+ @Bean
+ public HikariDataSource test1() {
+ HikariDataSource dataSource = new HikariDataSource();
+ dataSource.setJdbcUrl("jdbc:h2:mem:testdb-1-foo");
+ dataSource.setPoolName("test1");
+ return dataSource;
+ }
+
+ @Bean
+ public HikariDataSource test2() {
+ HikariDataSource dataSource = new HikariDataSource();
+ dataSource.setJdbcUrl("jdbc:h2:mem:testdb-2-bar");
+ dataSource.setPoolName("test2");
+ return dataSource;
+ }
+
+ }
+
+}
diff --git a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingQueryExecutionListenerTests.java b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingQueryExecutionListenerTests.java
index b54480927..6897f4293 100644
--- a/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingQueryExecutionListenerTests.java
+++ b/tests/common/src/main/java/org/springframework/cloud/sleuth/instrument/jdbc/TracingQueryExecutionListenerTests.java
@@ -1,39 +1,40 @@
-/*
- * Copyright 2013-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.sleuth.instrument.jdbc;
-
-import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.test.context.FilteredClassLoader;
-import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.sleuth.autoconfig.instrument.jdbc.TraceJdbcAutoConfiguration;
-
-public abstract class TracingQueryExecutionListenerTests extends TracingListenerStrategyTests {
-
- @Override
- ApplicationContextRunner parentContextRunner() {
- return new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
- TraceJdbcAutoConfiguration.class, autoConfiguration(), PropertyPlaceholderAutoConfiguration.class))
- .withUserConfiguration(testConfiguration())
- .withPropertyValues("spring.datasource.initialization-mode=never",
- "spring.datasource.url:jdbc:h2:mem:testdb-baz", "spring.datasource.hikari.pool-name=test")
- .withClassLoader(new FilteredClassLoader("com.p6spy"));
- }
-
-}
+/*
+ * Copyright 2013-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.instrument.jdbc;
+
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.test.context.FilteredClassLoader;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cloud.sleuth.autoconfig.instrument.jdbc.TraceJdbcAutoConfiguration;
+
+public abstract class TracingQueryExecutionListenerTests extends TracingListenerStrategyTests {
+
+ @Override
+ ApplicationContextRunner parentContextRunner() {
+ return new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(DataSourceAutoConfiguration.class, TraceJdbcAutoConfiguration.class,
+ autoConfiguration(), PropertyPlaceholderAutoConfiguration.class))
+ .withUserConfiguration(testConfiguration())
+ .withPropertyValues("spring.datasource.initialization-mode=never",
+ "spring.datasource.url:jdbc:h2:mem:testdb-baz", "spring.datasource.hikari.pool-name=test")
+ .withClassLoader(new FilteredClassLoader("com.p6spy"));
+ }
+
+}