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(); + } + +}