diff --git a/pom.xml b/pom.xml
index 7b1064f32..3da2a0c29 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,452 +1,460 @@
-
-
-
-
- 4.0.0
-
- spring-cloud-sleuth
- 3.1.0-SNAPSHOT
- pom
- Spring Cloud Sleuth
- Spring Cloud Sleuth
-
-
- org.springframework.cloud
- spring-cloud-build
- 3.0.3-SNAPSHOT
-
-
-
-
-
- https://github.com/spring-cloud/spring-cloud-sleuth
- scm:git:git://github.com/spring-cloud/spring-cloud-sleuth.git
-
-
- scm:git:ssh://git@github.com/spring-cloud/spring-cloud-sleuth.git
-
- HEAD
-
-
-
- spring-cloud-sleuth-dependencies
- spring-cloud-sleuth-api
- spring-cloud-sleuth-instrumentation
- spring-cloud-sleuth-brave
- spring-cloud-sleuth-autoconfigure
- tests
- spring-cloud-sleuth-zipkin
- spring-cloud-starter-sleuth
- spring-cloud-sleuth-samples
- docs
-
-
-
- 1.8
- 1.8
- 1.8
- 1.8
- 3.0.3-SNAPSHOT
- 3.0.3-SNAPSHOT
- 3.0.3-SNAPSHOT
- 3.0.3-SNAPSHOT
- 2.0.2-SNAPSHOT
- 3.1.3-SNAPSHOT
- 3.1.3-SNAPSHOT
- 3.0.3-SNAPSHOT
- 3.0.3-SNAPSHOT
- 2.3.2-SNAPSHOT
- 5.13.2
- 0.32.0
- 2.3.4.RELEASE
- false
- 4.9.0
- 4.8.0
- 20.0
- 1.7.1
- 3.3.0
- 3.0.1
- 2.2.0.RELEASE
-
-
- true
- false
- 3.8.1
- 2.2
- 4.0.3
- 0.21.3
- 0.14.1
- 1.15.3
-
-
-
-
-
-
- maven-compiler-plugin
- 3.8.1
-
-
- default-compile
-
- true
- true
-
- ${maven.compiler.source}
- ${maven.compiler.target}
-
-
-
-
- default-testCompile
-
- true
- true
-
- ${maven.compiler.testSource}
- ${maven.compiler.testTarget}
-
-
-
-
-
-
- maven-enforcer-plugin
- 1.3.1
-
-
- enforce-java
-
- enforce
-
-
-
-
- ${maven.compiler.testTarget}
-
-
-
-
-
-
-
- maven-deploy-plugin
- 2.8.2
-
-
-
-
-
- io.spring.javaformat
- spring-javaformat-maven-plugin
-
-
- maven-checkstyle-plugin
-
-
-
-
-
-
-
- maven-checkstyle-plugin
-
-
- maven-surefire-report-plugin
-
-
-
-
-
-
-
- org.springframework.cloud
- spring-cloud-sleuth-dependencies
- ${project.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-netflix-dependencies
- ${spring-cloud-netflix.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-commons-dependencies
- ${spring-cloud-commons.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-gateway-dependencies
- ${spring-cloud-gateway.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-circuitbreaker-dependencies
- ${spring-cloud-circuitbreaker.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-stream-dependencies
- ${spring-cloud-stream.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-function-dependencies
- ${spring-cloud-function.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-openfeign-dependencies
- ${spring-cloud-openfeign.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-config-dependencies
- ${spring-cloud-config.version}
- pom
- import
-
-
- org.springframework.cloud
- spring-cloud-task-dependencies
- ${spring-cloud-task.version}
- pom
- import
-
-
- org.springframework.security.oauth.boot
- spring-security-oauth2-autoconfigure
- ${spring-security-boot-autoconfigure.version}
- true
-
-
- cglib
- cglib-nodep
- ${cglib-nodep.version}
-
-
- org.objenesis
- objenesis
- ${objenesis.version}
-
-
-
- com.squareup.okhttp3
- mockwebserver
- ${mockwebserver.version}
-
-
- org.springframework.security.oauth
- spring-security-oauth2
- ${spring-security-oauth2.version}
-
-
- io.zipkin.aws
- brave-propagation-aws
- ${brave-propagation-aws.version}
-
-
- org.hamcrest
- hamcrest-core
- ${hamcrest-core.version}
- test
-
-
- org.awaitility
- awaitility
- ${awaitility.version}
- test
-
-
- com.tngtech.archunit
- archunit-junit5
- ${archunit-junit5.version}
-
-
- org.testcontainers
- testcontainers-bom
- ${testcontainers.version}
- pom
- import
-
-
-
-
-
-
- spring
-
-
- spring-snapshots
- Spring Snapshots
- https://repo.spring.io/snapshot
-
- true
-
-
- false
-
-
-
-
- jfrog-snapshots
- JFrog Snapshots
- https://oss.jfrog.org/oss-snapshot-local/
-
- true
-
-
- false
-
-
-
- spring-milestones
- Spring Milestones
- https://repo.spring.io/milestone
-
- false
-
-
-
- spring-releases
- Spring Releases
- https://repo.spring.io/release
-
- false
-
-
-
-
-
- spring-snapshots
- Spring Snapshots
- https://repo.spring.io/snapshot
-
- true
-
-
- false
-
-
-
- spring-milestones
- Spring Milestones
- https://repo.spring.io/milestone
-
- false
-
-
-
- spring-releases
- Spring Releases
- https://repo.spring.io/release
-
- false
-
-
-
-
-
- ide
-
- false
-
-
-
-
- maven-compiler-plugin
-
- ${maven.compiler.testSource}
- ${maven.compiler.testTarget}
-
-
-
-
-
-
- benchmarks
-
- false
-
-
- benchmarks
-
-
-
- sonar
-
-
-
- org.jacoco
- jacoco-maven-plugin
-
-
- pre-unit-test
-
- prepare-agent
-
-
- surefireArgLine
- ${project.build.directory}/jacoco.exec
-
-
-
-
- post-unit-test
- test
-
- report
-
-
-
- ${project.build.directory}/jacoco.exec
-
-
-
-
-
-
- maven-surefire-plugin
-
-
- ${surefireArgLine}
-
-
-
-
-
-
-
-
+
+
+
+
+ 4.0.0
+
+ spring-cloud-sleuth
+ 3.1.0-SNAPSHOT
+ pom
+ Spring Cloud Sleuth
+ Spring Cloud Sleuth
+
+
+ org.springframework.cloud
+ spring-cloud-build
+ 3.0.3-SNAPSHOT
+
+
+
+
+
+ https://github.com/spring-cloud/spring-cloud-sleuth
+ scm:git:git://github.com/spring-cloud/spring-cloud-sleuth.git
+
+
+ scm:git:ssh://git@github.com/spring-cloud/spring-cloud-sleuth.git
+
+ HEAD
+
+
+
+ spring-cloud-sleuth-dependencies
+ spring-cloud-sleuth-api
+ spring-cloud-sleuth-instrumentation
+ spring-cloud-sleuth-brave
+ spring-cloud-sleuth-autoconfigure
+ tests
+ spring-cloud-sleuth-zipkin
+ spring-cloud-starter-sleuth
+ spring-cloud-sleuth-samples
+ docs
+
+
+
+ 1.8
+ 1.8
+ 1.8
+ 1.8
+ 3.0.3-SNAPSHOT
+ 3.0.3-SNAPSHOT
+ 3.0.3-SNAPSHOT
+ 3.0.3-SNAPSHOT
+ 2.0.2-SNAPSHOT
+ 3.1.3-SNAPSHOT
+ 3.1.3-SNAPSHOT
+ 3.0.3-SNAPSHOT
+ 3.0.3-SNAPSHOT
+ 2.3.2-SNAPSHOT
+ 2.5.1
+ 5.13.2
+ 0.32.0
+ 2.3.4.RELEASE
+ false
+ 4.9.0
+ 4.8.0
+ 20.0
+ 1.7.1
+ 3.3.0
+ 3.0.1
+ 2.2.0.RELEASE
+
+
+ true
+ false
+ 3.8.1
+ 2.2
+ 4.0.3
+ 0.21.3
+ 0.14.1
+ 1.15.3
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.8.1
+
+
+ default-compile
+
+ true
+ true
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+
+ default-testCompile
+
+ true
+ true
+
+ ${maven.compiler.testSource}
+ ${maven.compiler.testTarget}
+
+
+
+
+
+
+ maven-enforcer-plugin
+ 1.3.1
+
+
+ enforce-java
+
+ enforce
+
+
+
+
+ ${maven.compiler.testTarget}
+
+
+
+
+
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+
+
+ io.spring.javaformat
+ spring-javaformat-maven-plugin
+
+
+ maven-checkstyle-plugin
+
+
+
+
+
+
+
+ maven-checkstyle-plugin
+
+
+ maven-surefire-report-plugin
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-sleuth-dependencies
+ ${project.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-netflix-dependencies
+ ${spring-cloud-netflix.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-commons-dependencies
+ ${spring-cloud-commons.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-gateway-dependencies
+ ${spring-cloud-gateway.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-circuitbreaker-dependencies
+ ${spring-cloud-circuitbreaker.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-stream-dependencies
+ ${spring-cloud-stream.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-function-dependencies
+ ${spring-cloud-function.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-openfeign-dependencies
+ ${spring-cloud-openfeign.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-config-dependencies
+ ${spring-cloud-config.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-task-dependencies
+ ${spring-cloud-task.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-dependencies
+ ${spring-cloud-deployer.version}
+ import
+ pom
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ ${spring-security-boot-autoconfigure.version}
+ true
+
+
+ cglib
+ cglib-nodep
+ ${cglib-nodep.version}
+
+
+ org.objenesis
+ objenesis
+ ${objenesis.version}
+
+
+
+ com.squareup.okhttp3
+ mockwebserver
+ ${mockwebserver.version}
+
+
+ org.springframework.security.oauth
+ spring-security-oauth2
+ ${spring-security-oauth2.version}
+
+
+ io.zipkin.aws
+ brave-propagation-aws
+ ${brave-propagation-aws.version}
+
+
+ org.hamcrest
+ hamcrest-core
+ ${hamcrest-core.version}
+ test
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
+
+ com.tngtech.archunit
+ archunit-junit5
+ ${archunit-junit5.version}
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+
+
+
+
+ spring
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+ false
+
+
+
+
+ jfrog-snapshots
+ JFrog Snapshots
+ https://oss.jfrog.org/oss-snapshot-local/
+
+ true
+
+
+ false
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+ spring-releases
+ Spring Releases
+ https://repo.spring.io/release
+
+ false
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+ false
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+ spring-releases
+ Spring Releases
+ https://repo.spring.io/release
+
+ false
+
+
+
+
+
+ ide
+
+ false
+
+
+
+
+ maven-compiler-plugin
+
+ ${maven.compiler.testSource}
+ ${maven.compiler.testTarget}
+
+
+
+
+
+
+ benchmarks
+
+ false
+
+
+ benchmarks
+
+
+
+ sonar
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ pre-unit-test
+
+ prepare-agent
+
+
+ surefireArgLine
+ ${project.build.directory}/jacoco.exec
+
+
+
+
+ post-unit-test
+ test
+
+ report
+
+
+
+ ${project.build.directory}/jacoco.exec
+
+
+
+
+
+
+ maven-surefire-plugin
+
+
+ ${surefireArgLine}
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-sleuth-autoconfigure/pom.xml b/spring-cloud-sleuth-autoconfigure/pom.xml
index ac237bbf7..994f00cd4 100644
--- a/spring-cloud-sleuth-autoconfigure/pom.xml
+++ b/spring-cloud-sleuth-autoconfigure/pom.xml
@@ -1,450 +1,455 @@
-
-
-
-
- 4.0.0
-
- spring-cloud-sleuth-autoconfigure
- jar
- Spring Cloud Sleuth AutoConfigure
- Spring Cloud Sleuth AutoConfigure
-
-
- org.springframework.cloud
- spring-cloud-sleuth
- 3.1.0-SNAPSHOT
- ..
-
-
-
-
-
- org.springframework.cloud
- spring-cloud-sleuth-instrumentation
-
-
- org.springframework.boot
- spring-boot-starter-web
- true
-
-
- io.micrometer
- micrometer-core
- true
-
-
- io.projectreactor
- reactor-core
- true
-
-
- org.reactivestreams
- reactive-streams
- true
-
-
- org.springframework.boot
- spring-boot-configuration-processor
- true
-
-
- org.springframework.boot
- spring-boot-starter-actuator
- true
-
-
- org.springframework.integration
- spring-integration-core
- true
-
-
- org.springframework.cloud
- spring-cloud-config-server
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-config
- true
-
-
- org.springframework.cloud
- spring-cloud-function-context
- true
-
-
- org.springframework.boot
- spring-boot-starter-websocket
- true
-
-
- org.springframework.cloud
- spring-cloud-stream
-
- ${spring-cloud-stream.version}
- true
-
-
- org.springframework.cloud
- spring-cloud-commons
-
-
- org.springframework
- spring-context
-
-
- org.springframework.cloud
- spring-cloud-context
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-task
- true
-
-
- io.reactivex
- rxjava
- true
-
-
- io.github.openfeign
- feign-okhttp
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-openfeign
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-loadbalancer
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-gateway
- true
-
-
- org.aspectj
- aspectjrt
-
-
-
- org.springframework.boot
- spring-boot-starter-quartz
- true
-
-
- org.springframework.boot
- spring-boot-autoconfigure-processor
- true
-
-
- org.springframework.security.oauth
- spring-security-oauth2
- true
-
-
- org.springframework.security.oauth.boot
- spring-security-oauth2-autoconfigure
- true
-
-
-
-
- org.springframework.cloud
- spring-cloud-sleuth-brave
- true
-
-
- io.zipkin.brave
- brave
-
-
- io.zipkin.reporter2
- *
-
-
- io.zipkin.zipkin2
- *
-
-
- true
-
-
- io.zipkin.brave
- brave-context-slf4j
- true
-
-
- io.zipkin.brave
- brave-instrumentation-messaging
- true
-
-
- io.zipkin.brave
- brave-instrumentation-rpc
- true
-
-
- io.zipkin.brave
- brave-instrumentation-spring-rabbit
- true
-
-
- io.zipkin.brave
- brave-instrumentation-kafka-clients
- true
-
-
- io.zipkin.brave
- brave-instrumentation-kafka-streams
- true
-
-
- io.zipkin.brave
- brave-instrumentation-httpclient
- true
-
-
- io.zipkin.brave
- brave-instrumentation-httpasyncclient
- true
-
-
- io.zipkin.brave
- brave-instrumentation-jms
- true
-
-
- io.zipkin.brave
- brave-instrumentation-mongodb
- true
-
-
- io.zipkin.aws
- brave-propagation-aws
- true
-
-
- javax.jms
- javax.jms-api
- true
-
-
- io.opentracing.brave
- brave-opentracing
- true
-
-
- org.apache.httpcomponents
- httpasyncclient
- true
-
-
- org.springframework
- spring-jms
- true
-
-
-
- io.github.lognet
- grpc-spring-boot-starter
- true
-
-
- org.springframework.boot
- spring-boot-starter
-
-
-
-
- io.zipkin.brave
- brave-instrumentation-grpc
- true
-
-
- io.zipkin.reporter2
- zipkin-reporter-metrics-micrometer
-
-
- io.micrometer
- micrometer-core
-
-
- true
-
-
-
- io.lettuce
- lettuce-core
- true
-
-
- org.springframework.kafka
- spring-kafka
- true
-
-
- org.apache.kafka
- kafka-streams
- true
-
-
- org.springframework.amqp
- spring-rabbit
- true
-
-
- org.springframework.boot
- spring-boot-starter-data-mongodb
- true
-
-
-
-
- org.springframework.cloud
- spring-cloud-sleuth-zipkin
- true
-
-
- io.zipkin.zipkin2
- zipkin
- true
-
-
- io.zipkin.reporter2
- zipkin-reporter
- true
-
-
- io.zipkin.reporter2
- zipkin-reporter-brave
- true
-
-
- io.zipkin.reporter2
- zipkin-sender-kafka
- true
-
-
-
- org.apache.kafka
- kafka-clients
-
-
-
-
- io.zipkin.reporter2
- zipkin-sender-activemq-client
- true
-
-
- org.apache.activemq
- activemq-client
-
-
-
-
- org.apache.activemq
- activemq-client
- true
-
-
- io.zipkin.reporter2
- zipkin-sender-amqp-client
- true
-
-
-
- com.rabbitmq
- amqp-client
-
-
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.awaitility
- awaitility
- test
-
-
- org.mongodb
- mongodb-driver-reactivestreams
- test
-
-
-
-
- io.zipkin.brave
- brave-instrumentation-http-tests
- test
-
-
- com.squareup.okhttp3
- mockwebserver
- test
-
-
-
-
- com.squareup.okhttp3
- okhttp
-
- 4.8.0
- test
-
-
- com.tngtech.archunit
- archunit-junit5
- test
-
-
-
-
-
-
- fast
-
- false
-
-
-
-
- maven-surefire-plugin
-
- 4
- true
- -Xmx1024m -XX:MaxPermSize=256m
-
-
-
-
-
-
-
-
+
+
+
+
+ 4.0.0
+
+ spring-cloud-sleuth-autoconfigure
+ jar
+ Spring Cloud Sleuth AutoConfigure
+ Spring Cloud Sleuth AutoConfigure
+
+
+ org.springframework.cloud
+ spring-cloud-sleuth
+ 3.1.0-SNAPSHOT
+ ..
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-sleuth-instrumentation
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ true
+
+
+ io.micrometer
+ micrometer-core
+ true
+
+
+ io.projectreactor
+ reactor-core
+ true
+
+
+ org.reactivestreams
+ reactive-streams
+ true
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+ true
+
+
+ org.springframework.integration
+ spring-integration-core
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-function-context
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-stream
+
+ ${spring-cloud-stream.version}
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-commons
+
+
+ org.springframework
+ spring-context
+
+
+ org.springframework.cloud
+ spring-cloud-context
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-task
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-spi
+ true
+
+
+ io.reactivex
+ rxjava
+ true
+
+
+ io.github.openfeign
+ feign-okhttp
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-gateway
+ true
+
+
+ org.aspectj
+ aspectjrt
+
+
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+ true
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure-processor
+ true
+
+
+ org.springframework.security.oauth
+ spring-security-oauth2
+ true
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ true
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-sleuth-brave
+ true
+
+
+ io.zipkin.brave
+ brave
+
+
+ io.zipkin.reporter2
+ *
+
+
+ io.zipkin.zipkin2
+ *
+
+
+ true
+
+
+ io.zipkin.brave
+ brave-context-slf4j
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-messaging
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-rpc
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-spring-rabbit
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-kafka-clients
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-kafka-streams
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-httpclient
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-httpasyncclient
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-jms
+ true
+
+
+ io.zipkin.brave
+ brave-instrumentation-mongodb
+ true
+
+
+ io.zipkin.aws
+ brave-propagation-aws
+ true
+
+
+ javax.jms
+ javax.jms-api
+ true
+
+
+ io.opentracing.brave
+ brave-opentracing
+ true
+
+
+ org.apache.httpcomponents
+ httpasyncclient
+ true
+
+
+ org.springframework
+ spring-jms
+ true
+
+
+
+ io.github.lognet
+ grpc-spring-boot-starter
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+ io.zipkin.brave
+ brave-instrumentation-grpc
+ true
+
+
+ io.zipkin.reporter2
+ zipkin-reporter-metrics-micrometer
+
+
+ io.micrometer
+ micrometer-core
+
+
+ true
+
+
+
+ io.lettuce
+ lettuce-core
+ true
+
+
+ org.springframework.kafka
+ spring-kafka
+ true
+
+
+ org.apache.kafka
+ kafka-streams
+ true
+
+
+ org.springframework.amqp
+ spring-rabbit
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+ true
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-sleuth-zipkin
+ true
+
+
+ io.zipkin.zipkin2
+ zipkin
+ true
+
+
+ io.zipkin.reporter2
+ zipkin-reporter
+ true
+
+
+ io.zipkin.reporter2
+ zipkin-reporter-brave
+ true
+
+
+ io.zipkin.reporter2
+ zipkin-sender-kafka
+ true
+
+
+
+ org.apache.kafka
+ kafka-clients
+
+
+
+
+ io.zipkin.reporter2
+ zipkin-sender-activemq-client
+ true
+
+
+ org.apache.activemq
+ activemq-client
+
+
+
+
+ org.apache.activemq
+ activemq-client
+ true
+
+
+ io.zipkin.reporter2
+ zipkin-sender-amqp-client
+ true
+
+
+
+ com.rabbitmq
+ amqp-client
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+ org.mongodb
+ mongodb-driver-reactivestreams
+ test
+
+
+
+
+ io.zipkin.brave
+ brave-instrumentation-http-tests
+ test
+
+
+ com.squareup.okhttp3
+ mockwebserver
+ test
+
+
+
+
+ com.squareup.okhttp3
+ okhttp
+
+ 4.8.0
+ test
+
+
+ com.tngtech.archunit
+ archunit-junit5
+ test
+
+
+
+
+
+
+ fast
+
+ false
+
+
+
+
+ maven-surefire-plugin
+
+ 4
+ true
+ -Xmx1024m -XX:MaxPermSize=256m
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/deployer/TraceDeployerAutoConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/deployer/TraceDeployerAutoConfiguration.java
new file mode 100644
index 000000000..45b7b577c
--- /dev/null
+++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/deployer/TraceDeployerAutoConfiguration.java
@@ -0,0 +1,52 @@
+/*
+ * 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.deployer;
+
+import org.springframework.beans.factory.BeanFactory;
+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.ConditionalOnProperty;
+import org.springframework.cloud.deployer.spi.app.AppDeployer;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.deployer.TraceAppDeployerBeanPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+/**
+ * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
+ * Auto-configuration} that registers instrumentation for app deployers.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.1.0
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnBean(Tracer.class)
+@ConditionalOnProperty(value = "spring.sleuth.deployer.enabled", matchIfMissing = true)
+@ConditionalOnClass(AppDeployer.class)
+@AutoConfigureAfter(BraveAutoConfiguration.class)
+public class TraceDeployerAutoConfiguration {
+
+ @Bean
+ static TraceAppDeployerBeanPostProcessor traceAppDeployerBeanPostProcessor(BeanFactory beanFactory,
+ Environment environment) {
+ return new TraceAppDeployerBeanPostProcessor(beanFactory, environment);
+ }
+
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index b2ebb1d5a..ec3dadb1b 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -1,147 +1,159 @@
-{
- "properties": [
- {
- "name": "spring.zipkin.kafka.topic",
- "type": "java.lang.String",
- "description": "Name of the Kafka topic where spans should be sent to Zipkin.",
- "defaultValue": "zipkin"
- },
- {
- "name": "spring.zipkin.rabbitmq.queue",
- "type": "java.lang.String",
- "description": "Name of the RabbitMQ queue where spans should be sent to Zipkin.",
- "defaultValue": "zipkin"
- },
- {
- "name": "spring.zipkin.rabbitmq.addresses",
- "type": "java.lang.String",
- "description": "Addresses of the RabbitMQ brokers used to send spans to Zipkin"
- },
- {
- "name": "spring.zipkin.activemq.queue",
- "type": "java.lang.String",
- "description": "Name of the ActiveMQ queue where spans should be sent to Zipkin.",
- "defaultValue": "zipkin"
- },
- {
- "name": "spring.zipkin.activemq.message-max-bytes",
- "type": "java.lang.String",
- "description": "Maximum number of bytes for a given message with spans sent to Zipkin over ActiveMQ.",
- "defaultValue": 100000
- },
- {
- "name": "spring.sleuth.function.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable instrumenting of Spring Cloud Function and Spring Cloud Function based projects (e.g. Spring Cloud Stream).",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.integration.websockets.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing for WebSockets.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.async.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable instrumenting async related components so that the tracing information is passed between threads.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.async.configurer.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable default AsyncConfigurer.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.feign.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable span information propagation when using Feign.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.feign.processor.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable post processor that wraps Feign Context in its tracing representations.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.grpc.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable span information propagation when using GRPC.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.messaging.jms.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing of JMS.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.messaging.rabbit.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing of RabbitMQ.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.messaging.kafka.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing of Kafka.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.messaging.kafka.mapper.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable DefaultKafkaHeaderMapper tracing for Kafka.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.quartz.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing for Quartz.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.mongodb.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing for MongoDb.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.rpc.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing of RPC.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.sampler.refresh.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable refresh scope for sampler.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.web.webclient.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable tracing instrumentation for WebClient.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.integration.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable Spring Integration instrumentation.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.task.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable Spring Cloud Task instrumentation.",
- "defaultValue": true
- },
- {
- "name": "spring.sleuth.config.server.enabled",
- "type": "java.lang.Boolean",
- "description": "Enable Spring Cloud Config Server instrumentation.",
- "defaultValue": true
- }
- ]
-}
+{
+ "properties": [
+ {
+ "name": "spring.zipkin.kafka.topic",
+ "type": "java.lang.String",
+ "description": "Name of the Kafka topic where spans should be sent to Zipkin.",
+ "defaultValue": "zipkin"
+ },
+ {
+ "name": "spring.zipkin.rabbitmq.queue",
+ "type": "java.lang.String",
+ "description": "Name of the RabbitMQ queue where spans should be sent to Zipkin.",
+ "defaultValue": "zipkin"
+ },
+ {
+ "name": "spring.zipkin.rabbitmq.addresses",
+ "type": "java.lang.String",
+ "description": "Addresses of the RabbitMQ brokers used to send spans to Zipkin"
+ },
+ {
+ "name": "spring.zipkin.activemq.queue",
+ "type": "java.lang.String",
+ "description": "Name of the ActiveMQ queue where spans should be sent to Zipkin.",
+ "defaultValue": "zipkin"
+ },
+ {
+ "name": "spring.zipkin.activemq.message-max-bytes",
+ "type": "java.lang.String",
+ "description": "Maximum number of bytes for a given message with spans sent to Zipkin over ActiveMQ.",
+ "defaultValue": 100000
+ },
+ {
+ "name": "spring.sleuth.function.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable instrumenting of Spring Cloud Function and Spring Cloud Function based projects (e.g. Spring Cloud Stream).",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.integration.websockets.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing for WebSockets.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.async.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable instrumenting async related components so that the tracing information is passed between threads.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.async.configurer.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable default AsyncConfigurer.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.feign.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable span information propagation when using Feign.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.feign.processor.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable post processor that wraps Feign Context in its tracing representations.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.grpc.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable span information propagation when using GRPC.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.messaging.jms.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing of JMS.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.messaging.rabbit.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing of RabbitMQ.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.messaging.kafka.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing of Kafka.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.messaging.kafka.mapper.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable DefaultKafkaHeaderMapper tracing for Kafka.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.quartz.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing for Quartz.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.mongodb.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing for MongoDb.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.rpc.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing of RPC.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.sampler.refresh.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable refresh scope for sampler.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.web.webclient.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable tracing instrumentation for WebClient.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.integration.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable Spring Integration instrumentation.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.task.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable Spring Cloud Task instrumentation.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.deployer.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable Spring Cloud Deployer instrumentation.",
+ "defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.deployer.status-poll-delay",
+ "type": "java.lang.Long",
+ "description": "Default poll delay to retrieve the deployed application status.",
+ "defaultValue": 1000
+ },
+ {
+ "name": "spring.sleuth.config.server.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable Spring Cloud Config Server instrumentation.",
+ "defaultValue": true
+ }
+ ]
+}
diff --git a/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/spring.factories
index d2df0f518..d96b177e0 100644
--- a/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-sleuth-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -1,34 +1,35 @@
-# Auto Configuration
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.springframework.cloud.sleuth.autoconfig.instrument.async.TraceAsyncAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.async.TraceAsyncCustomAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.async.TraceAsyncDefaultAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.config.TraceSpringCloudConfigAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.circuitbreaker.TraceCircuitBreakerAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.rxjava.TraceRxJavaAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.quartz.TraceQuartzAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.task.TraceTaskAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.web.TraceWebAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.web.client.TraceWebClientAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.web.client.feign.TraceFeignClientAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.web.client.TraceWebAsyncClientAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.scheduling.TraceSchedulingAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.reactor.TraceReactorAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceFunctionAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceSpringIntegrationAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceSpringMessagingAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceWebSocketAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.web.client.BraveWebClientAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.rpc.BraveRpcAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.grpc.BraveGrpcAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.messaging.BraveKafkaStreamsAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.messaging.BraveMessagingAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.opentracing.BraveOpentracingAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.redis.BraveRedisAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.brave.instrument.mongodb.BraveMongoDbAutoConfiguration,\
-org.springframework.cloud.sleuth.autoconfig.zipkin2.ZipkinAutoConfiguration
-# Environment Post Processor
-org.springframework.boot.env.EnvironmentPostProcessor=\
-org.springframework.cloud.sleuth.autoconfig.TraceEnvironmentPostProcessor,\
-org.springframework.cloud.sleuth.autoconfig.instrument.web.client.TraceGatewayEnvironmentPostProcessor
\ No newline at end of file
+# Auto Configuration
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.springframework.cloud.sleuth.autoconfig.instrument.async.TraceAsyncAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.async.TraceAsyncCustomAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.async.TraceAsyncDefaultAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.config.TraceSpringCloudConfigAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.circuitbreaker.TraceCircuitBreakerAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.deployer.TraceDeployerAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.rxjava.TraceRxJavaAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.quartz.TraceQuartzAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.task.TraceTaskAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.web.TraceWebAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.web.client.TraceWebClientAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.web.client.feign.TraceFeignClientAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.web.client.TraceWebAsyncClientAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.scheduling.TraceSchedulingAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.reactor.TraceReactorAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceFunctionAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceSpringIntegrationAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceSpringMessagingAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.instrument.messaging.TraceWebSocketAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.web.client.BraveWebClientAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.rpc.BraveRpcAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.grpc.BraveGrpcAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.messaging.BraveKafkaStreamsAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.messaging.BraveMessagingAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.opentracing.BraveOpentracingAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.redis.BraveRedisAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.brave.instrument.mongodb.BraveMongoDbAutoConfiguration,\
+org.springframework.cloud.sleuth.autoconfig.zipkin2.ZipkinAutoConfiguration
+# Environment Post Processor
+org.springframework.boot.env.EnvironmentPostProcessor=\
+org.springframework.cloud.sleuth.autoconfig.TraceEnvironmentPostProcessor,\
+org.springframework.cloud.sleuth.autoconfig.instrument.web.client.TraceGatewayEnvironmentPostProcessor
diff --git a/spring-cloud-sleuth-instrumentation/pom.xml b/spring-cloud-sleuth-instrumentation/pom.xml
index 4793fa853..0dfdf55a4 100644
--- a/spring-cloud-sleuth-instrumentation/pom.xml
+++ b/spring-cloud-sleuth-instrumentation/pom.xml
@@ -1,219 +1,224 @@
-
-
-
-
- 4.0.0
-
- spring-cloud-sleuth-instrumentation
- jar
- Spring Cloud Sleuth Instrumentation
- Spring Cloud Sleuth Instrumentation
-
-
- org.springframework.cloud
- spring-cloud-sleuth
- 3.1.0-SNAPSHOT
- ..
-
-
-
-
- org.springframework.cloud
- spring-cloud-sleuth-api
-
-
- org.springframework.boot
- spring-boot-starter-web
- true
-
-
- io.micrometer
- micrometer-core
- true
-
-
- io.projectreactor
- reactor-core
- true
-
-
- io.projectreactor.kafka
- reactor-kafka
- true
-
-
- org.reactivestreams
- reactive-streams
- true
-
-
- org.springframework.boot
- spring-boot-configuration-processor
- true
-
-
- org.springframework.boot
- spring-boot-starter-actuator
- true
-
-
- org.springframework.integration
- spring-integration-core
- true
-
-
- org.springframework.cloud
- spring-cloud-config-server
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-config
- true
-
-
- org.springframework.cloud
- spring-cloud-function-context
- true
-
-
- org.springframework.boot
- spring-boot-starter-websocket
- true
-
-
- org.springframework.cloud
- spring-cloud-stream
-
- ${spring-cloud-stream.version}
- true
-
-
- org.springframework.cloud
- spring-cloud-commons
-
-
- org.springframework
- spring-context
-
-
- org.springframework.cloud
- spring-cloud-context
- true
-
-
- io.reactivex
- rxjava
- true
-
-
- io.github.openfeign
- feign-okhttp
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-openfeign
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-loadbalancer
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-gateway
- true
-
-
- org.springframework.cloud
- spring-cloud-starter-task
- true
-
-
- org.aspectj
- aspectjrt
-
-
-
- org.springframework.boot
- spring-boot-starter-quartz
- true
-
-
- org.springframework.boot
- spring-boot-autoconfigure-processor
- true
-
-
- org.springframework.security.oauth
- spring-security-oauth2
- true
-
-
- org.springframework.security.oauth.boot
- spring-security-oauth2-autoconfigure
- true
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.awaitility
- awaitility
- test
-
-
- com.tngtech.archunit
- archunit-junit5
- test
-
-
- io.projectreactor
- reactor-test
- test
-
-
-
-
-
- fast
-
- false
-
-
-
-
- maven-surefire-plugin
-
- 4
- true
- -Xmx1024m -XX:MaxPermSize=256m
-
-
-
-
-
-
-
-
+
+
+
+
+ 4.0.0
+
+ spring-cloud-sleuth-instrumentation
+ jar
+ Spring Cloud Sleuth Instrumentation
+ Spring Cloud Sleuth Instrumentation
+
+
+ org.springframework.cloud
+ spring-cloud-sleuth
+ 3.1.0-SNAPSHOT
+ ..
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-sleuth-api
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ true
+
+
+ io.micrometer
+ micrometer-core
+ true
+
+
+ io.projectreactor
+ reactor-core
+ true
+
+
+ io.projectreactor.kafka
+ reactor-kafka
+ true
+
+
+ org.reactivestreams
+ reactive-streams
+ true
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+ true
+
+
+ org.springframework.integration
+ spring-integration-core
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-function-context
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-stream
+
+ ${spring-cloud-stream.version}
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-commons
+
+
+ org.springframework
+ spring-context
+
+
+ org.springframework.cloud
+ spring-cloud-context
+ true
+
+
+ io.reactivex
+ rxjava
+ true
+
+
+ io.github.openfeign
+ feign-okhttp
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-gateway
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-starter-task
+ true
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-spi
+ true
+
+
+ org.aspectj
+ aspectjrt
+
+
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+ true
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure-processor
+ true
+
+
+ org.springframework.security.oauth
+ spring-security-oauth2
+ true
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+ com.tngtech.archunit
+ archunit-junit5
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+
+
+
+ fast
+
+ false
+
+
+
+
+ maven-surefire-plugin
+
+ 4
+ true
+ -Xmx1024m -XX:MaxPermSize=256m
+
+
+
+
+
+
+
+
diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceReactiveCircuitBreaker.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceReactiveCircuitBreaker.java
index b283db6e8..ecf8cce3c 100644
--- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceReactiveCircuitBreaker.java
+++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceReactiveCircuitBreaker.java
@@ -19,22 +19,16 @@ package org.springframework.cloud.sleuth.instrument.circuitbreaker;
import java.util.function.Function;
import java.util.function.Supplier;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
-import reactor.util.context.Context;
import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;
import org.springframework.cloud.sleuth.CurrentTraceContext;
-import org.springframework.cloud.sleuth.Span;
-import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.instrument.reactor.ReactorSleuth;
class TraceReactiveCircuitBreaker implements ReactiveCircuitBreaker {
- private static final Log log = LogFactory.getLog(TraceReactiveCircuitBreaker.class);
-
private final ReactiveCircuitBreaker delegate;
private final Tracer tracer;
@@ -71,68 +65,11 @@ class TraceReactiveCircuitBreaker implements ReactiveCircuitBreaker {
}
private Mono runAndTraceMono(Supplier> mono) {
- return Mono.deferContextual(contextView -> {
- Span span = contextView.get(Span.class);
- Tracer.SpanInScope scope = contextView.get(Tracer.SpanInScope.class);
- return mono.get().doOnError(span::error).doFinally(signalType -> {
- span.end();
- scope.close();
- });
- }).contextWrite(this::enhanceContext);
+ return ReactorSleuth.tracedMono(this.tracer, this.currentTraceContext, "function", mono);
}
private Flux runAndTraceFlux(Supplier> flux) {
- return Flux.deferContextual(contextView -> {
- Span span = contextView.get(Span.class);
- Tracer.SpanInScope scope = contextView.get(Tracer.SpanInScope.class);
- return flux.get().doOnError(span::error).doFinally(signalType -> {
- span.end();
- scope.close();
- });
- }).contextWrite(this::enhanceContext);
- }
-
- private Span spanFromContext(reactor.util.context.Context context) {
- TraceContext traceContext = context.getOrDefault(TraceContext.class, null);
- Span span = null;
- if (traceContext == null) {
- span = context.getOrDefault(Span.class, null);
- }
- if (traceContext == null && span == null) {
- span = this.tracer.nextSpan();
- if (log.isDebugEnabled()) {
- log.debug("There was no previous span in reactor context, created a new one [" + span + "]");
- }
- }
- else if (traceContext != null) {
- // there was a previous span - we create a child one
- try (CurrentTraceContext.Scope scope = this.currentTraceContext.maybeScope(traceContext)) {
- if (log.isDebugEnabled()) {
- log.debug("Found a trace context in reactor context [" + traceContext + "]");
- }
- span = this.tracer.nextSpan();
- if (log.isDebugEnabled()) {
- log.debug("Created a child span [" + span + "]");
- }
- }
- }
- else {
- if (log.isDebugEnabled()) {
- log.debug("Found a span in reactor context [" + span + "]");
- }
- span = this.tracer.nextSpan(span);
- if (log.isDebugEnabled()) {
- log.debug("Created a child span [" + span + "]");
- }
- }
- // TODO: Better name?
- return span.name("function");
- }
-
- private Context enhanceContext(Context context) {
- Span span = spanFromContext(context);
- return context.put(Span.class, span).put(TraceContext.class, span.context()).put(Tracer.SpanInScope.class,
- this.tracer.withSpan(span));
+ return ReactorSleuth.tracedFlux(this.tracer, this.currentTraceContext, "function", flux);
}
}
diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployer.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployer.java
new file mode 100644
index 000000000..4ea4de184
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployer.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2018-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.deployer;
+
+import java.time.Duration;
+import java.util.Arrays;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.cloud.deployer.spi.app.AppDeployer;
+import org.springframework.cloud.deployer.spi.app.AppScaleRequest;
+import org.springframework.cloud.deployer.spi.app.AppStatus;
+import org.springframework.cloud.deployer.spi.app.DeploymentState;
+import org.springframework.cloud.deployer.spi.core.AppDeploymentRequest;
+import org.springframework.cloud.deployer.spi.core.RuntimeEnvironmentInfo;
+import org.springframework.cloud.sleuth.CurrentTraceContext;
+import org.springframework.cloud.sleuth.Span;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.instrument.reactor.ReactorSleuth;
+import org.springframework.core.env.Environment;
+
+/**
+ * Trace representation of an {@link AppDeployer}.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.1.0
+ */
+public class TraceAppDeployer implements AppDeployer {
+
+ private static final Log log = LogFactory.getLog(TraceAppDeployer.class);
+
+ private final AppDeployer delegate;
+
+ private final BeanFactory beanFactory;
+
+ private final Environment environment;
+
+ private Tracer tracer;
+
+ private CurrentTraceContext currentTraceContext;
+
+ private Long pollDelay;
+
+ public TraceAppDeployer(AppDeployer delegate, BeanFactory beanFactory, Environment environment) {
+ this.delegate = delegate;
+ this.beanFactory = beanFactory;
+ this.environment = environment;
+ }
+
+ @Override
+ public String deploy(AppDeploymentRequest request) {
+ Span span = tracer().nextSpan().name("deploy");
+ // TODO: Is this secure to pass?
+ // TODO: Does it make sense?
+ // if (!request.getCommandlineArguments().isEmpty()) {
+ // span.tag("commandlineArguments", request.getCommandlineArguments().toString());
+ // }
+ // if (!request.getDeploymentProperties().isEmpty()) {
+ // span.tag("deploymentProperties", request.getDeploymentProperties().toString());
+ // }
+ try (Tracer.SpanInScope spanInScope = tracer().withSpan(span.start())) {
+ span.event("start");
+ String id = this.delegate.deploy(request);
+ span.tag("id", id);
+ registerListener(span, id);
+ return id;
+ }
+ }
+
+ private void registerListener(Span span, String id) {
+ PreviousAndCurrentStatus previousAndCurrentStatus = new PreviousAndCurrentStatus(span);
+ // @formatter:off
+ this.delegate.statusReactive(id)
+ .map(previousAndCurrentStatus::updateCurrent)
+ .repeatWhen(repeat -> repeat.flatMap(i -> Mono.delay(Duration.ofMillis(pollDelay()))))
+ .takeUntil(PreviousAndCurrentStatus::isFinished)
+ .last()
+ .doOnNext(PreviousAndCurrentStatus::annotateSpan)
+ .doOnError(span::error)
+ // we will close the span in the reactive part
+ .doFinally(signalType -> span.end()).subscribe();
+ // @formatter:on
+ }
+
+ @Override
+ public void undeploy(String id) {
+ Span span = tracer().nextSpan().name("undeploy");
+ span.tag("id", id);
+ try (Tracer.SpanInScope spanInScope = tracer().withSpan(span.start())) {
+ span.event("start");
+ this.delegate.undeploy(id);
+ registerListener(span, id);
+ }
+ finally {
+ span.end();
+ }
+ }
+
+ @Override
+ public AppStatus status(String id) {
+ Span span = tracer().nextSpan().name("status");
+ span.tag("id", id);
+ try (Tracer.SpanInScope spanInScope = tracer().withSpan(span.start())) {
+ return this.delegate.status(id);
+ }
+ finally {
+ span.end();
+ }
+ }
+
+ @Override
+ public Mono statusReactive(String id) {
+ return ReactorSleuth.tracedMono(tracer(), currentTraceContext(), "status",
+ () -> this.delegate.statusReactive(id), span -> span.tag("id", id));
+ }
+
+ @Override
+ public Flux statusesReactive(String... ids) {
+ return ReactorSleuth.tracedFlux(tracer(), currentTraceContext(), "statuses",
+ () -> this.delegate.statusesReactive(ids), span -> span.tag("ids", Arrays.toString(ids)));
+ }
+
+ @Override
+ public RuntimeEnvironmentInfo environmentInfo() {
+ return this.delegate.environmentInfo();
+ }
+
+ @Override
+ public String getLog(String id) {
+ Span span = tracer().nextSpan().name("getLog");
+ span.tag("id", id);
+ try (Tracer.SpanInScope spanInScope = tracer().withSpan(span.start())) {
+ return this.delegate.getLog(id);
+ }
+ finally {
+ span.end();
+ }
+ }
+
+ @Override
+ public void scale(AppScaleRequest appScaleRequest) {
+ Span span = tracer().nextSpan().name("scale");
+ span.tag("deploymentId", appScaleRequest.getDeploymentId());
+ span.tag("count", String.valueOf(appScaleRequest.getCount()));
+ // TODO: Is this secure to pass?
+ // TODO: Does it make sense?
+ // if (appScaleRequest.getProperties().isPresent() &&
+ // !appScaleRequest.getProperties().get().isEmpty()) {
+ // span.tag("properties", appScaleRequest.getProperties().get().toString());
+ // }
+ try (Tracer.SpanInScope spanInScope = tracer().withSpan(span.start())) {
+ this.delegate.scale(appScaleRequest);
+ }
+ finally {
+ span.end();
+ }
+ }
+
+ private Tracer tracer() {
+ if (this.tracer == null) {
+ this.tracer = this.beanFactory.getBean(Tracer.class);
+ }
+ return this.tracer;
+ }
+
+ private CurrentTraceContext currentTraceContext() {
+ if (this.currentTraceContext == null) {
+ this.currentTraceContext = this.beanFactory.getBean(CurrentTraceContext.class);
+ }
+ return this.currentTraceContext;
+ }
+
+ private long pollDelay() {
+ if (this.pollDelay == null) {
+ this.pollDelay = this.environment.getProperty("spring.sleuth.deployer.status-poll-delay", Long.class, 500L);
+ }
+ return this.pollDelay;
+ }
+
+ private static final class PreviousAndCurrentStatus {
+
+ private final Span span;
+
+ private AppStatus current;
+
+ private AppStatus previous;
+
+ private PreviousAndCurrentStatus(Span span) {
+ this.span = span;
+ if (log.isDebugEnabled()) {
+ log.debug("Current span is [" + span + "]");
+ }
+ }
+
+ private PreviousAndCurrentStatus updateCurrent(AppStatus current) {
+ if (log.isTraceEnabled()) {
+ log.trace("State before change: current [" + this.current + "], previous [" + this.previous + "]");
+ }
+ this.previous = this.current;
+ this.current = current;
+ if (log.isTraceEnabled()) {
+ log.trace("State after change: current [" + this.current + "], previous [" + this.previous + "]");
+ }
+ if (statusChanged()) {
+ annotateSpan();
+ }
+ else if (log.isTraceEnabled()) {
+ log.trace("State has not changed, will not annotate the span");
+ }
+ return this;
+ }
+
+ private void annotateSpan() {
+ String name = this.current.getState().name();
+ if (log.isDebugEnabled()) {
+ log.debug("Will annotate its state with [" + name + "]");
+ }
+ this.span.event(name);
+ }
+
+ private boolean statusChanged() {
+ if (this.previous == null && this.current != null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Previous is null, current is not null");
+ }
+ return true;
+ }
+ else if (this.current == null) {
+ throw new IllegalStateException("Current state can't be null");
+ }
+ DeploymentState currentState = this.current.getState();
+ DeploymentState previousState = this.previous.getState();
+ return currentState != previousState;
+ }
+
+ private boolean isFinished() {
+ boolean finished = this.current.getState() == DeploymentState.deployed
+ || this.current.getState() == DeploymentState.undeployed
+ || this.current.getState() == DeploymentState.failed
+ || this.current.getState() == DeploymentState.error
+ || this.current.getState() == DeploymentState.unknown;
+ if (log.isTraceEnabled()) {
+ log.trace("Status is finished [" + finished + "]");
+ }
+ return finished;
+ }
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployerBeanPostProcessor.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployerBeanPostProcessor.java
new file mode 100644
index 000000000..616ba68df
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployerBeanPostProcessor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.deployer;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.cloud.deployer.spi.app.AppDeployer;
+import org.springframework.core.env.Environment;
+
+/**
+ * {@link BeanPostProcessor} to wrap a {@link AppDeployer} instance into its trace
+ * representation.
+ *
+ * @author Marcin Grzejszczak
+ * @since 2.0.0
+ */
+public class TraceAppDeployerBeanPostProcessor implements BeanPostProcessor {
+
+ private final BeanFactory beanFactory;
+
+ private final Environment environment;
+
+ public TraceAppDeployerBeanPostProcessor(BeanFactory beanFactory, Environment environment) {
+ this.beanFactory = beanFactory;
+ this.environment = environment;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) {
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) {
+ if (bean instanceof AppDeployer && !(bean instanceof TraceAppDeployer)) {
+ return new TraceAppDeployer((AppDeployer) bean, this.beanFactory, this.environment);
+ }
+ return bean;
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorHooksHelper.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorHooksHelper.java
index dd759fbbd..135a4be6d 100644
--- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorHooksHelper.java
+++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorHooksHelper.java
@@ -60,13 +60,13 @@ import org.springframework.util.Assert;
* .scan((l, r) -> l + r) // (-)
* .doOnNext(it -> { // (-)
* //log
- * })
+ * })
* .doFirst(() -> { // (-)
* //log
- * })
+ * })
* .doFinally(signalType -> { // (-)
* //log
- * })
+ * })
* .subscribeOn(Schedulers.parallel()) //(+)
* .subscribe();//(*)
* (*) - captures tracing context if it differs from what was captured before at subscription and propagates it.
@@ -84,7 +84,7 @@ import org.springframework.util.Assert;
* .map(it -> ...) // (+) is SYNC but should add hook as previous Processor/operator does not use hooks
* .doOnNext(it -> { // (-) is SYNC no need to wrap
* //log
- * })
+ * })
* .subscribe();
*}
*/
@@ -93,6 +93,7 @@ final class ReactorHooksHelper {
// need a way to determine SYNC sources to not add redundant scope passing decorator
// most of reactor-core SYNC sources are marked with SourceProducer interface
static final Class> sourceProducerClass;
+
static {
Class> c;
try {
diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java
index 82dd63265..dabadd1a3 100644
--- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java
+++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java
@@ -17,8 +17,10 @@
package org.springframework.cloud.sleuth.instrument.reactor;
import java.util.function.BiFunction;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -28,16 +30,20 @@ import org.reactivestreams.Subscription;
import reactor.core.CoreSubscriber;
import reactor.core.Fuseable;
import reactor.core.Scannable;
+import reactor.core.publisher.Flux;
import reactor.core.publisher.Hooks;
+import reactor.core.publisher.Mono;
import reactor.core.publisher.Operators;
-import reactor.util.annotation.Nullable;
import reactor.util.context.Context;
import org.springframework.cloud.sleuth.CurrentTraceContext;
+import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.internal.LazyBean;
import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
/**
* Reactive Span pointcuts factories.
@@ -314,6 +320,132 @@ public abstract class ReactorSleuth {
};
}
+ /**
+ * Wraps the given Mono in a trace representation. Retrieves the span from context,
+ * creates a child span with the given name.
+ * @param tracer - Tracer bean
+ * @param currentTraceContext - CurrentTraceContext bean
+ * @param childSpanName - name of the created child span
+ * @param supplier - supplier of a {@link Mono} to be wrapped in tracing
+ * @param - type returned by the Mono
+ * @param spanCustomizer - customizer for the child span
+ * @return traced Mono
+ */
+ public static Mono tracedMono(@NonNull Tracer tracer, @NonNull CurrentTraceContext currentTraceContext,
+ @NonNull String childSpanName, @NonNull Supplier> supplier,
+ @NonNull Consumer spanCustomizer) {
+ return Mono.deferContextual(contextView -> {
+ Span span = contextView.get(Span.class);
+ spanCustomizer.accept(span);
+ Tracer.SpanInScope scope = contextView.get(Tracer.SpanInScope.class);
+ return supplier.get().doOnError(span::error).doFinally(signalType -> {
+ span.end();
+ scope.close();
+ });
+ }).contextWrite(context -> ReactorSleuth.enhanceContext(tracer, currentTraceContext, context, childSpanName));
+ }
+
+ /**
+ * Wraps the given Mono in a trace representation. Retrieves the span from context,
+ * creates a child span with the given name.
+ * @param tracer - Tracer bean
+ * @param currentTraceContext - CurrentTraceContext bean
+ * @param childSpanName - name of the created child span
+ * @param supplier - supplier of a {@link Mono} to be wrapped in tracing
+ * @param - type returned by the Mono
+ * @return traced Mono
+ */
+ public static Mono tracedMono(@NonNull Tracer tracer, @NonNull CurrentTraceContext currentTraceContext,
+ @NonNull String childSpanName, @NonNull Supplier> supplier) {
+ return tracedMono(tracer, currentTraceContext, childSpanName, supplier, span -> {
+ });
+ }
+
+ /**
+ * Wraps the given Flux in a trace representation. Retrieves the span from context,
+ * creates a child span with the given name.
+ * @param tracer - Tracer bean
+ * @param currentTraceContext - CurrentTraceContext bean
+ * @param childSpanName - name of the created child span
+ * @param supplier - supplier of a {@link Flux} to be wrapped in tracing
+ * @param - type returned by the Flux
+ * @param spanCustomizer - customizer for the child span
+ * @return traced Flux
+ */
+ public static Flux tracedFlux(@NonNull Tracer tracer, @NonNull CurrentTraceContext currentTraceContext,
+ @NonNull String childSpanName, @NonNull Supplier> supplier,
+ @NonNull Consumer spanCustomizer) {
+ return Flux.deferContextual(contextView -> {
+ Span span = contextView.get(Span.class);
+ spanCustomizer.accept(span);
+ Tracer.SpanInScope scope = contextView.get(Tracer.SpanInScope.class);
+ return supplier.get().doOnError(span::error).doFinally(signalType -> {
+ span.end();
+ scope.close();
+ });
+ }).contextWrite(context -> ReactorSleuth.enhanceContext(tracer, currentTraceContext, context, childSpanName));
+ }
+
+ /**
+ * Wraps the given Flux in a trace representation. Retrieves the span from context,
+ * creates a child span with the given name.
+ * @param tracer - Tracer bean
+ * @param currentTraceContext - CurrentTraceContext bean
+ * @param childSpanName - name of the created child span
+ * @param supplier - supplier of a {@link Flux} to be wrapped in tracing
+ * @param - type returned by the Flux
+ * @return traced Flux
+ */
+ public static Flux tracedFlux(@NonNull Tracer tracer, @NonNull CurrentTraceContext currentTraceContext,
+ @NonNull String childSpanName, @NonNull Supplier> supplier) {
+ return tracedFlux(tracer, currentTraceContext, childSpanName, supplier, span -> {
+ });
+ }
+
+ private static Span spanFromContext(Tracer tracer, CurrentTraceContext currentTraceContext,
+ reactor.util.context.Context context, String childSpanName) {
+ TraceContext traceContext = context.getOrDefault(TraceContext.class, null);
+ Span span = null;
+ if (traceContext == null) {
+ span = context.getOrDefault(Span.class, null);
+ }
+ if (traceContext == null && span == null) {
+ span = tracer.nextSpan();
+ if (log.isDebugEnabled()) {
+ log.debug("There was no previous span in reactor context, created a new one [" + span + "]");
+ }
+ }
+ else if (traceContext != null) {
+ // there was a previous span - we create a child one
+ try (CurrentTraceContext.Scope scope = currentTraceContext.maybeScope(traceContext)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Found a trace context in reactor context [" + traceContext + "]");
+ }
+ span = tracer.nextSpan();
+ if (log.isDebugEnabled()) {
+ log.debug("Created a child span [" + span + "]");
+ }
+ }
+ }
+ else {
+ if (log.isDebugEnabled()) {
+ log.debug("Found a span in reactor context [" + span + "]");
+ }
+ span = tracer.nextSpan(span);
+ if (log.isDebugEnabled()) {
+ log.debug("Created a child span [" + span + "]");
+ }
+ }
+ return span.name(childSpanName).start();
+ }
+
+ private static Context enhanceContext(Tracer tracer, CurrentTraceContext currentTraceContext,
+ reactor.util.context.Context context, String childSpanName) {
+ Span span = spanFromContext(tracer, currentTraceContext, context, childSpanName);
+ return context.put(Span.class, span).put(TraceContext.class, span.context()).put(Tracer.SpanInScope.class,
+ tracer.withSpan(span));
+ }
+
}
class SleuthContextOperator implements Subscription, CoreSubscriber, Scannable {
diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpCurrentTraceContext.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpCurrentTraceContext.java
new file mode 100644
index 000000000..394c3eefb
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpCurrentTraceContext.java
@@ -0,0 +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.instrument.deployer;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+
+import org.springframework.cloud.sleuth.CurrentTraceContext;
+import org.springframework.cloud.sleuth.TraceContext;
+
+/**
+ * A noop implementation. Does nothing.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.0.0
+ */
+class NoOpCurrentTraceContext implements CurrentTraceContext {
+
+ @Override
+ public TraceContext context() {
+ return null;
+ }
+
+ @Override
+ public Scope newScope(TraceContext context) {
+ return () -> {
+ };
+ }
+
+ @Override
+ public Scope maybeScope(TraceContext context) {
+ return () -> {
+ };
+ }
+
+ @Override
+ public Callable wrap(Callable task) {
+ return task;
+ }
+
+ @Override
+ public Runnable wrap(Runnable task) {
+ return task;
+ }
+
+ @Override
+ public Executor wrap(Executor delegate) {
+ return delegate;
+ }
+
+ @Override
+ public ExecutorService wrap(ExecutorService delegate) {
+ return delegate;
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpSpanInScope.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpSpanInScope.java
new file mode 100644
index 000000000..d2339918a
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpSpanInScope.java
@@ -0,0 +1,34 @@
+/*
+ * 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.deployer;
+
+import org.springframework.cloud.sleuth.Tracer;
+
+/**
+ * A noop implementation. Does nothing.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.0.0
+ */
+class NoOpSpanInScope implements Tracer.SpanInScope {
+
+ @Override
+ public void close() {
+
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpTraceContext.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpTraceContext.java
new file mode 100644
index 000000000..057b4b41f
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/NoOpTraceContext.java
@@ -0,0 +1,49 @@
+/*
+ * 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.deployer;
+
+import org.springframework.cloud.sleuth.TraceContext;
+
+/**
+ * A noop implementation. Does nothing.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.0.0
+ */
+class NoOpTraceContext implements TraceContext {
+
+ @Override
+ public String traceId() {
+ return "";
+ }
+
+ @Override
+ public String parentId() {
+ return "";
+ }
+
+ @Override
+ public String spanId() {
+ return "";
+ }
+
+ @Override
+ public Boolean sampled() {
+ return false;
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/SimpleSpan.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/SimpleSpan.java
new file mode 100644
index 000000000..86cdfd169
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/SimpleSpan.java
@@ -0,0 +1,91 @@
+/*
+ * 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.deployer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.cloud.sleuth.Span;
+import org.springframework.cloud.sleuth.TraceContext;
+
+/**
+ * A noop implementation. Does nothing.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.0.0
+ */
+class SimpleSpan implements Span {
+
+ Map tags = new HashMap<>();
+
+ boolean started;
+
+ boolean ended;
+
+ @Override
+ public boolean isNoop() {
+ return true;
+ }
+
+ @Override
+ public TraceContext context() {
+ return new NoOpTraceContext();
+ }
+
+ @Override
+ public Span start() {
+ this.started = true;
+ return this;
+ }
+
+ @Override
+ public Span name(String name) {
+ return this;
+ }
+
+ @Override
+ public Span event(String value) {
+ return this;
+ }
+
+ @Override
+ public Span tag(String key, String value) {
+ this.tags.put(key, value);
+ return this;
+ }
+
+ @Override
+ public Span error(Throwable throwable) {
+ return this;
+ }
+
+ @Override
+ public void end() {
+ this.ended = true;
+ }
+
+ @Override
+ public void abandon() {
+
+ }
+
+ @Override
+ public Span remoteServiceName(String remoteServiceName) {
+ return this;
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/SimpleTracer.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/SimpleTracer.java
new file mode 100644
index 000000000..295d2288d
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/SimpleTracer.java
@@ -0,0 +1,113 @@
+/*
+ * 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.deployer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.assertj.core.api.BDDAssertions;
+
+import org.springframework.cloud.sleuth.BaggageInScope;
+import org.springframework.cloud.sleuth.ScopedSpan;
+import org.springframework.cloud.sleuth.Span;
+import org.springframework.cloud.sleuth.SpanCustomizer;
+import org.springframework.cloud.sleuth.TraceContext;
+import org.springframework.cloud.sleuth.Tracer;
+
+/**
+ * A noop implementation. Does nothing.
+ *
+ * @author Marcin Grzejszczak
+ * @since 3.0.0
+ */
+class SimpleTracer implements Tracer {
+
+ List spans = new ArrayList<>();
+
+ @Override
+ public Span nextSpan(Span parent) {
+ return new SimpleSpan();
+ }
+
+ SimpleSpan getOnlySpan() {
+ BDDAssertions.then(this.spans).hasSize(1);
+ SimpleSpan span = this.spans.get(0);
+ BDDAssertions.then(span.started).as("Span must be started").isTrue();
+ BDDAssertions.then(span.ended).as("Span must be finished").isTrue();
+ return span;
+ }
+
+ @Override
+ public SpanInScope withSpan(Span span) {
+ return new NoOpSpanInScope();
+ }
+
+ @Override
+ public SpanCustomizer currentSpanCustomizer() {
+ return null;
+ }
+
+ @Override
+ public Span currentSpan() {
+ return new SimpleSpan();
+ }
+
+ @Override
+ public Span nextSpan() {
+ final SimpleSpan span = new SimpleSpan();
+ this.spans.add(span);
+ return span;
+ }
+
+ @Override
+ public ScopedSpan startScopedSpan(String name) {
+ return null;
+ }
+
+ @Override
+ public Span.Builder spanBuilder() {
+ return null;
+ }
+
+ @Override
+ public Map getAllBaggage() {
+ return new HashMap<>();
+ }
+
+ @Override
+ public BaggageInScope getBaggage(String name) {
+ return null;
+ }
+
+ @Override
+ public BaggageInScope getBaggage(TraceContext traceContext, String name) {
+ return null;
+ }
+
+ @Override
+ public BaggageInScope createBaggage(String name) {
+ return null;
+ }
+
+ @Override
+ public BaggageInScope createBaggage(String name, String value) {
+ return null;
+ }
+
+}
diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployerTests.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployerTests.java
new file mode 100644
index 000000000..c6b50b62e
--- /dev/null
+++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/deployer/TraceAppDeployerTests.java
@@ -0,0 +1,144 @@
+/*
+ * 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.deployer;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.assertj.core.api.BDDAssertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.BDDMockito;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.support.StaticListableBeanFactory;
+import org.springframework.cloud.deployer.spi.app.AppDeployer;
+import org.springframework.cloud.deployer.spi.app.AppScaleRequest;
+import org.springframework.cloud.deployer.spi.app.AppStatus;
+import org.springframework.cloud.deployer.spi.core.AppDefinition;
+import org.springframework.cloud.deployer.spi.core.AppDeploymentRequest;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.PathResource;
+import org.springframework.mock.env.MockEnvironment;
+
+class TraceAppDeployerTests {
+
+ SimpleTracer simpleTracer = new SimpleTracer();
+
+ AppDeployer delegate = BDDMockito.mock(AppDeployer.class);
+
+ TraceAppDeployer traceAppDeployer = new TraceAppDeployer(this.delegate, beanFactory(), environment());
+
+ @Test
+ void should_trace_deploy() {
+ BDDMockito.given(this.delegate.statusReactive(BDDMockito.any()))
+ .willReturn(Mono.just(AppStatus.of("asd").build()));
+
+ this.traceAppDeployer.deploy(deploymentRequest());
+
+ BDDAssertions.then(this.simpleTracer.getOnlySpan().tags).isNotEmpty();
+ BDDMockito.then(this.delegate).should().deploy(BDDMockito.any());
+ }
+
+ @Test
+ void should_trace_undeploy() {
+ BDDMockito.given(this.delegate.statusReactive(BDDMockito.any()))
+ .willReturn(Mono.just(AppStatus.of("asd").build()));
+
+ this.traceAppDeployer.undeploy("asd");
+
+ BDDAssertions.then(this.simpleTracer.getOnlySpan().tags).isNotEmpty();
+ BDDMockito.then(this.delegate).should().undeploy(BDDMockito.any());
+ }
+
+ @Test
+ void should_trace_status() {
+ this.traceAppDeployer.status("asd");
+
+ BDDAssertions.then(this.simpleTracer.getOnlySpan().tags).isNotEmpty();
+ BDDMockito.then(this.delegate).should().status(BDDMockito.any());
+ }
+
+ @Test
+ void should_trace_status_reactive() {
+ BDDMockito.given(this.delegate.statusReactive(BDDMockito.any()))
+ .willReturn(Mono.just(AppStatus.of("asd").build()));
+
+ this.traceAppDeployer.statusReactive("asd").block();
+
+ BDDAssertions.then(this.simpleTracer.getOnlySpan().tags).isNotEmpty();
+ BDDMockito.then(this.delegate).should().statusReactive(BDDMockito.any());
+ }
+
+ @Test
+ void should_trace_statuses_reactive() {
+ BDDMockito.given(this.delegate.statusesReactive(BDDMockito.any()))
+ .willReturn(Flux.just(AppStatus.of("asd").build()));
+
+ this.traceAppDeployer.statusesReactive("asd").blockFirst();
+
+ BDDAssertions.then(this.simpleTracer.getOnlySpan().tags).isNotEmpty();
+ BDDMockito.then(this.delegate).should().statusesReactive(BDDMockito.any());
+ }
+
+ @Test
+ void should_trace_log() {
+ this.traceAppDeployer.getLog("id");
+
+ BDDAssertions.then(this.simpleTracer.getOnlySpan().tags).isNotEmpty();
+ BDDMockito.then(this.delegate).should().getLog(BDDMockito.any());
+ }
+
+ @Test
+ void should_trace_scale() {
+ this.traceAppDeployer.scale(new AppScaleRequest("asd", 2));
+
+ BDDAssertions.then(this.simpleTracer.getOnlySpan().tags).isNotEmpty();
+ BDDMockito.then(this.delegate).should().scale(BDDMockito.any());
+ }
+
+ private AppDeploymentRequest deploymentRequest() {
+ return new AppDeploymentRequest(new AppDefinition("foo", new HashMap<>()), new PathResource("/"),
+ deploymentProps(), commandLineArgs());
+ }
+
+ private List commandLineArgs() {
+ return Arrays.asList("foo=bar1", "baz=bar2");
+ }
+
+ private Map deploymentProps() {
+ Map map = new HashMap<>();
+ map.put("deployment1", "prop1");
+ map.put("deployment2", "prop2");
+ return map;
+ }
+
+ private BeanFactory beanFactory() {
+ StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
+ beanFactory.addBean("tracer", this.simpleTracer);
+ beanFactory.addBean("currentTraceContext", new NoOpCurrentTraceContext());
+ return beanFactory;
+ }
+
+ private Environment environment() {
+ return new MockEnvironment();
+ }
+
+}