├── baggage-consumer ├── README.adoc └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── BaggageConsumerApplication.java ├── baggage-producer ├── README.adoc ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── BaggageProducerApplication.java ├── kafka-consumer ├── README.adoc ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── KafkaConsumerApplication.java ├── kafka-producer ├── README.adoc ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── KafkaProducerApplication.java ├── cassandra ├── README.adoc ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── docker-compose.yml └── src │ ├── main │ ├── resources │ │ └── application.yaml │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ ├── BasicConfiguration.java │ │ ├── CassandraApplication.java │ │ ├── BasicUserRepository.java │ │ └── User.java │ └── test │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── CassandraApplicationTests.java ├── mongodb-reactive ├── README.adoc ├── docker-compose.yml ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ ├── BasicUserRepository.java │ ├── User.java │ └── ReactiveMongoApplication.java ├── cassandra-reactive ├── README.adoc ├── docker-compose.yml ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── src │ ├── main │ ├── resources │ │ └── application.yaml │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ ├── BasicConfiguration.java │ │ ├── ReactiveCassandraApplication.java │ │ ├── BasicUserRepository.java │ │ └── User.java │ └── test │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── ReactiveCassandraApplicationTests.java ├── kafka-reactive-consumer ├── README.adoc ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── KafkaReactiveConsumerApplication.java ├── kafka-reactive-producer ├── README.adoc ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── KafkaReactiveProducerApplication.java ├── acceptance-tests ├── src │ ├── main │ │ └── resources │ │ │ └── application.yaml │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ ├── MongoDbAcceptanceTests.java │ │ ├── VaultAcceptanceTests.java │ │ ├── RedisAcceptanceTests.java │ │ ├── KafkaAcceptanceTests.java │ │ ├── RabbitAcceptanceTests.java │ │ ├── CassandraAcceptanceTests.java │ │ ├── ProjectRebuilder.java │ │ ├── AcceptanceTestsBase.java │ │ └── TracingAssertions.java └── .mvn │ └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── session ├── docker-compose.yml ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── README.adoc └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── SessionApplication.java ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── security ├── src │ └── main │ │ ├── resources │ │ ├── application.yml │ │ └── templates │ │ │ └── index.html │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ ├── SecurityController.java │ │ ├── SpringSecurityApplication.java │ │ └── SecurityConfiguration.java ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── README.adoc ├── bus ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ ├── org │ │ └── springframework │ │ │ └── cloud │ │ │ └── bus │ │ │ └── event │ │ │ └── MyEvent.java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── BusApplication.java └── README.adoc ├── data-reactive ├── src │ └── main │ │ ├── resources │ │ ├── schema.sql │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ ├── ReactiveCustomerRepository.java │ │ ├── ReactiveCustomer.java │ │ ├── ReactiveNestedTransactionService.java │ │ ├── ReactiveContinuedTransactionService.java │ │ ├── ReactiveNewTransactionService.java │ │ └── ReactiveDataApplication.java ├── docker-compose.yml ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties └── README.adoc ├── mvc ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── MvcApplication.java └── README.adoc ├── batch ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── BatchApplication.java └── README.adoc ├── data ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── sleuthsamples │ │ │ ├── CustomerRepository.java │ │ │ ├── Customer.java │ │ │ ├── DataApplication.java │ │ │ ├── NestedTransactionService.java │ │ │ ├── ContinuedTransactionService.java │ │ │ └── NewTransactionService.java │ │ └── resources │ │ └── application.yaml └── README.adoc ├── task ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── SpringCloudTaskApplication.java └── README.adoc ├── deployer ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ └── resources │ │ └── application.yaml └── README.adoc ├── gateway ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── GatewayApplication.java └── README.adoc ├── webflux ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── WebFluxApplication.java └── README.adoc ├── config-server ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.properties │ │ └── maven-wrapper.jar ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── ConfigServerApplication.java └── README.adoc ├── integration ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── SpringIntegrationProducerApplication.java └── README.adoc ├── openfeign ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── OpenFeignApplication.java └── README.adoc ├── webclient ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── WebClientApplication.java └── README.adoc ├── resttemplate ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── RestTemplateApplication.java └── README.adoc ├── circuitbreaker ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── CircuitBreakerApplication.java └── README.adoc ├── rsocket-client ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── RsocketClient.java └── README.adoc ├── rsocket-server ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── RsocketServerApplication.java └── README.adoc ├── stream-consumer ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── StreamConsumerApplication.java └── README.adoc ├── stream-producer ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── StreamProducerApplication.java └── README.adoc ├── vault-webclient ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── README.adoc ├── docker-compose.yml └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── VaultWebClientApplication.java ├── vault-resttemplate ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── README.adoc ├── docker-compose.yml └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── VaultRestTemplateApplication.java ├── circuitbreaker-reactive ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── ReactiveCircuitBreakerApplication.java └── README.adoc ├── stream-reactive-consumer ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ └── application.yaml │ │ └── java │ │ └── com │ │ └── example │ │ └── sleuthsamples │ │ └── StreamReactiveConsumerApplication.java └── README.adoc ├── stream-reactive-producer ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── README.adoc └── src │ └── main │ ├── resources │ └── application.yaml │ └── java │ └── com │ └── example │ └── sleuthsamples │ └── StreamReactiveProducerApplication.java ├── scripts └── runAcceptanceTests.sh ├── .gitignore ├── .gitattributes ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── ISSUE_TEMPLATE.md ├── workflows │ └── maven.yml └── CONTRIBUTING.md ├── README.md └── pom.xml /baggage-consumer/README.adoc: -------------------------------------------------------------------------------- 1 | = Baggage Producer -------------------------------------------------------------------------------- /baggage-producer/README.adoc: -------------------------------------------------------------------------------- 1 | = Baggage Consumer -------------------------------------------------------------------------------- /kafka-consumer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Kafka integration 4 | 5 | -------------------------------------------------------------------------------- /kafka-producer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Kafka integration 4 | 5 | -------------------------------------------------------------------------------- /cassandra/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cassandra Integration 4 | -------------------------------------------------------------------------------- /mongodb-reactive/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring MongoDb Reactor Integration 4 | -------------------------------------------------------------------------------- /cassandra-reactive/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cassandra Reactive Integration 4 | -------------------------------------------------------------------------------- /kafka-reactive-consumer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Kafka reactive integration 4 | 5 | -------------------------------------------------------------------------------- /kafka-reactive-producer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Kafka reactive integration 4 | 5 | -------------------------------------------------------------------------------- /acceptance-tests/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | # For tests 2 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /session/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | redis: 4 | image: redis:latest 5 | ports: 6 | - "6379:6379" 7 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /mongodb-reactive/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | mongo: 4 | image: mongo:4.4.7 5 | ports: 6 | - 27017:27017 7 | -------------------------------------------------------------------------------- /security/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring.application.name: security-sample 2 | 3 | #logging.level.org.springframework.security: TRACE 4 | -------------------------------------------------------------------------------- /bus/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/bus/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /data-reactive/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE reactive_customer (id SERIAL PRIMARY KEY, first_name VARCHAR(255), last_name VARCHAR(255)); 2 | -------------------------------------------------------------------------------- /mvc/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/mvc/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /batch/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/batch/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /data-reactive/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | cassandra: 4 | image : "cassandra:3.11.2" 5 | ports: 6 | - 9042:9042 7 | -------------------------------------------------------------------------------- /data/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/data/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /task/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/task/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /deployer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/deployer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /gateway/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/gateway/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /security/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/security/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /session/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/session/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /webflux/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/webflux/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /batch/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: batch 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /cassandra/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/cassandra/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /config-server/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /integration/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/integration/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /openfeign/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/openfeign/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /webclient/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/webclient/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /bus/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: circuitbreaker 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /cassandra/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | cassandra: 4 | image: cassandra:3.11.2 5 | ports: 6 | - 7000:7000 7 | - 9042:9042 8 | -------------------------------------------------------------------------------- /config-server/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/config-server/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /data-reactive/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/data-reactive/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /resttemplate/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/resttemplate/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /acceptance-tests/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/acceptance-tests/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /baggage-producer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/baggage-producer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /cassandra-reactive/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | cassandra: 4 | image: cassandra:3.11.2 5 | ports: 6 | - 7000:7000 7 | - 9042:9042 8 | -------------------------------------------------------------------------------- /circuitbreaker/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/circuitbreaker/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /kafka-consumer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/kafka-consumer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /kafka-producer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/kafka-producer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /mongodb-reactive/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/mongodb-reactive/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /openfeign/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: openfeign 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /rsocket-client/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/rsocket-client/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /rsocket-server/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/rsocket-server/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /stream-consumer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/stream-consumer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /stream-producer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/stream-producer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /vault-webclient/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/vault-webclient/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /webclient/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: webclient 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /cassandra-reactive/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/cassandra-reactive/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /resttemplate/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: resttemplate 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /vault-resttemplate/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/vault-resttemplate/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /bus/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud Bus 4 | 5 | We're using Spring Cloud Stream for Bus messaging. You can check out the corresponding sample for more information. 6 | -------------------------------------------------------------------------------- /circuitbreaker/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: circuitbreaker 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /rsocket-client/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: rsocket-client 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /circuitbreaker-reactive/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/circuitbreaker-reactive/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /kafka-reactive-consumer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/kafka-reactive-consumer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /kafka-reactive-producer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/kafka-reactive-producer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /integration/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: spring-integration-producer 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /mvc/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7100 3 | 4 | spring: 5 | application: 6 | name: mvc 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /stream-reactive-consumer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/stream-reactive-consumer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /stream-reactive-producer/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-sleuth-samples/HEAD/stream-reactive-producer/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /circuitbreaker-reactive/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: circuitbreaker-reactive 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG 7 | -------------------------------------------------------------------------------- /gateway/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7111 3 | 4 | spring: 5 | application: 6 | name: gateway 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /kafka-reactive-producer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: reactive-kafka-producer 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG 7 | -------------------------------------------------------------------------------- /webflux/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7110 3 | 4 | spring: 5 | application: 6 | name: webflux 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /stream-reactive-producer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud Stream Reactive integration 4 | 5 | Starting from Spring Cloud Sleuth 3.1.0 we support Spring Cloud Stream with Reactive functions. 6 | -------------------------------------------------------------------------------- /task/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: task 4 | 5 | # For tests 6 | logging.level.org.springframework.cloud.sleuth: DEBUG 7 | logging.level.org.springframework.cloud.task: DEBUG -------------------------------------------------------------------------------- /vault-resttemplate/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Vault 4 | 5 | Sleuth instruments Vault via the `RestTemplate` and `WebClient` customizers. It works in the same way as the standard `RestTemplate` and `WebClient` instrumentation. 6 | -------------------------------------------------------------------------------- /vault-webclient/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Vault 4 | 5 | Sleuth instruments Vault via the `RestTemplate` and `WebClient` customizers. It works in the same way as the standard `RestTemplate` and `WebClient` instrumentation. 6 | -------------------------------------------------------------------------------- /kafka-reactive-consumer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: reactive-kafka-consumer 4 | 5 | spring.kafka.consumer.group-id: foo 6 | 7 | # For tests 8 | logging.level.org.springframework.cloud.sleuth: DEBUG 9 | -------------------------------------------------------------------------------- /session/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Session 4 | 5 | We're instrumenting the `SessionRepository`, `ReactiveSessionRepository` and the `FindByIndexNameSessionRepository`. Check the `TraceSessionAutoConfiguration` for more details. 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /scripts/runAcceptanceTests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | 5 | echo -e "\n\nRunning tests for Brave\n\n" 6 | ./mvnw clean install -Pdefault -U 7 | 8 | echo -e "\n\nRunning tests for OTel\n\n" 9 | ./mvnw clean install -Potel -U 10 | -------------------------------------------------------------------------------- /bus/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /data/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /mvc/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /task/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /baggage-producer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: baggage-producer 4 | sleuth: 5 | baggage: 6 | remote-fields: mybaggage, myremotefield 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /batch/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /cassandra/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /deployer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /gateway/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /openfeign/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /security/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /session/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /webclient/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /webflux/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /circuitbreaker/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /data-reactive/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /integration/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /kafka-consumer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /kafka-producer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /resttemplate/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /rsocket-client/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /rsocket-server/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /stream-consumer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: stream-consumer 4 | 5 | spring.cloud.stream: 6 | bindings.channel-in-0.destination: channeldestination 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /acceptance-tests/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /baggage-producer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /cassandra-reactive/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /mongodb-reactive/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /mongodb-reactive/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: mongo-reactive 4 | sleuth: 5 | reactor: 6 | instrumentation-type: decorate_queues 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG 10 | -------------------------------------------------------------------------------- /stream-consumer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /stream-producer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /vault-resttemplate/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /vault-webclient/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /circuitbreaker-reactive/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /deployer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: deployer 4 | sleuth: 5 | reactor: 6 | instrumentation-type: decorate_queues 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth.instrument.deployer: TRACE 10 | -------------------------------------------------------------------------------- /kafka-consumer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: kafka-consumer 4 | sleuth: 5 | otel: 6 | config: 7 | trace-id-ratio-based: 1.0 8 | 9 | # For tests 10 | logging.level.org.springframework.cloud.sleuth: DEBUG 11 | -------------------------------------------------------------------------------- /kafka-producer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: kafka-producer 4 | sleuth: 5 | otel: 6 | config: 7 | trace-id-ratio-based: 1.0 8 | 9 | # For tests 10 | logging.level.org.springframework.cloud.sleuth: DEBUG 11 | -------------------------------------------------------------------------------- /kafka-reactive-consumer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /kafka-reactive-producer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /stream-reactive-consumer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /stream-reactive-producer/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /session/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7200 3 | 4 | spring: 5 | application: 6 | name: session 7 | session: 8 | store-type: redis # Session store type. 9 | 10 | 11 | # For tests 12 | logging.level.org.springframework.cloud.sleuth: DEBUG 13 | -------------------------------------------------------------------------------- /vault-webclient/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | vault-server: 4 | image: vault:latest 5 | ports: 6 | - "8200:8200" 7 | environment: 8 | VAULT_ADDR: "http://0.0.0.0:8200" 9 | VAULT_DEV_ROOT_TOKEN_ID: "vault-plaintext-root-token" 10 | -------------------------------------------------------------------------------- /vault-resttemplate/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | vault-server: 4 | image: vault:latest 5 | ports: 6 | - "8200:8200" 7 | environment: 8 | VAULT_ADDR: "http://0.0.0.0:8200" 9 | VAULT_DEV_ROOT_TOKEN_ID: "vault-plaintext-root-token" 10 | -------------------------------------------------------------------------------- /vault-webclient/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: vault-webclient 4 | cloud: 5 | vault: 6 | scheme: http 7 | token: vault-plaintext-root-token 8 | 9 | # For tests 10 | logging.level.org.springframework.cloud.sleuth: DEBUG 11 | -------------------------------------------------------------------------------- /config-server/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server.port: 8888 2 | spring.cloud.config.server.git.uri: https://github.com/spring-cloud-samples/config-repo 3 | 4 | spring: 5 | application: 6 | name: config-server 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /vault-resttemplate/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: vault-resttemplate 4 | cloud: 5 | vault: 6 | scheme: http 7 | token: vault-plaintext-root-token 8 | 9 | # For tests 10 | logging.level.org.springframework.cloud.sleuth: DEBUG 11 | -------------------------------------------------------------------------------- /stream-producer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: stream-producer 4 | 5 | spring.cloud.stream: 6 | source: channel 7 | bindings.channel-out-0.destination: channeldestination 8 | 9 | # For tests 10 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /cassandra/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: cassandra 4 | 5 | spring.data.cassandra: 6 | keyspace-name: example 7 | schema-action: recreate 8 | local-datacenter: datacenter1 9 | 10 | # For tests 11 | logging.level.org.springframework.cloud.sleuth: DEBUG 12 | -------------------------------------------------------------------------------- /stream-reactive-consumer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: stream-reactive-consumer 4 | 5 | spring.cloud.stream: 6 | bindings.channel-in-0.destination: channelreactivedestination 7 | 8 | # For tests 9 | logging.level.org.springframework.cloud.sleuth: DEBUG 10 | -------------------------------------------------------------------------------- /rsocket-server/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7112 3 | 4 | spring: 5 | application: 6 | name: rsocket-server 7 | rsocket: 8 | server: 9 | mapping-path: "/rsocket" 10 | transport: websocket 11 | 12 | # For tests 13 | logging.level.org.springframework.cloud.sleuth: DEBUG -------------------------------------------------------------------------------- /security/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello Spring Security! 4 | 5 | 6 |

Hello Spring Security!

7 | Hello API
8 | Log Out 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | #* 3 | *# 4 | .#* 5 | .classpath 6 | .project 7 | .settings/ 8 | .springBeans 9 | target/ 10 | _site/ 11 | .idea 12 | *.iml 13 | *.swp 14 | .factorypath 15 | *.logtjmeter 16 | .checkstyle 17 | *.log 18 | .DS_Store 19 | build/ 20 | .gradle 21 | .gradletasknamecache 22 | nohup.out 23 | effective.pom 24 | test-results/ 25 | bin/ 26 | protoc 27 | .vscode/ -------------------------------------------------------------------------------- /stream-reactive-consumer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud Stream Reactive integration 4 | 5 | Starting from Spring Cloud Sleuth 3.1.0 we support Spring Cloud Stream with Reactive functions. 6 | 7 | When defining the consumer bean of `Consumer` type, remember to call `subscribe()` at the end of your flux. Otherwise you'll get the `Dispatcher has no subscribers` error. 8 | -------------------------------------------------------------------------------- /data/src/main/java/com/example/sleuthsamples/CustomerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | public interface CustomerRepository extends CrudRepository { 8 | 9 | List findByLastName(String lastName); 10 | 11 | Customer findById(long id); 12 | } 13 | -------------------------------------------------------------------------------- /cassandra-reactive/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: cassandra-reactive 4 | sleuth: 5 | reactor: 6 | instrumentation-type: decorate_queues 7 | 8 | spring.data.cassandra: 9 | keyspace-name: example 10 | schema-action: recreate 11 | local-datacenter: datacenter1 12 | 13 | # For tests 14 | logging.level.org.springframework.cloud.sleuth: DEBUG 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize line endings to LF. 2 | * text eol=lf 3 | 4 | # Ensure that line endings for multipart files in spring-web are not modified. 5 | *.multipart -text 6 | 7 | # Ensure that line endings for DOS batch files are not modified. 8 | *.bat -text 9 | 10 | # Ensure the following are treated as binary. 11 | *.gif binary 12 | *.jar binary 13 | *.jpeg binary 14 | *.jpg binary 15 | *.png binary 16 | *.vsd binary 17 | -------------------------------------------------------------------------------- /baggage-consumer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7200 3 | 4 | spring: 5 | application: 6 | name: baggage-consumer 7 | sleuth: 8 | baggage: 9 | remote-fields: mybaggage, myremotefield 10 | correlation-fields: mybaggage 11 | 12 | # For tests 13 | logging.level.org.springframework.cloud.sleuth: DEBUG 14 | 15 | logging.pattern.level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-},%X{mybaggage:-}]" 16 | 17 | -------------------------------------------------------------------------------- /bus/src/main/java/org/springframework/cloud/bus/event/MyEvent.java: -------------------------------------------------------------------------------- 1 | package org.springframework.cloud.bus.event; 2 | 3 | public class MyEvent extends RemoteApplicationEvent { 4 | 5 | public MyEvent(Object source, String originService) { 6 | super(source, originService); 7 | } 8 | 9 | MyEvent(Object source, String originService, String destinationService) { 10 | super(source, originService, destinationService); 11 | } 12 | 13 | MyEvent() { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /data/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: data 4 | datasource: 5 | url: jdbc:h2:mem:my-h2-db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 6 | sleuth: 7 | jdbc: 8 | # enable logging for datasource-proxy 9 | datasource-proxy: 10 | query: 11 | enable-logging: true 12 | # enable logging for p6spy 13 | p6spy: 14 | enable-logging: true 15 | # For tests 16 | logging.level.org.springframework.cloud.sleuth: DEBUG 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.java] 8 | indent_style = tab 9 | indent_size = 4 10 | continuation_indent_size = 8 11 | 12 | [*.groovy] 13 | indent_style = tab 14 | indent_size = 4 15 | continuation_indent_size = 8 16 | 17 | [*.xml] 18 | indent_style = tab 19 | indent_size = 4 20 | continuation_indent_size = 8 21 | 22 | [*.yml] 23 | indent_style = space 24 | indent_size = 2 25 | 26 | [*.yaml] 27 | indent_style = space 28 | indent_size = 2 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | Please provide details of the problem, including the version of Spring Cloud that you 12 | are using. 13 | 14 | **Sample** 15 | If possible, please provide a test case or sample application that reproduces 16 | the problem. This makes it much easier for us to diagnose the problem and to verify that 17 | we have fixed it. 18 | -------------------------------------------------------------------------------- /data-reactive/src/main/java/com/example/sleuthsamples/ReactiveCustomerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import reactor.core.publisher.Flux; 4 | import reactor.core.publisher.Mono; 5 | 6 | import org.springframework.data.repository.reactive.ReactiveCrudRepository; 7 | 8 | public interface ReactiveCustomerRepository extends ReactiveCrudRepository { 9 | 10 | Flux findByLastName(String lastName); 11 | 12 | Mono findById(long id); 13 | } 14 | -------------------------------------------------------------------------------- /data-reactive/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: data-reactive 4 | sleuth: 5 | reactor: 6 | instrumentation-type: decorate_queues 7 | autoconfigure: 8 | exclude: org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration 9 | datasource: 10 | url: jdbc:h2:mem:my-h2-db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 11 | # For tests 12 | logging.level.org.springframework.cloud.sleuth: DEBUG 13 | logging.level.com.example.sleuthsamples: DEBUG 14 | -------------------------------------------------------------------------------- /config-server/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Config Server 4 | 5 | We're using an aspect around the `EnvironmentRepository`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/config[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/config[here]. 8 | -------------------------------------------------------------------------------- /batch/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Batch 4 | 5 | We're wrapping the `StepBuilderFactory` and `JobBuilderFactory` in trace representations. 6 | 7 | You can check the instrumentation code, starting from the aspect https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/batch[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/batch/[here]. 8 | -------------------------------------------------------------------------------- /deployer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud Deployer 4 | 5 | We're wrapping `AppDeployer` in a trace representation. 6 | 7 | You can check the instrumentation code, starting from the code in the package https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/deployer/[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/deployer/[here]. 8 | -------------------------------------------------------------------------------- /rsocket-server/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring RSocket - server 4 | 5 | We're using a `RSocketServerCustomizer`, `RSocketConnectorCustomizer` together with `TraceMessagingAspect`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/3.1.x/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/rsocket[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/3.1.x/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/rsocket[here]. 8 | -------------------------------------------------------------------------------- /rsocket-client/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring RSocket - client 4 | 5 | We're using a `RSocketServerCustomizer`, `RSocketConnectorCustomizer` together with `TraceMessagingAspect`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/rsocket[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/{branch}/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/rsocket[here]. 8 | -------------------------------------------------------------------------------- /task/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud Task 4 | 5 | We're instrumenting `TaskExecutionListener` and `CommandLineRunner` and `ApplicationRunner`. 6 | 7 | You can check the instrumentation code, starting from the code in the package https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/task/[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/task/TraceTaskAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /webflux/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring WebFlux Integration 4 | 5 | We're using a special `WebFilter` called `org.springframework.cloud.sleuth.instrument.web.TraceWebFilter`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFilter.java[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/TraceWebFluxConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /data/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Data Integration 4 | 5 | For transaction instrumentation we're wrapping the `PlatformTransactionManager`. 6 | 7 | You can check the instrumentation code, starting from the aspect https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/tx/TracePlatformTransactionManager.java[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/tx/TraceTxAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /data-reactive/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Data Reactive Integration 4 | 5 | For transaction instrumentation we're wrapping the `ReactiveTransactionManager`. 6 | 7 | You can check the instrumentation code, starting from the aspect https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/tx/TraceReactiveTransactionManager.java[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/tx/TraceTxAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /integration/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Integratoin Sleuth Integration 4 | 5 | We're using a `ChannelInterceptor` called `org.springframework.cloud.sleuth.instrument.messaging.TracingChannelInterceptor`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptor.java[here] and the configuration is https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/messaging/TraceSpringIntegrationAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /security/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Security 4 | 5 | We are listening on `SecurityContextChangedEvent` and annotate the spans based on the events coming from Spring Security. 6 | You can check the instrumentation code in the https://github.com/spring-cloud/spring-cloud-sleuth/blob/main/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/security/TracingSecurityContextChangedListener.java [`org.springframework.cloud.sleuth.instrument.security` package]. 7 | 8 | You can test the app via a browser by visiting http://localhost:8080 or hitting the API endpoint via a client, e.g.: `http -a user:password :8080/api/hello` or `curl user:password@localhost:8080/api/hello`. 9 | -------------------------------------------------------------------------------- /stream-consumer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud Stream integration 4 | 5 | We're using a `FunctionAroundWrapper` advice. `org.springframework.cloud.sleuth.instrument.messaging.TraceFunctionAroundWrapper`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapper.java[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/messaging/TraceFunctionAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /stream-producer/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud Stream integration 4 | 5 | We're using a `FunctionAroundWrapper` advice. `org.springframework.cloud.sleuth.instrument.messaging.TraceFunctionAroundWrapper`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapper.java[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/messaging/TraceFunctionAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /mvc/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring WebMvc Integration 4 | 5 | We're using a special `Filter` called `org.springframework.cloud.sleuth.instrument.web.servlet.TracingFilter` and via *AOP* `org.springframework.cloud.sleuth.instrument.web.TraceWebAspect` to instrument async controllers. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/mvc[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/TraceWebServletConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /circuitbreaker/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud CircuitBreaker 4 | 5 | We're proxying via **AOP** calls to `CircuitBreaker`. We're wrapping the `Supplier` and the fallback `Function` in trace representations. 6 | 7 | You can check the instrumentation code, starting from the aspect https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceCircuitBreakerFactoryAspect.java[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/circuitbreaker/TraceCircuitBreakerAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /circuitbreaker-reactive/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring Cloud CircuitBreaker Reactive 4 | 5 | We're proxying via **AOP** calls to `ReactiveCircuitBreaker`. We're instrumenting the reactor context with span information. 6 | 7 | You can check the instrumentation code, starting from the aspect https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/circuitbreaker/TraceReactiveCircuitBreakerFactoryAspect.java[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/circuitbreaker/TraceCircuitBreakerAutoConfiguration.java[here]. 8 | -------------------------------------------------------------------------------- /stream-reactive-producer/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: stream-reactive-producer 4 | 5 | # streambridge -> channelreactivedestination-input -> function bean -> channelreactivedestination 6 | spring.cloud.stream.bindings.tracingFunction-in-0.destination: channelreactivedestination-input 7 | spring.cloud.stream.bindings.tracingFunction-out-0.destination: channelreactivedestination 8 | 9 | spring.cloud.stream.bindings.supplier-out-0.destination: supplier 10 | spring.cloud.stream.bindings.stringSupplier-out-0.destination: stringSupplier 11 | 12 | spring.cloud.function.definition: tracingFunction 13 | # spring.cloud.function.definition: tracingFunction;supplier;stringSupplier 14 | 15 | # For tests 16 | logging.level.org.springframework.cloud.sleuth: DEBUG 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Build 5 | 6 | on: 7 | push: 8 | branches: [ main, 3.0.x ] 9 | pull_request: 10 | branches: [ main, 3.0.x ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 11 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 11 23 | - name: Cache local Maven repository 24 | uses: actions/cache@v2 25 | with: 26 | path: ~/.m2/repository 27 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} 28 | restore-keys: | 29 | ${{ runner.os }}-maven- 30 | - name: Build with Maven 31 | run: ./scripts/runAcceptanceTests.sh 32 | -------------------------------------------------------------------------------- /data-reactive/src/main/java/com/example/sleuthsamples/ReactiveCustomer.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.springframework.data.annotation.Id; 4 | 5 | public class ReactiveCustomer { 6 | 7 | @Id 8 | private Long id; 9 | 10 | private final String firstName; 11 | 12 | private final String lastName; 13 | 14 | public ReactiveCustomer(String firstName, String lastName) { 15 | this.firstName = firstName; 16 | this.lastName = lastName; 17 | } 18 | 19 | public Long getId() { 20 | return this.id; 21 | } 22 | 23 | public void setId(Long id) { 24 | this.id = id; 25 | } 26 | 27 | public String getFirstName() { 28 | return this.firstName; 29 | } 30 | 31 | public String getLastName() { 32 | return this.lastName; 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return String.format( 38 | "Customer[id=%d, firstName='%s', lastName='%s']", 39 | id, firstName, lastName); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /webclient/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring WebClient Integration 4 | 5 | We're using a `WebClient`'s exchange filter function. `org.springframework.cloud.sleuth.instrument.web.client.TraceExchangeFilterFunction`. 6 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceExchangeFilterFunction.java[here] the bean post processor https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessor.java[here] the and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/client/TraceWebClientAutoConfiguration.java[here]. 7 | -------------------------------------------------------------------------------- /data/src/main/java/com/example/sleuthsamples/Customer.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.GenerationType; 6 | import javax.persistence.Id; 7 | 8 | @Entity 9 | public class Customer { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.AUTO) 13 | private Long id; 14 | private String firstName; 15 | private String lastName; 16 | 17 | protected Customer() { 18 | } 19 | 20 | public Customer(String firstName, String lastName) { 21 | this.firstName = firstName; 22 | this.lastName = lastName; 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return String.format( 28 | "Customer[id=%d, firstName='%s', lastName='%s']", 29 | id, firstName, lastName); 30 | } 31 | 32 | public Long getId() { 33 | return id; 34 | } 35 | 36 | public String getFirstName() { 37 | return firstName; 38 | } 39 | 40 | public String getLastName() { 41 | return lastName; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /openfeign/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring RestTemplate Integration 4 | 5 | We're using a `RestTemplate`'s interceptors. `org.springframework.cloud.sleuth.instrument.web.mvc.TracingClientHttpRequestInterceptor` and `org.springframework.cloud.sleuth.instrument.web.mvc.TracingAsyncClientHttpRequestInterceptor`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/mvc[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java[here for async] and https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/client/TraceWebClientAutoConfiguration.java[here for non-async]. 8 | -------------------------------------------------------------------------------- /resttemplate/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring RestTemplate Integration 4 | 5 | We're using a `RestTemplate`'s interceptors. `org.springframework.cloud.sleuth.instrument.web.mvc.TracingClientHttpRequestInterceptor` and `org.springframework.cloud.sleuth.instrument.web.mvc.TracingAsyncClientHttpRequestInterceptor`. 6 | 7 | You can check the instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/mvc[here] and the instrumentation configuration code https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java[here for async] and https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/client/TraceWebClientAutoConfiguration.java[here for non-async]. 8 | -------------------------------------------------------------------------------- /security/src/main/java/com/example/sleuthsamples/SecurityController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.sleuthsamples; 18 | 19 | import org.springframework.web.bind.annotation.GetMapping; 20 | import org.springframework.web.bind.annotation.RestController; 21 | 22 | /** 23 | * Sample controller to simulate an API endpoint. 24 | * 25 | * @author Jonatan Ivanov 26 | */ 27 | @RestController 28 | public class SecurityController { 29 | @GetMapping("/api/hello") 30 | public String hello() { 31 | return "hello"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /data/src/main/java/com/example/sleuthsamples/DataApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.WebApplicationType; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.boot.builder.SpringApplicationBuilder; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.dao.DataAccessException; 12 | 13 | @SpringBootApplication 14 | public class DataApplication { 15 | 16 | private static final Logger log = LoggerFactory.getLogger(DataApplication.class); 17 | 18 | public static void main(String... args) { 19 | new SpringApplicationBuilder(DataApplication.class).web(WebApplicationType.NONE).run(args); 20 | } 21 | 22 | @Bean 23 | public CommandLineRunner demo(NewTransactionService newTransactionService) { 24 | return (args) -> { 25 | try { 26 | newTransactionService.newTransaction(); 27 | } 28 | catch (DataAccessException e) { 29 | log.info("Expected to throw an exception so that we see if rollback works", e); 30 | } 31 | }; 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /data/src/main/java/com/example/sleuthsamples/NestedTransactionService.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.cloud.sleuth.Tracer; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Propagation; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | @Service 12 | public class NestedTransactionService { 13 | 14 | private static final Logger log = LoggerFactory.getLogger(NestedTransactionService.class); 15 | 16 | private final CustomerRepository repository; 17 | 18 | private final Tracer tracer; 19 | 20 | public NestedTransactionService(CustomerRepository repository, Tracer tracer) { 21 | this.repository = repository; 22 | this.tracer = tracer; 23 | } 24 | 25 | @Transactional(propagation = Propagation.REQUIRES_NEW) 26 | public void newTransaction() { 27 | log.info(" Hello from consumer requires new", tracer.currentSpan().context().traceId()); 28 | repository.save(new Customer("Hello", "From Propagated Transaction")); 29 | repository.deleteById(10238L); 30 | log.info(""); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /mvc/src/main/java/com/example/sleuthsamples/MvcApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.cloud.sleuth.Tracer; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @SpringBootApplication 14 | public class MvcApplication { 15 | 16 | public static void main(String... args) { 17 | new SpringApplication(MvcApplication.class).run(args); 18 | } 19 | } 20 | 21 | @RestController 22 | class MvcController { 23 | private static final Logger log = LoggerFactory.getLogger(MvcController.class); 24 | 25 | private final Tracer tracer; 26 | 27 | MvcController(Tracer tracer) { 28 | this.tracer = tracer; 29 | } 30 | 31 | @GetMapping("/") 32 | public String span() { 33 | String traceId = this.tracer.currentSpan().context().traceId(); 34 | log.info(" Hello from producer", traceId); 35 | return traceId; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /webflux/src/main/java/com/example/sleuthsamples/WebFluxApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import reactor.core.publisher.Mono; 6 | 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.cloud.sleuth.Tracer; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @SpringBootApplication 14 | public class WebFluxApplication { 15 | 16 | public static void main(String... args) { 17 | new SpringApplication(WebFluxApplication.class).run(args); 18 | } 19 | } 20 | 21 | @RestController 22 | class WebFluxController { 23 | private static final Logger log = LoggerFactory.getLogger(WebFluxController.class); 24 | 25 | private final Tracer tracer; 26 | 27 | WebFluxController(Tracer tracer) { 28 | this.tracer = tracer; 29 | } 30 | 31 | @RequestMapping("/") 32 | public Mono span() { 33 | String traceId = this.tracer.currentSpan().context().traceId(); 34 | log.info(" Hello from producer", traceId); 35 | return Mono.just(traceId); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cassandra/src/main/java/com/example/sleuthsamples/BasicConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | import org.springframework.boot.autoconfigure.domain.EntityScan; 19 | import org.springframework.context.annotation.Configuration; 20 | 21 | /** 22 | * Basic {@link Configuration} to create the necessary schema for the {@link User} table. 23 | * 24 | * @author Oliver Gierke 25 | * @author Thomas Darimont 26 | * @author Mark Paluch 27 | */ 28 | @Configuration(proxyBeanMethods = false) 29 | @EntityScan(basePackageClasses = User.class) 30 | class BasicConfiguration { 31 | } 32 | -------------------------------------------------------------------------------- /stream-consumer/src/main/java/com/example/sleuthsamples/StreamConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.function.Consumer; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.WebApplicationType; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import org.springframework.boot.builder.SpringApplicationBuilder; 12 | import org.springframework.cloud.sleuth.Tracer; 13 | import org.springframework.context.annotation.Bean; 14 | 15 | @SpringBootApplication 16 | public class StreamConsumerApplication implements CommandLineRunner { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(StreamConsumerApplication.class); 19 | 20 | public static void main(String... args) { 21 | new SpringApplicationBuilder(StreamConsumerApplication.class).web(WebApplicationType.NONE).run(args); 22 | } 23 | 24 | @Override 25 | public void run(String... args) throws Exception { 26 | 27 | } 28 | 29 | @Bean 30 | Consumer channel(Tracer tracer) { 31 | return string -> 32 | log.info(" Hello from consumer", tracer.currentSpan().context().traceId()); 33 | } 34 | } -------------------------------------------------------------------------------- /cassandra-reactive/src/main/java/com/example/sleuthsamples/BasicConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | import org.springframework.boot.autoconfigure.SpringBootApplication; 19 | import org.springframework.boot.autoconfigure.domain.EntityScan; 20 | import org.springframework.context.annotation.Configuration; 21 | 22 | /** 23 | * Basic {@link Configuration} to create the necessary schema for the {@link User} table. 24 | * 25 | * @author Oliver Gierke 26 | * @author Thomas Darimont 27 | * @author Mark Paluch 28 | */ 29 | @Configuration 30 | @EntityScan(basePackageClasses = User.class) 31 | class BasicConfiguration { 32 | } 33 | -------------------------------------------------------------------------------- /gateway/README.adoc: -------------------------------------------------------------------------------- 1 | :branch: main 2 | 3 | = Spring WebFlux Integration 4 | 5 | We're using a special `WebFilter` called `org.springframework.cloud.sleuth.instrument.web.TraceWebFilter` for the incoming requests. For the outbound once we're using the following algorithm: 6 | 7 | 8 | You can check the `WebFilter` instrumentation code https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFilter.java[here] the request filter https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRequestHttpHeadersFilter.java[here] and the response filter https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceResponseHttpHeadersFilter.java[here]. The instrumentation configuration code org/springframework/cloud/sleuth/autoconfig/instrument/web/client/TraceWebClientAutoConfiguration.java[here]. The `BeanPostProcessor` for instrumenting Netty is here https://github.com/spring-cloud/spring-cloud-sleuth/tree/{branch}/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/HttpClientBeanPostProcessor.java[here]. 9 | -------------------------------------------------------------------------------- /mongodb-reactive/src/main/java/com/example/sleuthsamples/BasicUserRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | import reactor.core.publisher.Mono; 19 | 20 | import org.springframework.data.mongodb.repository.Query; 21 | import org.springframework.data.repository.reactive.ReactiveCrudRepository; 22 | 23 | /** 24 | * Simple repository interface for {@link User} instances. The interface is used to declare so called query methods, 25 | * methods to retrieve single entities or collections of them. 26 | * 27 | * @author Mark Paluch 28 | */ 29 | public interface BasicUserRepository extends ReactiveCrudRepository { 30 | 31 | Mono findUserByUsername(String username); 32 | } 33 | -------------------------------------------------------------------------------- /rsocket-server/src/main/java/com/example/sleuthsamples/RsocketServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import reactor.core.publisher.Mono; 6 | 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.cloud.sleuth.Tracer; 10 | import org.springframework.messaging.handler.annotation.MessageMapping; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | @SpringBootApplication 16 | public class RsocketServerApplication { 17 | 18 | public static void main(String... args) { 19 | new SpringApplication(RsocketServerApplication.class).run(args); 20 | } 21 | } 22 | 23 | @Controller 24 | class RSocketController { 25 | private static final Logger log = LoggerFactory.getLogger(RSocketController.class); 26 | 27 | private final Tracer tracer; 28 | 29 | RSocketController(Tracer tracer) { 30 | this.tracer = tracer; 31 | } 32 | 33 | @MessageMapping("foo") 34 | public Mono span() { 35 | String traceId = this.tracer.currentSpan().context().traceId(); 36 | log.info(" Hello from consumer", traceId); 37 | return Mono.just(traceId); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/MongoDbAcceptanceTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Map; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.TestInfo; 7 | import org.testcontainers.containers.MongoDBContainer; 8 | import org.testcontainers.junit.jupiter.Container; 9 | import org.testcontainers.junit.jupiter.Testcontainers; 10 | 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | 13 | // Uncomment the properties to rebuild the projects 14 | // @formatter:off 15 | @SpringBootTest( 16 | // properties = {"spring.cloud.sleuth.samples.rebuild-projects=true", "spring.cloud.sleuth.samples.project-root=${user.home}/repo/spring-cloud-sleuth-samples", "maven.home=${user.home}/.sdkman/candidates/maven/current"} 17 | ) 18 | @Testcontainers 19 | // @formatter:on 20 | class MongoDbAcceptanceTests extends AcceptanceTestsBase { 21 | 22 | @Container 23 | static MongoDBContainer mongo = new MongoDBContainer("mongo:4.4.7"); 24 | 25 | @Test 26 | void should_pass_tracing_context_with_mongo(TestInfo testInfo) { 27 | // when 28 | String producerId = deploy(testInfo, "mongodb-reactive", replicaSetUri()); 29 | 30 | // then 31 | assertThatTraceIdGotPropagated(producerId); 32 | } 33 | 34 | private Map replicaSetUri() { 35 | return Map.of("spring.data.mongodb.uri", mongo.getReplicaSetUrl()); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /data-reactive/src/main/java/com/example/sleuthsamples/ReactiveNestedTransactionService.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import reactor.core.publisher.Mono; 6 | 7 | import org.springframework.cloud.sleuth.Tracer; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Propagation; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | @Service 13 | public class ReactiveNestedTransactionService { 14 | 15 | private static final Logger log = LoggerFactory.getLogger(ReactiveNestedTransactionService.class); 16 | 17 | private final Tracer tracer; 18 | 19 | private final ReactiveCustomerRepository repository; 20 | 21 | public ReactiveNestedTransactionService(Tracer tracer, ReactiveCustomerRepository repository) { 22 | this.tracer = tracer; 23 | this.repository = repository; 24 | } 25 | 26 | @Transactional(propagation = Propagation.REQUIRES_NEW) 27 | public Mono requiresNew() { 28 | return Mono.fromRunnable(() -> log.info(" Hello from consumer requires new", tracer.currentSpan().context().traceId())) 29 | .then(repository.save(new ReactiveCustomer("Hello", "From Propagated Transaction"))) 30 | .doOnNext(customerFlux -> repository.deleteById(10238L)) 31 | .doOnNext(customerFlux -> log.info("")) 32 | .then(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cassandra/src/test/java/com/example/sleuthsamples/CassandraApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import com.datastax.driver.core.Cluster; 4 | import com.datastax.driver.core.Session; 5 | import org.junit.jupiter.api.Disabled; 6 | import org.junit.jupiter.api.Test; 7 | import org.testcontainers.containers.CassandraContainer; 8 | import org.testcontainers.junit.jupiter.Container; 9 | import org.testcontainers.junit.jupiter.Testcontainers; 10 | 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.test.context.DynamicPropertyRegistry; 13 | import org.springframework.test.context.DynamicPropertySource; 14 | 15 | @SpringBootTest 16 | @Testcontainers 17 | @Disabled 18 | class CassandraApplicationTests { 19 | 20 | @Container 21 | static CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2"); 22 | 23 | @DynamicPropertySource 24 | static void setup(DynamicPropertyRegistry registry) { 25 | registry.add("spring.data.cassandra.contact-points", () -> cassandra.getContainerIpAddress() + ":" + cassandra.getFirstMappedPort()); 26 | Cluster cluster = cassandra.getCluster(); 27 | try (Session session = cluster.connect()) { 28 | session.execute("CREATE KEYSPACE IF NOT EXISTS example WITH replication = \n" + 29 | "{'class':'SimpleStrategy','replication_factor':'1'};"); 30 | } 31 | } 32 | 33 | @Test 34 | void should_work() { 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cassandra-reactive/src/test/java/com/example/sleuthsamples/ReactiveCassandraApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import com.datastax.driver.core.Cluster; 4 | import com.datastax.driver.core.Session; 5 | import org.junit.jupiter.api.Disabled; 6 | import org.junit.jupiter.api.Test; 7 | import org.testcontainers.containers.CassandraContainer; 8 | import org.testcontainers.junit.jupiter.Container; 9 | import org.testcontainers.junit.jupiter.Testcontainers; 10 | 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.test.context.DynamicPropertyRegistry; 13 | import org.springframework.test.context.DynamicPropertySource; 14 | 15 | @SpringBootTest 16 | @Testcontainers 17 | @Disabled 18 | class ReactiveCassandraApplicationTests { 19 | 20 | @Container 21 | static CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2"); 22 | 23 | @DynamicPropertySource 24 | static void setup(DynamicPropertyRegistry registry) { 25 | registry.add("spring.data.cassandra.contact-points", () -> cassandra.getContainerIpAddress() + ":" + cassandra.getFirstMappedPort()); 26 | Cluster cluster = cassandra.getCluster(); 27 | try (Session session = cluster.connect()) { 28 | session.execute("CREATE KEYSPACE IF NOT EXISTS example WITH replication = \n" + 29 | "{'class':'SimpleStrategy','replication_factor':'1'};"); 30 | } 31 | } 32 | 33 | @Test 34 | void should_work() { 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /task/src/main/java/com/example/sleuthsamples/SpringCloudTaskApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.ApplicationArguments; 8 | import org.springframework.boot.ApplicationRunner; 9 | import org.springframework.boot.CommandLineRunner; 10 | import org.springframework.boot.WebApplicationType; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.boot.builder.SpringApplicationBuilder; 13 | import org.springframework.cloud.sleuth.Tracer; 14 | import org.springframework.cloud.task.configuration.EnableTask; 15 | import org.springframework.context.annotation.Bean; 16 | 17 | @SpringBootApplication 18 | @EnableTask 19 | public class SpringCloudTaskApplication { 20 | private static final Logger log = LoggerFactory.getLogger(SpringCloudTaskApplication.class); 21 | 22 | public static void main(String... args) { 23 | new SpringApplicationBuilder(SpringCloudTaskApplication.class).web(WebApplicationType.NONE).run(args); 24 | } 25 | 26 | @Bean 27 | CommandLineRunner myCommandLineRunner(Tracer tracer) { 28 | return args -> log.info(" Hello from consumer", tracer.currentSpan().context().traceId()); 29 | } 30 | 31 | @Bean 32 | ApplicationRunner myApplicationRunner(Tracer tracer) { 33 | return args -> log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 34 | } 35 | } -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/VaultAcceptanceTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Map; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.TestInfo; 7 | import org.testcontainers.junit.jupiter.Container; 8 | import org.testcontainers.junit.jupiter.Testcontainers; 9 | import org.testcontainers.vault.VaultContainer; 10 | 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | 13 | // Uncomment the properties to rebuild the projects 14 | // @formatter:off 15 | @SpringBootTest( 16 | // properties = {"spring.cloud.sleuth.samples.rebuild-projects=true", "spring.cloud.sleuth.samples.project-root=${user.home}/repo/spring-cloud-sleuth-samples", "maven.home=${user.home}/.sdkman/candidates/maven/current"} 17 | ) 18 | @Testcontainers 19 | // @formatter:on 20 | class VaultAcceptanceTests extends AcceptanceTestsBase { 21 | 22 | @Container 23 | static VaultContainer vault = new VaultContainer("vault:1.7.0") 24 | .withVaultToken("vault-plaintext-root-token"); 25 | 26 | @Test 27 | void should_pass_tracing_context_with_vault(TestInfo testInfo) { 28 | // when 29 | String producerId = deploy(testInfo, "vault-resttemplate", port()); 30 | 31 | // then 32 | assertThatTraceIdGotPropagated(producerId); 33 | } 34 | 35 | @Test 36 | void should_pass_tracing_context_with_vault_reactive(TestInfo testInfo) { 37 | // when 38 | String producerId = deploy(testInfo, "vault-webclient", port()); 39 | 40 | // then 41 | assertThatTraceIdGotPropagated(producerId); 42 | } 43 | 44 | private Map port() { 45 | return Map.of("spring.cloud.vault.port", String.valueOf(vault.getFirstMappedPort())); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /data/src/main/java/com/example/sleuthsamples/ContinuedTransactionService.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import javax.transaction.Transactional; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import org.springframework.cloud.sleuth.Tracer; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | public class ContinuedTransactionService { 13 | 14 | private static final Logger log = LoggerFactory.getLogger(ContinuedTransactionService.class); 15 | 16 | private final CustomerRepository repository; 17 | 18 | private final NestedTransactionService nestedTransactionService; 19 | 20 | private final Tracer tracer; 21 | 22 | public ContinuedTransactionService(CustomerRepository repository, NestedTransactionService nestedTransactionService, Tracer tracer) { 23 | this.repository = repository; 24 | this.nestedTransactionService = nestedTransactionService; 25 | this.tracer = tracer; 26 | } 27 | 28 | @Transactional 29 | public void continuedTransaction() { 30 | log.info(" Hello from consumer", tracer.currentSpan().context().traceId()); 31 | 32 | // fetch an individual customer by ID 33 | Customer customer = repository.findById(1L); 34 | log.info("Customer found with findById(1L):"); 35 | log.info("--------------------------------"); 36 | log.info(customer.toString()); 37 | log.info(""); 38 | 39 | // fetch customers by last name 40 | log.info("Customer found with findByLastName('Bauer'):"); 41 | log.info("--------------------------------------------"); 42 | repository.findByLastName("Bauer").forEach(bauer -> { 43 | log.info(bauer.toString()); 44 | }); 45 | nestedTransactionService.newTransaction(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cassandra/src/main/java/com/example/sleuthsamples/CassandraApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.WebApplicationType; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.boot.builder.SpringApplicationBuilder; 10 | import org.springframework.cloud.sleuth.Span; 11 | import org.springframework.cloud.sleuth.Tracer; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.dao.DataAccessException; 14 | 15 | @SpringBootApplication 16 | public class CassandraApplication { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(CassandraApplication.class); 19 | 20 | public static void main(String... args) { 21 | new SpringApplicationBuilder(CassandraApplication.class).web(WebApplicationType.NONE).run(args); 22 | } 23 | 24 | @Bean 25 | public CommandLineRunner demo(BasicUserRepository basicUserRepository, Tracer tracer) { 26 | return (args) -> { 27 | Span span = tracer.nextSpan().name("cassandra-app"); 28 | try (Tracer.SpanInScope ws = tracer.withSpan(span.start())){ 29 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 30 | User save = basicUserRepository.save(new User("foo", "bar", "baz", 1L)); 31 | User userByIdIn = basicUserRepository.findUserByIdIn(save.getId()); 32 | basicUserRepository.findUserByIdIn(123123L); 33 | } 34 | catch (DataAccessException e) { 35 | log.info("Expected to throw an exception so that we see if rollback works", e); 36 | } finally { 37 | span.end(); 38 | } 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /data/src/main/java/com/example/sleuthsamples/NewTransactionService.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import javax.transaction.Transactional; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import org.springframework.cloud.sleuth.Tracer; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | public class NewTransactionService { 13 | 14 | private static final Logger log = LoggerFactory.getLogger(NewTransactionService.class); 15 | 16 | private final CustomerRepository repository; 17 | 18 | private final ContinuedTransactionService continuedTransactionService; 19 | 20 | private final Tracer tracer; 21 | 22 | public NewTransactionService(CustomerRepository repository, ContinuedTransactionService continuedTransactionService, Tracer tracer) { 23 | this.repository = repository; 24 | this.continuedTransactionService = continuedTransactionService; 25 | this.tracer = tracer; 26 | } 27 | 28 | @Transactional 29 | public void newTransaction() { 30 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 31 | 32 | // save a few customers 33 | repository.save(new Customer("Jack", "Bauer")); 34 | repository.save(new Customer("Chloe", "O'Brian")); 35 | repository.save(new Customer("Kim", "Bauer")); 36 | repository.save(new Customer("David", "Palmer")); 37 | repository.save(new Customer("Michelle", "Dessler")); 38 | 39 | // fetch all customers 40 | log.info("Customers found with findAll():"); 41 | log.info("-------------------------------"); 42 | for (Customer customer : repository.findAll()) { 43 | log.info(customer.toString()); 44 | } 45 | log.info(""); 46 | 47 | this.continuedTransactionService.continuedTransaction(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cassandra-reactive/src/main/java/com/example/sleuthsamples/ReactiveCassandraApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.time.Duration; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import reactor.core.publisher.Mono; 8 | 9 | import org.springframework.boot.CommandLineRunner; 10 | import org.springframework.boot.WebApplicationType; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.boot.builder.SpringApplicationBuilder; 13 | import org.springframework.cloud.sleuth.Span; 14 | import org.springframework.cloud.sleuth.Tracer; 15 | import org.springframework.context.annotation.Bean; 16 | import org.springframework.dao.DataAccessException; 17 | 18 | @SpringBootApplication 19 | public class ReactiveCassandraApplication { 20 | 21 | private static final Logger log = LoggerFactory.getLogger(ReactiveCassandraApplication.class); 22 | 23 | public static void main(String... args) { 24 | new SpringApplicationBuilder(ReactiveCassandraApplication.class).web(WebApplicationType.NONE).run(args); 25 | } 26 | 27 | @Bean 28 | public CommandLineRunner demo(BasicUserRepository basicUserRepository, Tracer tracer) { 29 | return (args) -> { 30 | Span nextSpan = tracer.nextSpan().name("cassandra-reactive-app"); 31 | Mono.just(nextSpan) 32 | .doOnNext(span -> tracer.withSpan(span.start())) 33 | .flatMap(span -> { 34 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 35 | return basicUserRepository.save(new User("foo", "bar", "baz", 1L)) 36 | .flatMap(user -> basicUserRepository.findUserByIdIn(user.getId())); 37 | }) 38 | .doFinally(signalType -> nextSpan.end()).block(Duration.ofMinutes(1)); 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /cassandra/src/main/java/com/example/sleuthsamples/BasicUserRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | import java.util.List; 19 | 20 | import org.springframework.data.cassandra.repository.Query; 21 | import org.springframework.data.repository.CrudRepository; 22 | 23 | /** 24 | * Simple repository interface for {@link User} instances. The interface is used to declare so called query methods, 25 | * methods to retrieve single entities or collections of them. 26 | * 27 | * @author Thomas Darimont 28 | */ 29 | public interface BasicUserRepository extends CrudRepository { 30 | 31 | /** 32 | * Sample method annotated with {@link Query}. This method executes the CQL from the {@link Query} value. 33 | * 34 | * @param id 35 | * @return 36 | */ 37 | @Query("SELECT * from users where user_id in(?0)") 38 | User findUserByIdIn(long id); 39 | 40 | /** 41 | * Derived query method. This query corresponds with {@code SELECT * FROM users WHERE uname = ?0}. 42 | * {@link User#username} is not part of the primary so it requires a secondary index. 43 | * 44 | * @param username 45 | * @return 46 | */ 47 | User findUserByUsername(String username); 48 | } 49 | -------------------------------------------------------------------------------- /cassandra-reactive/src/main/java/com/example/sleuthsamples/BasicUserRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | import reactor.core.publisher.Mono; 19 | 20 | import org.springframework.data.cassandra.repository.Query; 21 | import org.springframework.data.repository.reactive.ReactiveCrudRepository; 22 | 23 | /** 24 | * Simple repository interface for {@link User} instances. The interface is used to declare so called query methods, 25 | * methods to retrieve single entities or collections of them. 26 | * 27 | * @author Mark Paluch 28 | */ 29 | public interface BasicUserRepository extends ReactiveCrudRepository { 30 | 31 | /** 32 | * Sample method annotated with {@link Query}. This method executes the CQL from the {@link Query} value. 33 | * 34 | * @param id 35 | * @return 36 | */ 37 | @Query("SELECT * from users where user_id in(?0)") 38 | Mono findUserByIdIn(long id); 39 | 40 | /** 41 | * Derived query method. This query corresponds with {@code SELECT * FROM users WHERE uname = ?0}. 42 | * {@link User#username} is not part of the primary so it requires a secondary index. 43 | * 44 | * @param username 45 | * @return 46 | */ 47 | Mono findUserByUsername(String username); 48 | } 49 | -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/RedisAcceptanceTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Map; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.TestInfo; 7 | import org.testcontainers.containers.GenericContainer; 8 | import org.testcontainers.junit.jupiter.Container; 9 | import org.testcontainers.junit.jupiter.Testcontainers; 10 | import org.testcontainers.utility.DockerImageName; 11 | 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.util.SocketUtils; 14 | 15 | // Uncomment the properties to rebuild the projects 16 | // @formatter:off 17 | @SpringBootTest( 18 | // properties = {"spring.cloud.sleuth.samples.rebuild-projects=true", "spring.cloud.sleuth.samples.project-root=${user.home}/repo/spring-cloud-sleuth-samples", "maven.home=${user.home}/.sdkman/candidates/maven/current"} 19 | ) 20 | @Testcontainers 21 | // @formatter:on 22 | class RedisAcceptanceTests extends AcceptanceTestsBase { 23 | 24 | @Container 25 | static GenericContainer redis = new GenericContainer(DockerImageName.parse("redis:6.2.3-alpine")) 26 | .withExposedPorts(6379); 27 | 28 | @Test 29 | void should_pass_tracing_context_from_client_to_redis_based_session_app(TestInfo testInfo) throws Exception { 30 | // given 31 | int port = SocketUtils.findAvailableTcpPort(); 32 | String producerId = waitUntilStarted(() -> deployWebApp(testInfo, "session", redisConfiguration(port))); 33 | 34 | // when 35 | String consumerId = deploy(testInfo, "resttemplate", Map.of("url", "http://localhost:" + port)); 36 | 37 | // then 38 | assertThatTraceIdGotPropagated(producerId, consumerId); 39 | } 40 | 41 | private Map redisConfiguration(int mvcPort) { 42 | return Map.of("spring.redis.host", redis.getHost(), "spring.redis.port", redis.getFirstMappedPort().toString(), "server.port", String.valueOf(mvcPort)); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /mongodb-reactive/src/main/java/com/example/sleuthsamples/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | /** 19 | * Sample user class. 20 | * 21 | * @author Oliver Gierke 22 | * @author Thomas Darimont 23 | * @author Mark Paluch 24 | */ 25 | public class User { 26 | private String id; 27 | 28 | private String username; 29 | private String firstname; 30 | private String lastname; 31 | 32 | public User() { 33 | } 34 | 35 | public User(String id) { 36 | this.setId(id); 37 | } 38 | 39 | public User(String username, String firstname, String lastname, String id) { 40 | this.username = username; 41 | this.firstname = firstname; 42 | this.lastname = lastname; 43 | this.id = id; 44 | } 45 | 46 | public String getId() { 47 | return id; 48 | } 49 | 50 | public void setId(String id) { 51 | this.id = id; 52 | } 53 | 54 | public String getUsername() { 55 | return username; 56 | } 57 | 58 | public void setUsername(String username) { 59 | this.username = username; 60 | } 61 | 62 | public String getFirstname() { 63 | return firstname; 64 | } 65 | 66 | public void setFirstname(String firstname) { 67 | this.firstname = firstname; 68 | } 69 | 70 | public String getLastname() { 71 | return lastname; 72 | } 73 | 74 | public void setLastname(String lastname) { 75 | this.lastname = lastname; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /session/src/main/java/com/example/sleuthsamples/SessionApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import javax.servlet.http.HttpSession; 4 | 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.aspectj.lang.annotation.Around; 7 | import org.aspectj.lang.annotation.Aspect; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import org.springframework.boot.SpringApplication; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.cloud.sleuth.Tracer; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | @SpringBootApplication 19 | public class SessionApplication { 20 | 21 | public static void main(String... args) { 22 | new SpringApplication(SessionApplication.class).run(args); 23 | } 24 | } 25 | 26 | @RestController 27 | class SessionController { 28 | private static final Logger log = LoggerFactory.getLogger(SessionController.class); 29 | 30 | @GetMapping("/") 31 | public String span(HttpSession httpSession) { 32 | log.info("Session id {}", httpSession.getId()); 33 | return httpSession.getId(); 34 | } 35 | } 36 | 37 | // This is only for test purposes. In your code you won't be doing this. 38 | @Aspect 39 | @Component 40 | class TestSessionRepositoryAspect { 41 | private static final Logger log = LoggerFactory.getLogger(TestSessionRepositoryAspect.class); 42 | 43 | private final Tracer tracer; 44 | 45 | public TestSessionRepositoryAspect(Tracer tracer) { 46 | this.tracer = tracer; 47 | } 48 | 49 | @Around("execution(public * org.springframework.session.SessionRepository.createSession(..))") 50 | public Object wrapSessionRepository(ProceedingJoinPoint pjp) throws Throwable { 51 | String traceId = this.tracer.currentSpan().context().traceId(); 52 | log.info(" Hello from producer", traceId); 53 | return pjp.proceed(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /data-reactive/src/main/java/com/example/sleuthsamples/ReactiveContinuedTransactionService.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import reactor.core.publisher.Mono; 6 | 7 | import org.springframework.cloud.sleuth.Tracer; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | @Service 12 | public class ReactiveContinuedTransactionService { 13 | 14 | private static final Logger log = LoggerFactory.getLogger(ReactiveContinuedTransactionService.class); 15 | 16 | private final ReactiveCustomerRepository repository; 17 | 18 | private final Tracer tracer; 19 | 20 | private final ReactiveNestedTransactionService reactiveNestedTransactionService; 21 | 22 | public ReactiveContinuedTransactionService(ReactiveCustomerRepository repository, Tracer tracer, ReactiveNestedTransactionService reactiveNestedTransactionService) { 23 | this.repository = repository; 24 | this.tracer = tracer; 25 | this.reactiveNestedTransactionService = reactiveNestedTransactionService; 26 | } 27 | 28 | @Transactional 29 | public Mono continuedTransaction() { 30 | return Mono.fromRunnable(() -> log.info(" Hello from consumer", tracer.currentSpan().context().traceId())) 31 | .then(repository.findById(1L)) 32 | .doOnNext(customer -> { 33 | // fetch an individual customer by ID 34 | log.info("Customer found with findById(1L):"); 35 | log.info("--------------------------------"); 36 | log.info(customer.toString()); 37 | log.info(""); 38 | }) 39 | .doOnNext(customer -> { 40 | // fetch customers by last name 41 | log.info("Customer found with findByLastName('Bauer'):"); 42 | log.info("--------------------------------------------"); 43 | }) 44 | .flatMapMany(customer -> repository.findByLastName("Bauer")) 45 | .doOnNext(cust -> log.info(cust.toString())) 46 | .then(this.reactiveNestedTransactionService.requiresNew()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /security/src/main/java/com/example/sleuthsamples/SpringSecurityApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.sleuthsamples; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | import org.springframework.beans.factory.BeanFactory; 23 | import org.springframework.boot.SpringApplication; 24 | import org.springframework.boot.autoconfigure.SpringBootApplication; 25 | import org.springframework.cloud.sleuth.Tracer; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.security.core.context.SecurityContextChangedListener; 28 | 29 | /** 30 | * Sample app to demonstrate instrumentation of Spring Security. 31 | * 32 | * @author Jonatan Ivanov 33 | */ 34 | @SpringBootApplication 35 | public class SpringSecurityApplication { 36 | 37 | private static final Logger log = LoggerFactory.getLogger(SecurityController.class); 38 | 39 | public static void main(String[] args) { 40 | SpringApplication.run(SpringSecurityApplication.class, args); 41 | } 42 | 43 | // This only needed for tests - you don't need this bean 44 | @Bean 45 | SecurityContextChangedListener testSecurityContextChangedListener(BeanFactory beanFactory) { 46 | return event -> { 47 | Tracer tracer = beanFactory.getBean(Tracer.class); 48 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /stream-producer/src/main/java/com/example/sleuthsamples/StreamProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.WebApplicationType; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import org.springframework.boot.builder.SpringApplicationBuilder; 12 | import org.springframework.cloud.sleuth.Span; 13 | import org.springframework.cloud.sleuth.Tracer; 14 | import org.springframework.cloud.stream.function.StreamBridge; 15 | import org.springframework.stereotype.Service; 16 | import org.springframework.web.client.RestTemplate; 17 | 18 | @SpringBootApplication 19 | public class StreamProducerApplication implements CommandLineRunner { 20 | 21 | public static void main(String... args) { 22 | new SpringApplicationBuilder(StreamProducerApplication.class).web(WebApplicationType.NONE).run(args); 23 | } 24 | 25 | @Autowired 26 | StreamBridgeService streamBridgeService; 27 | 28 | @Override 29 | public void run(String... args) throws Exception { 30 | this.streamBridgeService.call(); 31 | } 32 | } 33 | 34 | @Service 35 | class StreamBridgeService { 36 | private static final Logger log = LoggerFactory.getLogger(StreamBridgeService.class); 37 | 38 | private final StreamBridge streamBridge; 39 | 40 | private final Tracer tracer; 41 | 42 | StreamBridgeService(StreamBridge streamBridge, Tracer tracer) { 43 | this.streamBridge = streamBridge; 44 | this.tracer = tracer; 45 | } 46 | 47 | void call() { 48 | Span span = this.tracer.nextSpan(); 49 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 50 | log.info(" Hello from producer", this.tracer.currentSpan().context().traceId()); 51 | this.streamBridge.send("channel-out-0", "HELLO"); 52 | } finally { 53 | span.end(); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /stream-reactive-consumer/src/main/java/com/example/sleuthsamples/StreamReactiveConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.function.Consumer; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import reactor.core.publisher.Flux; 8 | 9 | import org.springframework.boot.CommandLineRunner; 10 | import org.springframework.boot.WebApplicationType; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.boot.builder.SpringApplicationBuilder; 13 | import org.springframework.cloud.sleuth.Tracer; 14 | import org.springframework.context.annotation.Bean; 15 | import org.springframework.messaging.Message; 16 | 17 | @SpringBootApplication 18 | public class StreamReactiveConsumerApplication implements CommandLineRunner { 19 | 20 | private static final Logger log = LoggerFactory.getLogger(StreamReactiveConsumerApplication.class); 21 | 22 | public static void main(String... args) { 23 | new SpringApplicationBuilder(StreamReactiveConsumerApplication.class).web(WebApplicationType.NONE).run(args); 24 | } 25 | 26 | @Override 27 | public void run(String... args) throws Exception { 28 | log.warn("Remember about calling <.subscribe()> at the end of your Consumer bean!"); 29 | log.warn("Remember about finishing the span manually before calling subscribe!"); 30 | } 31 | 32 | @Bean 33 | Consumer>> channel(Tracer tracer) { 34 | // For the reactive consumer remember to call "subscribe()" at the end, otherwise 35 | // you'll get the "Dispatcher has no subscribers" error 36 | return i -> i 37 | .doOnNext(s -> 38 | log.info(" Hello from consumer", tracer.currentSpan().context().traceId())) 39 | // You must finish the span yourself and clear the tracing context like presented below. 40 | // Otherwise you will be missing out the span that wraps the function execution. 41 | .doOnNext(s -> { 42 | tracer.currentSpan().end(); 43 | tracer.withSpan(null); 44 | }) 45 | .subscribe(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /data-reactive/src/main/java/com/example/sleuthsamples/ReactiveNewTransactionService.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import reactor.core.publisher.Mono; 6 | 7 | import org.springframework.cloud.sleuth.Tracer; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | @Service 12 | public class ReactiveNewTransactionService { 13 | 14 | private static final Logger log = LoggerFactory.getLogger(ReactiveNewTransactionService.class); 15 | 16 | private final ReactiveCustomerRepository repository; 17 | 18 | private final ReactiveContinuedTransactionService reactiveContinuedTransactionService; 19 | 20 | private final Tracer tracer; 21 | 22 | public ReactiveNewTransactionService(ReactiveCustomerRepository repository, ReactiveContinuedTransactionService reactiveContinuedTransactionService, Tracer tracer) { 23 | this.repository = repository; 24 | this.reactiveContinuedTransactionService = reactiveContinuedTransactionService; 25 | this.tracer = tracer; 26 | } 27 | 28 | @Transactional 29 | public Mono newTransaction() { 30 | return Mono.fromRunnable(() -> log.info(" Hello from producer", tracer.currentSpan().context().traceId())) 31 | // save a few customers 32 | .then(repository.save(new ReactiveCustomer("Jack", "Bauer"))) 33 | .then(repository.save(new ReactiveCustomer("Chloe", "O'Brian"))) 34 | .then(repository.save(new ReactiveCustomer("Kim", "Bauer"))) 35 | .then(repository.save(new ReactiveCustomer("David", "Palmer"))) 36 | .then(repository.save(new ReactiveCustomer("Michelle", "Dessler"))) 37 | .doOnNext(reactiveCustomer -> { 38 | log.info("Customers found with findAll():"); 39 | log.info("-------------------------------"); 40 | }) 41 | .flatMapMany(reactiveCustomer -> repository.findAll()) 42 | .doOnNext(cust -> log.info(cust.toString())) 43 | .doOnNext(o -> log.info("")) 44 | .then(this.reactiveContinuedTransactionService.continuedTransaction()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/KafkaAcceptanceTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Map; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.TestInfo; 7 | import org.testcontainers.containers.KafkaContainer; 8 | import org.testcontainers.junit.jupiter.Container; 9 | import org.testcontainers.junit.jupiter.Testcontainers; 10 | import org.testcontainers.utility.DockerImageName; 11 | 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | 14 | // Uncomment the properties to rebuild the projects 15 | // @formatter:off 16 | @SpringBootTest( 17 | // properties = {"spring.cloud.sleuth.samples.rebuild-projects=true", "spring.cloud.sleuth.samples.project-root=${user.home}/repo/spring-cloud-sleuth-samples", "maven.home=${user.home}/.sdkman/candidates/maven/current"} 18 | ) 19 | @Testcontainers 20 | // @formatter:on 21 | class KafkaAcceptanceTests extends AcceptanceTestsBase { 22 | 23 | @Container 24 | static KafkaContainer broker = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka").withTag("5.4.3")); 25 | 26 | @Test 27 | void should_pass_tracing_context_from_kafka_producer_to_consumer(TestInfo testInfo) throws Exception { 28 | // given 29 | String consumerId = wait10seconds(() -> deploy(testInfo, "kafka-consumer", brokerSetup())); 30 | 31 | // when 32 | String producerId = deploy(testInfo, "kafka-producer", brokerSetup()); 33 | 34 | // then 35 | assertThatTraceIdGotPropagated(producerId, consumerId); 36 | } 37 | 38 | @Test 39 | void should_pass_tracing_context_from_stream_reactive_producer_to_reactive_consumer(TestInfo testInfo) throws Exception { 40 | // given 41 | String consumerId = wait10seconds(() -> deploy(testInfo, "kafka-reactive-consumer", brokerSetup())); 42 | 43 | // when 44 | String producerId = deploy(testInfo, "kafka-reactive-producer", brokerSetup()); 45 | 46 | // then 47 | assertThatTraceIdGotPropagated(producerId, consumerId); 48 | } 49 | 50 | private Map brokerSetup() { 51 | return Map.of("spring.kafka.bootstrap-servers", broker.getBootstrapServers()); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /kafka-consumer/src/main/java/com/example/sleuthsamples/KafkaConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.apache.kafka.clients.admin.NewTopic; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.WebApplicationType; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.boot.builder.SpringApplicationBuilder; 11 | import org.springframework.cloud.sleuth.Span; 12 | import org.springframework.cloud.sleuth.Tracer; 13 | import org.springframework.context.annotation.Bean; 14 | import org.springframework.kafka.annotation.EnableKafka; 15 | import org.springframework.kafka.annotation.KafkaListener; 16 | import org.springframework.messaging.Message; 17 | 18 | @SpringBootApplication 19 | @EnableKafka 20 | public class KafkaConsumerApplication implements CommandLineRunner { 21 | 22 | public static void main(String... args) { 23 | new SpringApplicationBuilder(KafkaConsumerApplication.class).web(WebApplicationType.NONE).run(args); 24 | } 25 | 26 | @Override 27 | public void run(String... args) throws Exception { 28 | 29 | } 30 | 31 | @Bean 32 | NewTopic myTopic() { 33 | return new NewTopic("mytopic", 1, (short) 1); 34 | } 35 | 36 | @Bean 37 | MyKafkaListener myKafkaListener(Tracer tracer) { 38 | return new MyKafkaListener(tracer); 39 | } 40 | } 41 | 42 | class MyKafkaListener { 43 | 44 | private static final Logger log = LoggerFactory.getLogger(MyKafkaListener.class); 45 | 46 | private final Tracer tracer; 47 | 48 | MyKafkaListener(Tracer tracer) { 49 | this.tracer = tracer; 50 | } 51 | 52 | @KafkaListener(topics = "mytopic", groupId = "group") 53 | void onMessage(Message message) { 54 | Span span = this.tracer.nextSpan().name("on-message").start(); 55 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span)) { 56 | log.info("Got message <{}>", message.getPayload()); 57 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 58 | } finally { 59 | span.end(); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /circuitbreaker/src/main/java/com/example/sleuthsamples/CircuitBreakerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.WebApplicationType; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.boot.builder.SpringApplicationBuilder; 11 | import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; 12 | import org.springframework.cloud.sleuth.Span; 13 | import org.springframework.cloud.sleuth.Tracer; 14 | import org.springframework.stereotype.Service; 15 | 16 | @SpringBootApplication 17 | public class CircuitBreakerApplication implements CommandLineRunner { 18 | 19 | public static void main(String... args) { 20 | new SpringApplicationBuilder(CircuitBreakerApplication.class).web(WebApplicationType.NONE).run(args); 21 | } 22 | 23 | @Autowired 24 | CircuitService circuitService; 25 | 26 | @Override 27 | public void run(String... args) throws Exception { 28 | this.circuitService.call(); 29 | } 30 | } 31 | 32 | @Service 33 | class CircuitService { 34 | private static final Logger log = LoggerFactory.getLogger(CircuitService.class); 35 | 36 | private final CircuitBreakerFactory factory; 37 | 38 | private final Tracer tracer; 39 | 40 | CircuitService(CircuitBreakerFactory factory, Tracer tracer) { 41 | this.factory = factory; 42 | this.tracer = tracer; 43 | } 44 | 45 | String call() { 46 | Span span = this.tracer.nextSpan(); 47 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 48 | return this.factory.create("circuit").run(() -> { 49 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 50 | throw new IllegalStateException("BOOM"); 51 | }, throwable -> { 52 | log.info(" Hello from producer", this.tracer.currentSpan().context().traceId()); 53 | return "fallback"; 54 | }); 55 | } finally { 56 | span.end(); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /openfeign/src/main/java/com/example/sleuthsamples/OpenFeignApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.WebApplicationType; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.boot.builder.SpringApplicationBuilder; 11 | import org.springframework.cloud.openfeign.EnableFeignClients; 12 | import org.springframework.cloud.openfeign.FeignClient; 13 | import org.springframework.cloud.sleuth.Span; 14 | import org.springframework.cloud.sleuth.Tracer; 15 | import org.springframework.stereotype.Service; 16 | import org.springframework.web.bind.annotation.GetMapping; 17 | 18 | @SpringBootApplication 19 | @EnableFeignClients 20 | public class OpenFeignApplication implements CommandLineRunner { 21 | 22 | public static void main(String... args) { 23 | new SpringApplicationBuilder(OpenFeignApplication.class).web(WebApplicationType.NONE).run(args); 24 | } 25 | 26 | @Autowired 27 | OpenFeignService openFeignService; 28 | 29 | @Override 30 | public void run(String... args) throws Exception { 31 | this.openFeignService.call(); 32 | } 33 | } 34 | 35 | @Service 36 | class OpenFeignService { 37 | private static final Logger log = LoggerFactory.getLogger(OpenFeignService.class); 38 | 39 | private final ProducerClient producerClient; 40 | 41 | private final Tracer tracer; 42 | 43 | OpenFeignService(ProducerClient producerClient, Tracer tracer) { 44 | this.producerClient = producerClient; 45 | this.tracer = tracer; 46 | } 47 | 48 | String call() { 49 | Span span = this.tracer.nextSpan(); 50 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 51 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 52 | return this.producerClient.callProducer(); 53 | } finally { 54 | span.end(); 55 | } 56 | } 57 | } 58 | 59 | @FeignClient(url = "${url:http://localhost:7100}", name = "producer") 60 | interface ProducerClient { 61 | @GetMapping 62 | String callProducer(); 63 | } -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/RabbitAcceptanceTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Map; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.TestInfo; 7 | import org.testcontainers.containers.RabbitMQContainer; 8 | import org.testcontainers.junit.jupiter.Container; 9 | import org.testcontainers.junit.jupiter.Testcontainers; 10 | 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | 13 | // Uncomment the properties to rebuild the projects 14 | // @formatter:off 15 | @SpringBootTest( 16 | // properties = {"spring.cloud.sleuth.samples.rebuild-projects=true", "spring.cloud.sleuth.samples.project-root=${user.home}/repo/spring-cloud-sleuth-samples", "maven.home=${user.home}/.sdkman/candidates/maven/current"} 17 | ) 18 | @Testcontainers 19 | // @formatter:on 20 | class RabbitAcceptanceTests extends AcceptanceTestsBase { 21 | 22 | @Container 23 | static RabbitMQContainer broker = new RabbitMQContainer("rabbitmq:3.7.25-management-alpine"); 24 | 25 | @Test 26 | void should_pass_tracing_context_from_stream_producer_to_consumer(TestInfo testInfo) throws Exception { 27 | // given 28 | String consumerId = wait10seconds(() -> deploy(testInfo, "stream-consumer", brokerSetup())); 29 | 30 | // when 31 | String producerId = deploy(testInfo, "stream-producer", brokerSetup()); 32 | 33 | // then 34 | assertThatTraceIdGotPropagated(producerId, consumerId); 35 | } 36 | 37 | @Test 38 | void should_pass_tracing_context_from_stream_reactive_producer_to_reactive_consumer(TestInfo testInfo) throws Exception { 39 | // given 40 | String consumerId = wait10seconds(() -> deploy(testInfo, "stream-reactive-consumer", brokerSetup())); 41 | 42 | // when 43 | String producerId = deploy(testInfo, "stream-reactive-producer", brokerSetup()); 44 | 45 | // then 46 | assertThatTraceIdGotPropagated(producerId, consumerId); 47 | } 48 | 49 | @Test 50 | void should_pass_tracing_context_with_bus(TestInfo testInfo) { 51 | // when 52 | String producerId = deploy(testInfo, "bus", brokerSetup()); 53 | 54 | // then 55 | assertThatTraceIdGotPropagated(producerId); 56 | } 57 | 58 | private Map brokerSetup() { 59 | return Map.of("spring.rabbitmq.port", broker.getAmqpPort().toString()); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /gateway/src/main/java/com/example/sleuthsamples/GatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import reactor.core.publisher.Mono; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.boot.CommandLineRunner; 10 | import org.springframework.boot.SpringApplication; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.cloud.gateway.route.RouteLocator; 13 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; 14 | import org.springframework.cloud.sleuth.Tracer; 15 | import org.springframework.context.annotation.Bean; 16 | import org.springframework.core.env.Environment; 17 | import org.springframework.web.bind.annotation.RequestMapping; 18 | import org.springframework.web.bind.annotation.RestController; 19 | import org.springframework.web.client.RestTemplate; 20 | 21 | @SpringBootApplication 22 | public class GatewayApplication implements CommandLineRunner { 23 | private static final Logger log = LoggerFactory.getLogger(GatewayApplication.class); 24 | 25 | public static void main(String... args) { 26 | new SpringApplication(GatewayApplication.class).run(args); 27 | } 28 | 29 | @Bean 30 | RouteLocator myRouteLocator(RouteLocatorBuilder builder, Tracer tracer, @Value("${url:http://localhost:7100}") String url) { 31 | return builder.routes() 32 | .route("mvc_route", 33 | route -> route 34 | .path("/mvc/**") 35 | .filters(f -> f.stripPrefix(1).filter((exchange, chain) -> { 36 | String traceId = tracer.currentSpan().context().traceId(); 37 | log.info(" Hello from consumer", traceId); 38 | return chain.filter(exchange); 39 | })) 40 | .uri(url) 41 | ).build(); 42 | } 43 | 44 | @Autowired 45 | Environment environment; 46 | 47 | @Override 48 | public void run(String... args) throws Exception { 49 | try { 50 | new RestTemplate().getForObject("http://localhost:" + environment.getProperty("server.port") + "/mvc/", String.class); 51 | } catch (Exception exception) { 52 | log.error("Failed to reach the mvc application", exception); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /cassandra/src/main/java/com/example/sleuthsamples/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | import org.springframework.data.cassandra.core.mapping.Column; 19 | import org.springframework.data.cassandra.core.mapping.PrimaryKey; 20 | import org.springframework.data.cassandra.core.mapping.Table; 21 | 22 | /** 23 | * Sample user class. 24 | * 25 | * @author Oliver Gierke 26 | * @author Thomas Darimont 27 | * @author Mark Paluch 28 | */ 29 | @Table(value = "users") 30 | public class User { 31 | @PrimaryKey("user_id") 32 | private Long id; 33 | 34 | @Column("uname") 35 | private String username; 36 | @Column("fname") 37 | private String firstname; 38 | @Column("lname") 39 | private String lastname; 40 | 41 | public User() { 42 | } 43 | 44 | public User(Long id) { 45 | this.setId(id); 46 | } 47 | 48 | public User(String username, String firstname, String lastname, Long id) { 49 | this.username = username; 50 | this.firstname = firstname; 51 | this.lastname = lastname; 52 | this.id = id; 53 | } 54 | 55 | public Long getId() { 56 | return id; 57 | } 58 | 59 | public void setId(Long id) { 60 | this.id = id; 61 | } 62 | 63 | public String getUsername() { 64 | return username; 65 | } 66 | 67 | public void setUsername(String username) { 68 | this.username = username; 69 | } 70 | 71 | public String getFirstname() { 72 | return firstname; 73 | } 74 | 75 | public void setFirstname(String firstname) { 76 | this.firstname = firstname; 77 | } 78 | 79 | public String getLastname() { 80 | return lastname; 81 | } 82 | 83 | public void setLastname(String lastname) { 84 | this.lastname = lastname; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /cassandra-reactive/src/main/java/com/example/sleuthsamples/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.example.sleuthsamples; 17 | 18 | import org.springframework.data.cassandra.core.mapping.Column; 19 | import org.springframework.data.cassandra.core.mapping.PrimaryKey; 20 | import org.springframework.data.cassandra.core.mapping.Table; 21 | 22 | /** 23 | * Sample user class. 24 | * 25 | * @author Oliver Gierke 26 | * @author Thomas Darimont 27 | * @author Mark Paluch 28 | */ 29 | @Table(value = "users") 30 | public class User { 31 | @PrimaryKey("user_id") 32 | private Long id; 33 | 34 | @Column("uname") 35 | private String username; 36 | @Column("fname") 37 | private String firstname; 38 | @Column("lname") 39 | private String lastname; 40 | 41 | public User() { 42 | } 43 | 44 | public User(Long id) { 45 | this.setId(id); 46 | } 47 | 48 | public User(String username, String firstname, String lastname, Long id) { 49 | this.username = username; 50 | this.firstname = firstname; 51 | this.lastname = lastname; 52 | this.id = id; 53 | } 54 | 55 | public Long getId() { 56 | return id; 57 | } 58 | 59 | public void setId(Long id) { 60 | this.id = id; 61 | } 62 | 63 | public String getUsername() { 64 | return username; 65 | } 66 | 67 | public void setUsername(String username) { 68 | this.username = username; 69 | } 70 | 71 | public String getFirstname() { 72 | return firstname; 73 | } 74 | 75 | public void setFirstname(String firstname) { 76 | this.firstname = firstname; 77 | } 78 | 79 | public String getLastname() { 80 | return lastname; 81 | } 82 | 83 | public void setLastname(String lastname) { 84 | this.lastname = lastname; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/CassandraAcceptanceTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Map; 4 | 5 | import com.datastax.driver.core.Cluster; 6 | import com.datastax.driver.core.Session; 7 | import org.junit.jupiter.api.BeforeAll; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.TestInfo; 10 | import org.testcontainers.containers.CassandraContainer; 11 | import org.testcontainers.junit.jupiter.Container; 12 | import org.testcontainers.junit.jupiter.Testcontainers; 13 | import org.testcontainers.vault.VaultContainer; 14 | 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.test.context.DynamicPropertyRegistry; 17 | 18 | // Uncomment the properties to rebuild the projects 19 | // @formatter:off 20 | @SpringBootTest( 21 | // properties = {"spring.cloud.sleuth.samples.rebuild-projects=true", "spring.cloud.sleuth.samples.project-root=${user.home}/repo/spring-cloud-sleuth-samples", "maven.home=${user.home}/.sdkman/candidates/maven/current"} 22 | ) 23 | @Testcontainers 24 | // @formatter:on 25 | class CassandraAcceptanceTests extends AcceptanceTestsBase { 26 | 27 | @Container 28 | static CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2"); 29 | 30 | @BeforeAll 31 | static void setup() { 32 | Cluster cluster = cassandra.getCluster(); 33 | try (Session session = cluster.connect()) { 34 | session.execute("CREATE KEYSPACE IF NOT EXISTS example WITH replication = \n" + 35 | "{'class':'SimpleStrategy','replication_factor':'1'};"); 36 | } 37 | } 38 | 39 | @Test 40 | void should_pass_tracing_context_with_cassandra(TestInfo testInfo) { 41 | // when 42 | String producerId = deploy(testInfo, "cassandra", port()); 43 | 44 | // then 45 | assertThatLogsContainPropagatedIdAtLeastXNumberOfTimes(producerId, "cassandra", 7); 46 | } 47 | 48 | @Test 49 | void should_pass_tracing_context_with_cassandra_reactive(TestInfo testInfo) { 50 | // when 51 | String producerId = deploy(testInfo, "cassandra-reactive", port()); 52 | 53 | // then 54 | assertThatLogsContainPropagatedIdAtLeastXNumberOfTimes(producerId, "cassandra-reactive", 7); 55 | } 56 | 57 | private Map port() { 58 | return Map.of("spring.data.cassandra.contact-points", cassandra.getContainerIpAddress() + ":" + cassandra.getFirstMappedPort()); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /config-server/src/main/java/com/example/sleuthsamples/ConfigServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.boot.builder.SpringApplicationBuilder; 10 | import org.springframework.cloud.config.server.EnableConfigServer; 11 | import org.springframework.cloud.sleuth.Span; 12 | import org.springframework.cloud.sleuth.Tracer; 13 | import org.springframework.context.annotation.Bean; 14 | import org.springframework.context.annotation.Configuration; 15 | import org.springframework.core.env.Environment; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.web.client.RestTemplate; 18 | 19 | @SpringBootApplication 20 | @EnableConfigServer 21 | public class ConfigServerApplication implements CommandLineRunner { 22 | 23 | public static void main(String... args) { 24 | new SpringApplicationBuilder(ConfigServerApplication.class).run(args); 25 | } 26 | 27 | @Autowired 28 | WebClientService webClientService; 29 | 30 | @Override 31 | public void run(String... args) throws Exception { 32 | this.webClientService.call(); 33 | } 34 | } 35 | 36 | @Configuration 37 | class Config { 38 | @Bean 39 | RestTemplate restTemplate() { 40 | return new RestTemplate(); 41 | } 42 | } 43 | 44 | @Service 45 | class WebClientService { 46 | 47 | private static final Logger log = LoggerFactory.getLogger(WebClientService.class); 48 | 49 | private final Environment environment; 50 | 51 | private final RestTemplate restTemplate; 52 | 53 | private final Tracer tracer; 54 | 55 | WebClientService(Environment environment, RestTemplate restTemplate, Tracer tracer) { 56 | this.environment = environment; 57 | this.restTemplate = restTemplate; 58 | this.tracer = tracer; 59 | } 60 | 61 | void call() { 62 | Span hello = this.tracer.nextSpan().name("hello"); 63 | try (Tracer.SpanInScope spanInScope = this.tracer.withSpan(hello.start())) { 64 | int port = environment.getProperty("server.port", Integer.class, 8888); 65 | log.info("Got back the following response from config server \n{}", this.restTemplate.getForObject("http://localhost:" + port + "/main-application.yml", String.class)); 66 | } finally { 67 | hello.end(); 68 | } 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /data-reactive/src/main/java/com/example/sleuthsamples/ReactiveDataApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.time.Duration; 4 | import java.util.ArrayList; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | import java.util.function.Function; 8 | 9 | import io.r2dbc.proxy.ProxyConnectionFactory; 10 | import io.r2dbc.proxy.callback.ProxyConfig; 11 | import io.r2dbc.proxy.core.MethodExecutionInfo; 12 | import io.r2dbc.proxy.core.QueryExecutionInfo; 13 | import io.r2dbc.proxy.core.QueryInfo; 14 | import io.r2dbc.proxy.listener.ProxyExecutionListener; 15 | import io.r2dbc.spi.ConnectionFactory; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | import org.springframework.beans.BeansException; 20 | import org.springframework.beans.factory.BeanFactory; 21 | import org.springframework.beans.factory.ObjectProvider; 22 | import org.springframework.beans.factory.config.BeanPostProcessor; 23 | import org.springframework.boot.CommandLineRunner; 24 | import org.springframework.boot.WebApplicationType; 25 | import org.springframework.boot.autoconfigure.SpringBootApplication; 26 | import org.springframework.boot.builder.SpringApplicationBuilder; 27 | import org.springframework.cloud.sleuth.Span; 28 | import org.springframework.cloud.sleuth.Tracer; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.core.ParameterizedTypeReference; 31 | import org.springframework.core.ResolvableType; 32 | import org.springframework.core.io.ClassPathResource; 33 | import org.springframework.dao.DataAccessException; 34 | import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer; 35 | import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator; 36 | 37 | @SpringBootApplication 38 | public class ReactiveDataApplication { 39 | 40 | private static final Logger log = LoggerFactory.getLogger(ReactiveDataApplication.class); 41 | 42 | public static void main(String... args) { 43 | new SpringApplicationBuilder(ReactiveDataApplication.class).web(WebApplicationType.NONE) 44 | .run(args); 45 | } 46 | 47 | @Bean 48 | public CommandLineRunner demo(ReactiveNewTransactionService reactiveNewTransactionService) { 49 | return (args) -> { 50 | try { 51 | reactiveNewTransactionService.newTransaction().block(Duration.ofSeconds(50)); 52 | } 53 | catch (DataAccessException e) { 54 | log.info("Expected to throw an exception so that we see if rollback works", e); 55 | } 56 | }; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /webclient/src/main/java/com/example/sleuthsamples/WebClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.time.Duration; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import reactor.core.publisher.Mono; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.boot.CommandLineRunner; 12 | import org.springframework.boot.WebApplicationType; 13 | import org.springframework.boot.autoconfigure.SpringBootApplication; 14 | import org.springframework.boot.builder.SpringApplicationBuilder; 15 | import org.springframework.cloud.sleuth.Span; 16 | import org.springframework.cloud.sleuth.Tracer; 17 | import org.springframework.context.annotation.Bean; 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.stereotype.Service; 20 | import org.springframework.web.reactive.function.client.WebClient; 21 | 22 | @SpringBootApplication 23 | public class WebClientApplication implements CommandLineRunner { 24 | 25 | public static void main(String... args) { 26 | new SpringApplicationBuilder(WebClientApplication.class).web(WebApplicationType.NONE).run(args); 27 | } 28 | 29 | @Autowired 30 | WebClientService webClientService; 31 | 32 | @Override 33 | public void run(String... args) throws Exception { 34 | this.webClientService.call().block(Duration.ofSeconds(5)); 35 | // To ensure that the spans got successfully reported 36 | Thread.sleep(500); 37 | } 38 | } 39 | 40 | @Configuration 41 | class Config { 42 | // You must register WebClient as a bean! 43 | @Bean 44 | WebClient webClient(@Value("${url:http://localhost:7110}") String url) { 45 | return WebClient.builder().baseUrl(url).build(); 46 | } 47 | } 48 | 49 | @Service 50 | class WebClientService { 51 | private static final Logger log = LoggerFactory.getLogger(WebClientService.class); 52 | 53 | private final WebClient webClient; 54 | 55 | private final Tracer tracer; 56 | 57 | WebClientService(WebClient webClient, Tracer tracer) { 58 | this.webClient = webClient; 59 | this.tracer = tracer; 60 | } 61 | 62 | Mono call() { 63 | Span nextSpan = this.tracer.nextSpan().name("client"); 64 | return Mono.just(nextSpan) 65 | .doOnNext(span -> this.tracer.withSpan(span.start())) 66 | .flatMap(span -> { 67 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 68 | return this.webClient.get().retrieve().bodyToMono(String.class); 69 | }) 70 | .doFinally(signalType -> nextSpan.end()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /bus/src/main/java/com/example/sleuthsamples/BusApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.WebApplicationType; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.boot.builder.SpringApplicationBuilder; 11 | import org.springframework.cloud.bus.BusProperties; 12 | import org.springframework.cloud.bus.event.MyEvent; 13 | import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan; 14 | import org.springframework.cloud.sleuth.Span; 15 | import org.springframework.cloud.sleuth.Tracer; 16 | import org.springframework.context.ApplicationEventPublisher; 17 | import org.springframework.context.annotation.Configuration; 18 | import org.springframework.context.event.EventListener; 19 | import org.springframework.web.bind.annotation.RestController; 20 | 21 | @SpringBootApplication 22 | public class BusApplication implements CommandLineRunner { 23 | 24 | public static void main(String... args) { 25 | new SpringApplicationBuilder(BusApplication.class).web(WebApplicationType.NONE).run(args); 26 | } 27 | 28 | @Autowired 29 | MyEventService myEventService; 30 | 31 | @Override 32 | public void run(String... args) throws Exception { 33 | this.myEventService.publish(); 34 | } 35 | } 36 | 37 | @Configuration 38 | @RemoteApplicationEventScan(basePackageClasses = MyEvent.class) 39 | class EventConfig { 40 | 41 | } 42 | 43 | @RestController 44 | class MyEventService { 45 | private static final Logger log = LoggerFactory.getLogger(MyEventService.class); 46 | 47 | private final ApplicationEventPublisher publisher; 48 | 49 | private final BusProperties bus; 50 | 51 | private final Tracer tracer; 52 | 53 | MyEventService(ApplicationEventPublisher publisher, BusProperties bus, Tracer tracer) { 54 | this.publisher = publisher; 55 | this.bus = bus; 56 | this.tracer = tracer; 57 | } 58 | 59 | void publish() { 60 | Span span = this.tracer.nextSpan(); 61 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 62 | log.info(" Hello from producer", this.tracer.currentSpan().context().traceId()); 63 | publisher.publishEvent(new MyEvent(this, this.bus.getId())); 64 | } 65 | finally { 66 | span.end(); 67 | } 68 | } 69 | 70 | @EventListener(MyEvent.class) 71 | public void gotLoanIssued() { 72 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /batch/src/main/java/com/example/sleuthsamples/BatchApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.batch.core.Job; 7 | import org.springframework.batch.core.JobExecution; 8 | import org.springframework.batch.core.JobExecutionListener; 9 | import org.springframework.batch.core.JobParameters; 10 | import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; 11 | import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; 12 | import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; 13 | import org.springframework.batch.core.launch.JobLauncher; 14 | import org.springframework.batch.repeat.RepeatStatus; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.boot.CommandLineRunner; 17 | import org.springframework.boot.WebApplicationType; 18 | import org.springframework.boot.autoconfigure.SpringBootApplication; 19 | import org.springframework.boot.builder.SpringApplicationBuilder; 20 | import org.springframework.cloud.sleuth.Tracer; 21 | 22 | @SpringBootApplication 23 | @EnableBatchProcessing 24 | public class BatchApplication implements CommandLineRunner { 25 | private static final Logger log = LoggerFactory.getLogger(BatchApplication.class); 26 | 27 | public static void main(String... args) { 28 | new SpringApplicationBuilder(BatchApplication.class).web(WebApplicationType.NONE).run(args); 29 | } 30 | 31 | @Autowired 32 | Tracer tracer; 33 | 34 | @Autowired 35 | StepBuilderFactory stepBuilderFactory; 36 | 37 | @Autowired 38 | JobBuilderFactory jobBuilderFactory; 39 | 40 | @Autowired 41 | JobLauncher jobLauncher; 42 | 43 | @Override 44 | public void run(String... args) throws Exception { 45 | Job job = this.jobBuilderFactory.get("myJob") 46 | .listener(new JobExecutionListener() { 47 | @Override 48 | public void beforeJob(JobExecution jobExecution) { 49 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 50 | } 51 | 52 | @Override 53 | public void afterJob(JobExecution jobExecution) { 54 | 55 | } 56 | }) 57 | .start(this.stepBuilderFactory.get("myTask").tasklet((stepContribution, chunkContext) -> { 58 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 59 | return RepeatStatus.FINISHED; 60 | }).build()).build(); 61 | 62 | this.jobLauncher.run(job, new JobParameters()); 63 | // To ensure that the spans got successfully reported 64 | Thread.sleep(500); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /vault-resttemplate/src/main/java/com/example/sleuthsamples/VaultRestTemplateApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.WebApplicationType; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import org.springframework.boot.builder.SpringApplicationBuilder; 12 | import org.springframework.cloud.sleuth.Span; 13 | import org.springframework.cloud.sleuth.Tracer; 14 | import org.springframework.context.annotation.Bean; 15 | import org.springframework.stereotype.Service; 16 | import org.springframework.vault.client.RestTemplateCustomizer; 17 | import org.springframework.vault.core.VaultTemplate; 18 | import org.springframework.vault.support.VaultResponse; 19 | 20 | @SpringBootApplication 21 | public class VaultRestTemplateApplication { 22 | private static final Logger log = LoggerFactory.getLogger(VaultRestTemplateApplication.class); 23 | 24 | public static void main(String... args) { 25 | new SpringApplicationBuilder(VaultRestTemplateApplication.class).web(WebApplicationType.NONE).run(args); 26 | } 27 | 28 | // This bean is just for acceptance tests - you don't need it in your code 29 | @Bean 30 | RestTemplateCustomizer myRestTemplateCustomizer(Tracer tracer) { 31 | return restTemplate -> restTemplate.getInterceptors().add((request, body, execution) -> { 32 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 33 | return execution.execute(request, body); 34 | }); 35 | } 36 | 37 | @Bean 38 | CommandLineRunner myCommandLineRunner(RestTemplateService restTemplateService) { 39 | return args -> restTemplateService.call(); 40 | } 41 | } 42 | 43 | @Service 44 | class RestTemplateService { 45 | private static final Logger log = LoggerFactory.getLogger(RestTemplateService.class); 46 | 47 | private final VaultTemplate vaultTemplate; 48 | 49 | private final Tracer tracer; 50 | 51 | RestTemplateService(VaultTemplate vaultTemplate, Tracer tracer) { 52 | this.vaultTemplate = vaultTemplate; 53 | this.tracer = tracer; 54 | } 55 | 56 | VaultResponse call() { 57 | Span span = this.tracer.nextSpan().name("rest-template"); 58 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 59 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 60 | return this.vaultTemplate.read("/secret/foo"); 61 | } finally { 62 | span.end(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /rsocket-client/src/main/java/com/example/sleuthsamples/RsocketClient.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.net.URI; 4 | import java.time.Duration; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import reactor.core.publisher.Mono; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.boot.CommandLineRunner; 13 | import org.springframework.boot.WebApplicationType; 14 | import org.springframework.boot.autoconfigure.SpringBootApplication; 15 | import org.springframework.boot.builder.SpringApplicationBuilder; 16 | import org.springframework.cloud.sleuth.Span; 17 | import org.springframework.cloud.sleuth.Tracer; 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.messaging.rsocket.RSocketRequester; 21 | import org.springframework.stereotype.Service; 22 | 23 | @SpringBootApplication 24 | public class RsocketClient implements CommandLineRunner { 25 | 26 | public static void main(String... args) { 27 | new SpringApplicationBuilder(RsocketClient.class).web(WebApplicationType.NONE).run(args); 28 | } 29 | 30 | @Autowired 31 | RsocketService rsocketService; 32 | 33 | @Override 34 | public void run(String... args) throws Exception { 35 | this.rsocketService.call().block(Duration.ofSeconds(5)); 36 | // To ensure that the spans got successfully reported 37 | Thread.sleep(500); 38 | } 39 | } 40 | 41 | @Configuration 42 | class Config { 43 | // You must register RSocketRequester as a bean! 44 | @Bean 45 | RSocketRequester myRSocketRequester(@Value("${url:ws://localhost:7112/rsocket}") String url, RSocketRequester.Builder builder) { 46 | return builder.websocket(URI.create(url)); 47 | } 48 | } 49 | 50 | @Service 51 | class RsocketService { 52 | private static final Logger log = LoggerFactory.getLogger(RsocketService.class); 53 | 54 | private final RSocketRequester rSocketRequester; 55 | 56 | private final Tracer tracer; 57 | 58 | RsocketService(RSocketRequester rSocketRequester, Tracer tracer) { 59 | this.rSocketRequester = rSocketRequester; 60 | this.tracer = tracer; 61 | } 62 | 63 | Mono call() { 64 | Span nextSpan = this.tracer.nextSpan().name("client"); 65 | return Mono.just(nextSpan) 66 | .doOnNext(span -> this.tracer.withSpan(span.start())) 67 | .flatMap(span -> { 68 | log.info(" Hello from producer", this.tracer.currentSpan().context().traceId()); 69 | return this.rSocketRequester.route("foo").retrieveMono(String.class); 70 | }) 71 | .doFinally(signalType -> nextSpan.end()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /circuitbreaker-reactive/src/main/java/com/example/sleuthsamples/ReactiveCircuitBreakerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.time.Duration; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import reactor.core.publisher.Mono; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.boot.WebApplicationType; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.boot.builder.SpringApplicationBuilder; 14 | import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory; 15 | import org.springframework.cloud.sleuth.SpanAndScope; 16 | import org.springframework.cloud.sleuth.Tracer; 17 | import org.springframework.stereotype.Service; 18 | 19 | @SpringBootApplication 20 | public class ReactiveCircuitBreakerApplication implements CommandLineRunner { 21 | 22 | public static void main(String... args) { 23 | new SpringApplicationBuilder(ReactiveCircuitBreakerApplication.class).web(WebApplicationType.NONE).run(args); 24 | } 25 | 26 | @Autowired 27 | CircuitService circuitService; 28 | 29 | @Override 30 | public void run(String... args) throws Exception { 31 | this.circuitService.call().block(Duration.ofSeconds(1)); 32 | } 33 | } 34 | 35 | @Service 36 | class CircuitService { 37 | private static final Logger log = LoggerFactory.getLogger(CircuitService.class); 38 | 39 | private final ReactiveCircuitBreakerFactory factory; 40 | 41 | private final Tracer tracer; 42 | 43 | CircuitService(ReactiveCircuitBreakerFactory factory, Tracer tracer) { 44 | this.factory = factory; 45 | this.tracer = tracer; 46 | } 47 | 48 | Mono call() { 49 | // You don't need this in your code unless you want to create new spans manually 50 | return Mono.just(this.tracer.nextSpan().name("reactive-circuit-breaker")) 51 | .flatMap(span -> { 52 | // You don't need this in your code unless you want to create new spans manually 53 | Tracer.SpanInScope spanInScope = this.tracer.withSpan(span.start()); 54 | SpanAndScope spanAndScope = new SpanAndScope(span, spanInScope); 55 | return this.factory.create("circuit").run(Mono.defer(() -> { 56 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 57 | return Mono.error(new IllegalStateException("BOOM")); 58 | }), throwable -> { 59 | log.info(" Hello from producer", this.tracer.currentSpan().context().traceId()); 60 | return Mono.just("fallback"); 61 | }) 62 | .doFinally(signalType -> spanAndScope.close()); 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /resttemplate/src/main/java/com/example/sleuthsamples/RestTemplateApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.WebApplicationType; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import org.springframework.boot.builder.SpringApplicationBuilder; 12 | import org.springframework.boot.web.client.RestTemplateBuilder; 13 | import org.springframework.cloud.sleuth.Span; 14 | import org.springframework.cloud.sleuth.Tracer; 15 | import org.springframework.context.annotation.Bean; 16 | import org.springframework.context.annotation.Configuration; 17 | import org.springframework.stereotype.Service; 18 | import org.springframework.util.StringUtils; 19 | import org.springframework.web.client.RestTemplate; 20 | 21 | @SpringBootApplication 22 | public class RestTemplateApplication implements CommandLineRunner { 23 | 24 | public static void main(String... args) { 25 | new SpringApplicationBuilder(RestTemplateApplication.class).web(WebApplicationType.NONE).run(args); 26 | } 27 | 28 | @Autowired 29 | RestTemplateService restTemplateService; 30 | 31 | @Value("${url:http://localhost:7100}") 32 | String url; 33 | 34 | @Override 35 | public void run(String... args) throws Exception { 36 | this.restTemplateService.call(url); 37 | } 38 | } 39 | 40 | @Configuration 41 | class Config { 42 | // You must register RestTemplate as a bean! 43 | // We're using username and password in case you need basic authentication 44 | @Bean 45 | RestTemplate restTemplate(@Value("${username:user}") String username, @Value("${password:password}") String password) { 46 | return new RestTemplateBuilder() 47 | .basicAuthentication(username, password) 48 | .build(); 49 | } 50 | } 51 | 52 | @Service 53 | class RestTemplateService { 54 | private static final Logger log = LoggerFactory.getLogger(RestTemplateService.class); 55 | 56 | private final RestTemplate restTemplate; 57 | 58 | private final Tracer tracer; 59 | 60 | RestTemplateService(RestTemplate restTemplate, Tracer tracer) { 61 | this.restTemplate = restTemplate; 62 | this.tracer = tracer; 63 | } 64 | 65 | String call(String url) { 66 | Span span = this.tracer.nextSpan().name("rest-template"); 67 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 68 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 69 | return this.restTemplate.getForObject(url, String.class); 70 | } finally { 71 | span.end(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /integration/src/main/java/com/example/sleuthsamples/SpringIntegrationProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.io.File; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.boot.WebApplicationType; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.boot.builder.SpringApplicationBuilder; 14 | import org.springframework.cloud.sleuth.Span; 15 | import org.springframework.cloud.sleuth.Tracer; 16 | import org.springframework.context.annotation.Bean; 17 | import org.springframework.context.annotation.Configuration; 18 | import org.springframework.integration.annotation.Gateway; 19 | import org.springframework.integration.annotation.MessagingGateway; 20 | import org.springframework.integration.dsl.IntegrationFlow; 21 | import org.springframework.integration.dsl.IntegrationFlows; 22 | import org.springframework.integration.file.dsl.Files; 23 | 24 | @SpringBootApplication 25 | public class SpringIntegrationProducerApplication implements CommandLineRunner { 26 | 27 | private static final Logger log = LoggerFactory.getLogger(SpringIntegrationProducerApplication.class); 28 | 29 | public static void main(String... args) { 30 | new SpringApplicationBuilder(SpringIntegrationProducerApplication.class).web(WebApplicationType.NONE).run(args); 31 | } 32 | 33 | @Autowired FileGateway fileGateway; 34 | 35 | @Autowired Tracer tracer; 36 | 37 | @Override 38 | public void run(String... args) throws Exception { 39 | Span span = this.tracer.nextSpan(); 40 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 41 | String trace = span.context().traceId(); 42 | log.info(" Hello from producer", trace); 43 | this.fileGateway.placeOrder(trace); 44 | } finally { 45 | span.end(); 46 | } 47 | } 48 | } 49 | 50 | @MessagingGateway 51 | interface FileGateway { 52 | 53 | @Gateway(requestChannel = "files.input") 54 | void placeOrder(String text); 55 | 56 | } 57 | 58 | @Configuration 59 | class Config { 60 | 61 | private static final Logger log = LoggerFactory.getLogger(Config.class); 62 | 63 | @Bean 64 | public IntegrationFlow files(Tracer tracer, @Value("${outputFile:${java.io.tmpdir}/spring-integration-sleuth-samples/output}") File file) { 65 | return IntegrationFlows.from("files.input") 66 | .transform(message -> { 67 | String traceId = tracer.currentSpan().context().traceId(); 68 | log.info(" Hello from consumer", traceId); 69 | return message; 70 | }) 71 | .handle(Files.outboundAdapter(file)) 72 | .get(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /baggage-producer/src/main/java/com/example/sleuthsamples/BaggageProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.net.URI; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.boot.WebApplicationType; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.boot.builder.SpringApplicationBuilder; 14 | import org.springframework.cloud.sleuth.BaggageInScope; 15 | import org.springframework.cloud.sleuth.Span; 16 | import org.springframework.cloud.sleuth.Tracer; 17 | import org.springframework.context.annotation.Bean; 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.http.RequestEntity; 20 | import org.springframework.stereotype.Service; 21 | import org.springframework.web.client.RestTemplate; 22 | 23 | @SpringBootApplication 24 | public class BaggageProducerApplication implements CommandLineRunner { 25 | 26 | public static void main(String... args) { 27 | new SpringApplicationBuilder(BaggageProducerApplication.class).web(WebApplicationType.NONE).run(args); 28 | } 29 | 30 | @Autowired 31 | BaggageRestTemplateService baggageRestTemplateService; 32 | 33 | @Value("${url:http://localhost:7200}") 34 | String url; 35 | 36 | @Override 37 | public void run(String... args) throws Exception { 38 | this.baggageRestTemplateService.call(url); 39 | } 40 | } 41 | 42 | @Configuration 43 | class Config { 44 | // You must register RestTemplate as a bean! 45 | @Bean 46 | RestTemplate restTemplate() { 47 | return new RestTemplate(); 48 | } 49 | } 50 | 51 | @Service 52 | class BaggageRestTemplateService { 53 | private static final Logger log = LoggerFactory.getLogger(BaggageRestTemplateService.class); 54 | 55 | private final RestTemplate restTemplate; 56 | 57 | private final Tracer tracer; 58 | 59 | BaggageRestTemplateService(RestTemplate restTemplate, Tracer tracer) { 60 | this.restTemplate = restTemplate; 61 | this.tracer = tracer; 62 | } 63 | 64 | String call(String url) { 65 | Span span = this.tracer.nextSpan(); 66 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 67 | BaggageInScope baggage = this.tracer.createBaggage("mybaggage", "my-baggage-value"); 68 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 69 | log.info(" Baggage is set", baggage.get()); 70 | return this.restTemplate.exchange(RequestEntity.get(URI.create(url)) 71 | .header("myremotefield", "my-remote-field-value") 72 | .build(), String.class).getBody(); 73 | } finally { 74 | span.end(); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributing 3 | 4 | Spring Cloud is released under the non-restrictive Apache 2.0 license, 5 | and follows a very standard Github development process, using Github 6 | tracker for issues and merging pull requests into master. If you want 7 | to contribute even something trivial please do not hesitate, but 8 | follow the guidelines below. 9 | 10 | ## Sign the Contributor License Agreement 11 | Before we accept a non-trivial patch or pull request we will need you to sign the 12 | [Contributor License Agreement](https://cla.pivotal.io/sign/spring). 13 | Signing the contributor's agreement does not grant anyone commit rights to the main 14 | repository, but it does mean that we can accept your contributions, and you will get an 15 | author credit if we do. Active contributors might be asked to join the core team, and 16 | given the ability to merge pull requests. 17 | 18 | ## Code of Conduct 19 | This project adheres to the Contributor Covenant [code of 20 | conduct](https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report 21 | unacceptable behavior to spring-code-of-conduct@pivotal.io. 22 | 23 | ## Code Conventions and Housekeeping 24 | None of these is essential for a pull request, but they will all help. They can also be 25 | added after the original pull request but before a merge. 26 | 27 | * Use the Spring Framework code format conventions. If you use Eclipse 28 | you can import formatter settings using the 29 | `eclipse-code-formatter.xml` file from the 30 | [Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the 31 | [Eclipse Code Formatter Plugin](https://plugins.jetbrains.com/plugin/6546) to import the same file. 32 | * Make sure all new `.java` files to have a simple Javadoc class comment with at least an 33 | `@author` tag identifying you, and preferably at least a paragraph on what the class is 34 | for. 35 | * Add the ASF license header comment to all new `.java` files (copy from existing files 36 | in the project) 37 | * Add yourself as an `@author` to the .java files that you modify substantially (more 38 | than cosmetic changes). 39 | * Add some Javadocs and, if you change the namespace, some XSD doc elements. 40 | * A few unit tests would help a lot as well -- someone has to do it. 41 | * If no-one else is using your branch, please rebase it against the current master (or 42 | other target branch in the main project). 43 | * When writing a commit message please follow [these conventions](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), 44 | if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit 45 | message (where XXXX is the issue number). 46 | -------------------------------------------------------------------------------- /kafka-producer/src/main/java/com/example/sleuthsamples/KafkaProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | 5 | import org.apache.kafka.clients.admin.NewTopic; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.boot.WebApplicationType; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.boot.builder.SpringApplicationBuilder; 14 | import org.springframework.cloud.sleuth.Span; 15 | import org.springframework.cloud.sleuth.Tracer; 16 | import org.springframework.context.annotation.Bean; 17 | import org.springframework.kafka.core.KafkaTemplate; 18 | import org.springframework.kafka.support.SendResult; 19 | import org.springframework.stereotype.Service; 20 | import org.springframework.util.concurrent.ListenableFuture; 21 | import org.springframework.util.concurrent.ListenableFutureCallback; 22 | 23 | @SpringBootApplication 24 | public class KafkaProducerApplication implements CommandLineRunner { 25 | 26 | public static void main(String... args) { 27 | new SpringApplicationBuilder(KafkaProducerApplication.class).web(WebApplicationType.NONE).run(args); 28 | } 29 | 30 | @Autowired 31 | KafkaProducerService kafkaProducerService; 32 | 33 | @Override 34 | public void run(String... args) throws Exception { 35 | this.kafkaProducerService.call(); 36 | } 37 | 38 | @Bean 39 | NewTopic myTopic() { 40 | return new NewTopic("mytopic", 1, (short) 1); 41 | } 42 | } 43 | 44 | @Service 45 | class KafkaProducerService { 46 | private static final Logger log = LoggerFactory.getLogger(KafkaProducerService.class); 47 | 48 | private final KafkaTemplate kafkaTemplate; 49 | 50 | private final Tracer tracer; 51 | 52 | KafkaProducerService(KafkaTemplate kafkaTemplate, Tracer tracer) { 53 | this.kafkaTemplate = kafkaTemplate; 54 | this.tracer = tracer; 55 | } 56 | 57 | void call() throws ExecutionException, InterruptedException { 58 | Span span = this.tracer.nextSpan().name("kafka-producer"); 59 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.start())) { 60 | log.info(" Hello from producer", this.tracer.currentSpan().context().traceId()); 61 | ListenableFuture> future = 62 | kafkaTemplate.send("mytopic", "hello"); 63 | future.addCallback(new ListenableFutureCallback<>() { 64 | 65 | @Override 66 | public void onSuccess(SendResult result) { 67 | log.info("Sent <{}>", result); 68 | span.end(); 69 | } 70 | 71 | @Override 72 | public void onFailure(Throwable ex) { 73 | log.info("Failed to send a message", ex); 74 | span.end(); 75 | } 76 | }); 77 | // Blocking to ensure that we push all the spans 78 | future.get(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/ProjectRebuilder.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.io.File; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.Properties; 7 | 8 | import org.apache.maven.shared.invoker.DefaultInvocationRequest; 9 | import org.apache.maven.shared.invoker.DefaultInvoker; 10 | import org.apache.maven.shared.invoker.InvocationRequest; 11 | import org.apache.maven.shared.invoker.Invoker; 12 | import org.apache.maven.shared.invoker.MavenInvocationException; 13 | import org.apache.maven.shared.invoker.SystemOutHandler; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import org.springframework.beans.factory.annotation.Value; 18 | import org.springframework.stereotype.Component; 19 | import org.springframework.util.StringUtils; 20 | 21 | @Component 22 | class ProjectRebuilder { 23 | 24 | private static final Logger log = LoggerFactory.getLogger(ProjectRebuilder.class); 25 | 26 | private final boolean rebuildProjects; 27 | 28 | private final String mavenHome; 29 | 30 | private final String projectRoot; 31 | 32 | ProjectRebuilder(@Value("${spring.cloud.sleuth.samples.rebuild-projects:false}") boolean rebuildProjects, 33 | @Value("${maven.home:}") String mavenHome, 34 | @Value("${spring.cloud.sleuth.samples.project-root:}") String projectRoot) { 35 | this.rebuildProjects = rebuildProjects; 36 | this.mavenHome = mavenHome; 37 | this.projectRoot = projectRoot; 38 | } 39 | 40 | void rebuildProjectBeforeDeployment(String appName) { 41 | if (!this.rebuildProjects) { 42 | log.info("The flag [spring.cloud.sleuth.samples.rebuild-projects] was set to false - won't rebuild the projects"); 43 | return; 44 | } 45 | else if (!StringUtils.hasText(mavenHome)) { 46 | log.warn("The flag to rebuild was set to [true], however no MAVEN_HOME or maven.home was set, can't rebuild the projects"); 47 | return; 48 | } 49 | File rootPom = new File(this.projectRoot, "pom.xml"); 50 | try { 51 | invoker().execute(invocationRequest(rootPom, appName)); 52 | } 53 | catch (MavenInvocationException e) { 54 | throw new IllegalStateException(e); 55 | } 56 | } 57 | 58 | 59 | private Invoker invoker() { 60 | Invoker invoker = new DefaultInvoker(); 61 | invoker.setMavenHome(new File(this.mavenHome)); 62 | invoker.setOutputHandler(new SystemOutHandler()); // not interested in Maven output itself 63 | return invoker; 64 | } 65 | 66 | private InvocationRequest invocationRequest(File pom, String appName) { 67 | InvocationRequest request = new DefaultInvocationRequest(); 68 | request.setReactorFailureBehavior(InvocationRequest.ReactorFailureBehavior.FailFast); 69 | request.setPomFile(pom); 70 | request.setProjects(Collections.singletonList(appName)); 71 | request.setProfiles(Collections.singletonList("notest")); 72 | request.setGoals(Arrays.asList("clean", "install")); 73 | Properties properties = new Properties(); 74 | request.setProperties(properties); 75 | return request; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/AcceptanceTestsBase.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.time.Duration; 4 | import java.util.Map; 5 | import java.util.concurrent.Callable; 6 | 7 | import org.junit.jupiter.api.AfterEach; 8 | import org.junit.jupiter.api.TestInfo; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.boot.autoconfigure.SpringBootApplication; 14 | import org.springframework.boot.test.context.SpringBootTest; 15 | import org.springframework.cloud.deployer.spi.app.DeploymentState; 16 | 17 | @SpringBootTest 18 | class AcceptanceTestsBase { 19 | 20 | private static final Logger log = LoggerFactory.getLogger(AcceptanceTestsBase.class); 21 | 22 | @Autowired 23 | ProjectDeployer projectDeployer; 24 | 25 | @Autowired 26 | TracingAssertions tracingAssertions; 27 | 28 | AcceptanceTestsBase() { 29 | Runtime.getRuntime().addShutdownHook(new Thread(() -> projectDeployer.getIds().forEach((key, values) -> values.forEach(id -> { 30 | if (projectDeployer.status(id).getState() != DeploymentState.undeployed) { 31 | undeploy(id); 32 | } 33 | })))); 34 | } 35 | 36 | String deployWebApp(TestInfo testInfo, String appName, int port) { 37 | return this.projectDeployer.deployWebApp(testInfo, appName, port); 38 | } 39 | 40 | String deployWebApp(TestInfo testInfo, String appName, Map props) { 41 | return this.projectDeployer.deployWebApp(testInfo, appName, props); 42 | } 43 | 44 | String deploy(TestInfo testInfo, String appName, Map props) { 45 | return this.projectDeployer.deploy(testInfo, appName, props); 46 | } 47 | 48 | String deploy(TestInfo testInfo, String appName) { 49 | return this.projectDeployer.deploy(testInfo, appName, Map.of()); 50 | } 51 | 52 | String waitUntilStarted(Callable callable) throws Exception { 53 | return this.projectDeployer.waitUntilStarted(callable); 54 | } 55 | 56 | String wait10seconds(Callable callable) throws Exception { 57 | try { 58 | String id = callable.call(); 59 | long millis = Duration.ofSeconds(10).toMillis(); 60 | log.info("Will wait for [{}] millis before the app starts", millis); 61 | Thread.sleep(millis); 62 | return id; 63 | } 64 | catch (InterruptedException e) { 65 | throw new IllegalStateException(); 66 | } 67 | } 68 | 69 | private void undeploy(String id) { 70 | this.projectDeployer.undeploy(id); 71 | } 72 | 73 | @AfterEach 74 | void cleanup(TestInfo testInfo) { 75 | this.projectDeployer.clean(testInfo); 76 | } 77 | 78 | void assertThatTraceIdGotPropagated(String... appIds) { 79 | this.tracingAssertions.assertThatTraceIdGotPropagated(appIds); 80 | } 81 | 82 | void assertThatLogsContainPropagatedIdAtLeastXNumberOfTimes(String appId, String springAppName, int minOccurrence) { 83 | this.tracingAssertions.assertThatLogsContainPropagatedIdAtLeastXNumberOfTimes(appId, springAppName, minOccurrence); 84 | } 85 | 86 | @SpringBootApplication 87 | static class Config { 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /security/src/main/java/com/example/sleuthsamples/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.sleuthsamples; 18 | 19 | import java.util.List; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import org.springframework.beans.factory.BeanFactory; 25 | import org.springframework.cloud.sleuth.Tracer; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 29 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 30 | import org.springframework.security.core.context.ListeningSecurityContextHolderStrategy; 31 | import org.springframework.security.core.context.SecurityContextChangedListener; 32 | import org.springframework.security.core.context.SecurityContextHolder; 33 | import org.springframework.security.core.context.SecurityContextHolderStrategy; 34 | import org.springframework.security.core.userdetails.User; 35 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 36 | import org.springframework.security.web.SecurityFilterChain; 37 | 38 | import static org.springframework.security.config.Customizer.withDefaults; 39 | 40 | /** 41 | * Spring Security config. 42 | * 43 | * @author Jonatan Ivanov 44 | */ 45 | @Configuration 46 | @EnableWebSecurity 47 | public class SecurityConfiguration { 48 | 49 | // TODO: remove this once Spring Boot autoconfigures it 50 | SecurityConfiguration(List securityContextChangedListeners) { 51 | SecurityContextHolderStrategy strategy = new ListeningSecurityContextHolderStrategy( 52 | SecurityContextHolder.getContextHolderStrategy(), securityContextChangedListeners); 53 | SecurityContextHolder.setContextHolderStrategy(strategy); 54 | } 55 | 56 | @Bean 57 | SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 58 | return http.authorizeRequests(requests -> 59 | requests.antMatchers("/favicon.ico").permitAll() 60 | .anyRequest().authenticated() 61 | ) 62 | .httpBasic(withDefaults()) 63 | .formLogin(withDefaults()).build(); 64 | } 65 | 66 | @Bean 67 | InMemoryUserDetailsManager userDetailsService() { 68 | return new InMemoryUserDetailsManager( 69 | User.withDefaultPasswordEncoder() 70 | .username("user") 71 | .password("password") 72 | .roles("USER") 73 | .build() 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Java CI with Maven](https://github.com/spring-cloud-samples/spring-cloud-sleuth-samples/workflows/Java%20CI%20with%20Maven/badge.svg) 2 | 3 | # Spring Cloud Sleuth Samples 4 | 5 | This repository contains isolated samples showing various integrations with Spring Cloud Sleuth. 6 | 7 | You can read more about the details of the instrumentation logic in each of the samples. 8 | 9 | ## Turning on Wavefront support 10 | 11 | Build the apps with the `default` and `wavefront` profile turned on. `default` will add Sleuth with Brave on the classpath. 12 | 13 | . All projects and acceptance tests 14 | ```bash 15 | $ ./mvnw clean install -Pdefault,wavefront 16 | ``` 17 | 18 | . Build one project 19 | ```bash 20 | $ ./mvnw clean install -Pdefault,wavefront -pl task 21 | $ # Run one app 22 | $ java -jar task/target/task*.jar 23 | ``` 24 | 25 | . Run one project (example for task) 26 | ```bash 27 | $ ./mvnw -Pdefault,wavefront -pl task spring-boot:run 28 | ``` 29 | 30 | If you want to run the project from IDE remember to tick the `default` and `wavefront` profiles there too. 31 | 32 | ## Turning on Zipkin support 33 | 34 | Run Zipkin 35 | 36 | ```bash 37 | $ docker run -d -p 9411:9411 openzipkin/zipkin 38 | ``` 39 | 40 | Build the apps with the `default` and `zipkin` profile turned on. `default` will add Sleuth with Brave on the classpath. 41 | 42 | . All projects and acceptance tests 43 | ```bash 44 | $ ./mvnw clean install -Pdefault,zipkin 45 | ``` 46 | 47 | . Build one project 48 | ```bash 49 | $ ./mvnw clean install -Pdefault,zipkin -pl task 50 | $ # Run one app 51 | $ java -jar task/target/task*.jar 52 | ``` 53 | 54 | . Run one project (example for task) 55 | ```bash 56 | $ ./mvnw -Pdefault,zipkin -pl task spring-boot:run 57 | ``` 58 | 59 | If you want to run the project from IDE remember to tick the `default` and `zipkin` profiles there too. 60 | 61 | ## Using OpenTelemetry 62 | 63 | Instead of using the `default` profile please use the `otel` profile. So if you want to run `otel` based tracing with zipkin you need to build the 64 | application with both `otel` and `zipkin` profiles. Example: 65 | 66 | . All projects and acceptance tests 67 | ```bash 68 | $ ./mvnw clean install -Potel,zipkin 69 | ``` 70 | 71 | . Build one project 72 | ```bash 73 | $ ./mvnw clean install -Potel,zipkin -pl task 74 | $ # Run one app 75 | $ java -jar task/target/task*.jar 76 | ``` 77 | 78 | . Run one project (example for task) 79 | ```bash 80 | $ ./mvnw -Potel,zipkin -pl task spring-boot:run 81 | ``` 82 | 83 | # FAQ 84 | 85 | ## The logging text makes no sense 86 | 87 | You can see logs like this 88 | 89 | ```java 90 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 91 | ``` 92 | 93 | or this 94 | 95 | ```java 96 | log.info(" Hello from consumer", tracer.currentSpan().context().traceId()); 97 | ``` 98 | 99 | even though there is no consumer / producer... 100 | 101 | That's because in the acceptance tests we're using conventions and we're searching for exactly those entries in the logs to see if the context got properly propagated. 102 | -------------------------------------------------------------------------------- /vault-webclient/src/main/java/com/example/sleuthsamples/VaultWebClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.time.Duration; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import reactor.core.publisher.Mono; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.boot.CommandLineRunner; 12 | import org.springframework.boot.WebApplicationType; 13 | import org.springframework.boot.autoconfigure.SpringBootApplication; 14 | import org.springframework.boot.builder.SpringApplicationBuilder; 15 | import org.springframework.cloud.sleuth.Span; 16 | import org.springframework.cloud.sleuth.Tracer; 17 | import org.springframework.context.annotation.Bean; 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.stereotype.Service; 20 | import org.springframework.vault.client.WebClientCustomizer; 21 | import org.springframework.vault.core.ReactiveVaultTemplate; 22 | import org.springframework.vault.support.VaultResponse; 23 | import org.springframework.web.reactive.function.client.ExchangeFilterFunction; 24 | import org.springframework.web.reactive.function.client.WebClient; 25 | 26 | @SpringBootApplication 27 | public class VaultWebClientApplication { 28 | 29 | public static void main(String... args) { 30 | new SpringApplicationBuilder(VaultWebClientApplication.class).web(WebApplicationType.NONE).run(args); 31 | } 32 | } 33 | 34 | @Configuration 35 | class Config { 36 | 37 | private static final Logger log = LoggerFactory.getLogger(Config.class); 38 | 39 | @Bean 40 | CommandLineRunner myCommandLineRunner(WebClientService webClientService) { 41 | return args -> { 42 | webClientService.call().block(Duration.ofSeconds(5)); 43 | // To ensure that the spans got successfully reported 44 | try { 45 | Thread.sleep(500); 46 | } catch (Exception ex) { 47 | 48 | } 49 | }; 50 | } 51 | 52 | @Bean 53 | WebClientCustomizer testWebClientCustomizer(Tracer tracer) { 54 | return webClientBuilder -> webClientBuilder.filter((request, next) -> { 55 | log.info(" Hello from producer", tracer.currentSpan().context().traceId()); 56 | return next.exchange(request); 57 | }); 58 | } 59 | } 60 | 61 | @Service 62 | class WebClientService { 63 | private static final Logger log = LoggerFactory.getLogger(WebClientService.class); 64 | 65 | private final ReactiveVaultTemplate reactiveVaultTemplate; 66 | 67 | private final Tracer tracer; 68 | 69 | WebClientService(ReactiveVaultTemplate reactiveVaultTemplate, Tracer tracer) { 70 | this.reactiveVaultTemplate = reactiveVaultTemplate; 71 | this.tracer = tracer; 72 | } 73 | 74 | Mono call() { 75 | Span nextSpan = this.tracer.nextSpan().name("client"); 76 | return Mono.just(nextSpan) 77 | .doOnNext(span -> this.tracer.withSpan(span.start())) 78 | .flatMap(span -> { 79 | log.info(" Hello from consumer", this.tracer.currentSpan().context().traceId()); 80 | return this.reactiveVaultTemplate.read("/secrets/foo"); 81 | }) 82 | .doFinally(signalType -> nextSpan.end()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /stream-reactive-producer/src/main/java/com/example/sleuthsamples/StreamReactiveProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.function.Function; 4 | import java.util.function.Supplier; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.CommandLineRunner; 10 | import org.springframework.boot.WebApplicationType; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.boot.builder.SpringApplicationBuilder; 13 | import org.springframework.cloud.function.context.PollableBean; 14 | import org.springframework.cloud.sleuth.Span; 15 | import org.springframework.cloud.sleuth.Tracer; 16 | import org.springframework.cloud.stream.function.StreamBridge; 17 | import org.springframework.context.annotation.Bean; 18 | import org.springframework.messaging.Message; 19 | import org.springframework.stereotype.Service; 20 | 21 | import reactor.core.publisher.Flux; 22 | import reactor.core.publisher.Mono; 23 | 24 | @SpringBootApplication 25 | public class StreamReactiveProducerApplication implements CommandLineRunner { 26 | 27 | private static final Logger log = LoggerFactory.getLogger(StreamReactiveProducerApplication.class); 28 | 29 | public static void main(String... args) { 30 | new SpringApplicationBuilder(StreamReactiveProducerApplication.class).web(WebApplicationType.NONE).run(args); 31 | } 32 | 33 | @Autowired 34 | StreamBridgeService streamBridgeService; 35 | 36 | @Override 37 | public void run(String... args) throws Exception { 38 | this.streamBridgeService.call(); 39 | } 40 | 41 | // Function, Mono> and Supplier> and Consumer> are not supported in Stream 42 | 43 | @Bean 44 | Function>, Flux>> tracingFunction(Tracer tracer) { 45 | return s -> s.doOnNext(i -> log.info(" Hello from producer function flux", tracer.currentSpan().context().traceId())); 46 | } 47 | 48 | // @PollableBean 49 | Supplier> supplier(Tracer tracer) { 50 | return () -> Flux.just("HELLO") 51 | .doOnNext(s -> log.info(" Hello from producer supplier mono", tracer.currentSpan().context().traceId())); 52 | } 53 | 54 | // @PollableBean 55 | Supplier> stringSupplier(Tracer tracer) { 56 | return () -> Flux.just("a", "b").doOnNext(s -> log.info(" Hello from producer supplier flux", tracer.currentSpan().context().traceId())); 57 | } 58 | } 59 | 60 | @Service 61 | class StreamBridgeService { 62 | private static final Logger log = LoggerFactory.getLogger(StreamBridgeService.class); 63 | 64 | private final StreamBridge streamBridge; 65 | 66 | private final Tracer tracer; 67 | 68 | StreamBridgeService(StreamBridge streamBridge, Tracer tracer) { 69 | this.streamBridge = streamBridge; 70 | this.tracer = tracer; 71 | } 72 | 73 | void call() { 74 | Span span = this.tracer.nextSpan(); 75 | try (Tracer.SpanInScope ws = this.tracer.withSpan(span.name("stream-bridge-service").start())) { 76 | log.info("Hello from stream bridge - trace <{}>", this.tracer.currentSpan().context().traceId()); 77 | this.streamBridge.send("tracingFunction-in-0", "HELLO"); 78 | } finally { 79 | span.end(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /kafka-reactive-producer/src/main/java/com/example/sleuthsamples/KafkaReactiveProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Map; 4 | 5 | import org.apache.kafka.clients.admin.NewTopic; 6 | import org.apache.kafka.clients.producer.ProducerConfig; 7 | import org.apache.kafka.clients.producer.ProducerRecord; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import reactor.core.publisher.Flux; 11 | import reactor.core.publisher.Mono; 12 | import reactor.kafka.sender.KafkaSender; 13 | import reactor.kafka.sender.SenderOptions; 14 | import reactor.kafka.sender.SenderRecord; 15 | 16 | import org.springframework.beans.factory.BeanFactory; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.boot.CommandLineRunner; 20 | import org.springframework.boot.WebApplicationType; 21 | import org.springframework.boot.autoconfigure.SpringBootApplication; 22 | import org.springframework.boot.autoconfigure.kafka.KafkaProperties; 23 | import org.springframework.boot.builder.SpringApplicationBuilder; 24 | import org.springframework.cloud.sleuth.Tracer; 25 | import org.springframework.cloud.sleuth.instrument.kafka.TracingKafkaProducerFactory; 26 | import org.springframework.context.annotation.Bean; 27 | import org.springframework.context.annotation.Configuration; 28 | import org.springframework.stereotype.Service; 29 | 30 | @SpringBootApplication 31 | public class KafkaReactiveProducerApplication implements CommandLineRunner { 32 | 33 | public static void main(String... args) { 34 | new SpringApplicationBuilder(KafkaReactiveProducerApplication.class).web(WebApplicationType.NONE).run(args); 35 | } 36 | 37 | @Autowired 38 | KafkaProducerService kafkaProducerService; 39 | 40 | @Override 41 | public void run(String... args) throws Exception { 42 | this.kafkaProducerService.call().blockFirst(); 43 | } 44 | 45 | 46 | @Configuration(proxyBeanMethods = false) 47 | static class Config { 48 | 49 | @Bean 50 | NewTopic myTopic() { 51 | return new NewTopic("mytopic2", 1, (short) 1); 52 | } 53 | 54 | @Bean KafkaSender reactiveKafkaSender(@Value("${spring.kafka.bootstrap-servers:localhost:9092}") String servers, KafkaProperties properties, BeanFactory beanFactory) { 55 | Map map = properties.getProducer().buildProperties(); 56 | map.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, servers); 57 | return KafkaSender.create(new TracingKafkaProducerFactory(beanFactory), SenderOptions.create(map)); 58 | } 59 | } 60 | } 61 | 62 | @Service 63 | class KafkaProducerService { 64 | private static final Logger log = LoggerFactory.getLogger(KafkaProducerService.class); 65 | 66 | private final KafkaSender kafkaSender; 67 | 68 | private final Tracer tracer; 69 | 70 | KafkaProducerService(KafkaSender kafkaSender, Tracer tracer) { 71 | this.kafkaSender = kafkaSender; 72 | this.tracer = tracer; 73 | } 74 | 75 | Flux call() { 76 | return Flux.just(this.tracer.nextSpan().name("reactive-kafka-producer")) 77 | .doOnNext(span -> this.tracer.withSpan(span.start())) 78 | .doOnNext(span -> log.info(" Hello from producer", this.tracer.currentSpan().context().traceId())) 79 | .flatMap(span -> kafkaSender.send(Mono.just(SenderRecord.create(new ProducerRecord<>("mytopic2", "hello"), null))) 80 | .doOnComplete(() -> { 81 | log.info("Sent message"); 82 | span.end(); 83 | }).doOnError(throwable -> { 84 | log.info("Failed to send a message", throwable); 85 | span.end(); 86 | })); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /baggage-consumer/src/main/java/com/example/sleuthsamples/BaggageConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import javax.annotation.PreDestroy; 4 | 5 | import com.github.tomakehurst.wiremock.WireMockServer; 6 | import com.github.tomakehurst.wiremock.client.WireMock; 7 | import com.github.tomakehurst.wiremock.core.WireMockConfiguration; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import org.springframework.boot.SpringApplication; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.cloud.sleuth.Tracer; 14 | import org.springframework.context.annotation.Bean; 15 | import org.springframework.context.annotation.Configuration; 16 | import org.springframework.web.bind.annotation.GetMapping; 17 | import org.springframework.web.bind.annotation.RestController; 18 | import org.springframework.web.client.RestTemplate; 19 | 20 | @SpringBootApplication 21 | public class BaggageConsumerApplication { 22 | 23 | public static void main(String... args) { 24 | new SpringApplication(BaggageConsumerApplication.class).run(args); 25 | } 26 | } 27 | 28 | @RestController 29 | class BaggageController { 30 | private static final Logger log = LoggerFactory.getLogger(BaggageController.class); 31 | 32 | private final Tracer tracer; 33 | 34 | // Used for tests - ignore me 35 | private final RemoteFieldsTestChecker remoteFieldsTestChecker; 36 | 37 | BaggageController(Tracer tracer, RemoteFieldsTestChecker remoteFieldsTestChecker) { 38 | this.tracer = tracer; 39 | this.remoteFieldsTestChecker = remoteFieldsTestChecker; 40 | } 41 | 42 | @GetMapping("/") 43 | public String span() { 44 | log.info("Contains the following baggage {}", this.tracer.getAllBaggage()); 45 | String traceId = this.tracer.currentSpan().context().traceId(); 46 | log.info(" Hello from producer", traceId); 47 | // Used for tests - ignore me 48 | this.remoteFieldsTestChecker.assertThatFieldGotPropagated(); 49 | return traceId; 50 | } 51 | } 52 | 53 | // Used for tests - ignore me 54 | @Configuration(proxyBeanMethods = false) 55 | class TestConfiguration { 56 | @Bean 57 | RestTemplate restTemplate() { 58 | return new RestTemplate(); 59 | } 60 | 61 | @Bean 62 | RemoteFieldsTestChecker remoteFieldsChecker(RestTemplate restTemplate) { 63 | return new RemoteFieldsTestChecker(restTemplate); 64 | } 65 | } 66 | 67 | // Used for tests - ignore me 68 | class RemoteFieldsTestChecker { 69 | private static final Logger log = LoggerFactory.getLogger(RemoteFieldsTestChecker.class); 70 | 71 | private final WireMockServer wireMockServer; 72 | 73 | private final RestTemplate restTemplate; 74 | 75 | RemoteFieldsTestChecker(RestTemplate restTemplate) { 76 | this.restTemplate = restTemplate; 77 | this.wireMockServer = new WireMockServer(WireMockConfiguration.options().dynamicPort()); 78 | this.wireMockServer.start(); 79 | this.wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/foo")).withHeader("myremotefield", WireMock.equalTo("my-remote-field-value")).willReturn(WireMock.aResponse().withStatus(200).withBody("OK"))); 80 | } 81 | 82 | void assertThatFieldGotPropagated() { 83 | String object = this.restTemplate.getForObject("http://localhost:" + this.wireMockServer.port() + "/foo", String.class); 84 | if (!"OK".equals(object)) { 85 | throw new IllegalStateException("WireMock failed to respond correctly"); 86 | } 87 | // [myremotefield] was set in the baggage-producer 88 | this.wireMockServer.verify(WireMock.getRequestedFor(WireMock.urlEqualTo("/foo")) 89 | .withHeader("myremotefield", WireMock.equalTo("my-remote-field-value"))); 90 | log.info("Successfully propagated the headers!"); 91 | } 92 | 93 | @PreDestroy 94 | void destroy() { 95 | this.wireMockServer.shutdown(); 96 | } 97 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example.sleuthsamples 8 | spring-cloud-sleuth-samples 9 | pom 10 | 0.0.1-SNAPSHOT 11 | 12 | Spring Cloud Sleuth Samples 13 | Spring Cloud Sleuth Samples 14 | 15 | 16 | 17 | 18 | maven-deploy-plugin 19 | 20 | true 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | default 29 | 30 | true 31 | 32 | 33 | resttemplate 34 | mvc 35 | integration 36 | webflux 37 | webclient 38 | security 39 | stream-producer 40 | stream-consumer 41 | stream-reactive-producer 42 | stream-reactive-consumer 43 | openfeign 44 | gateway 45 | circuitbreaker 46 | circuitbreaker-reactive 47 | task 48 | config-server 49 | batch 50 | bus 51 | deployer 52 | rsocket-server 53 | rsocket-client 54 | data 55 | data-reactive 56 | vault-resttemplate 57 | vault-webclient 58 | cassandra 59 | cassandra-reactive 60 | baggage-producer 61 | baggage-consumer 62 | mongodb-reactive 63 | kafka-producer 64 | kafka-consumer 65 | kafka-reactive-producer 66 | kafka-reactive-consumer 67 | session 68 | acceptance-tests 69 | 70 | 71 | 72 | notest 73 | 74 | resttemplate 75 | mvc 76 | integration 77 | webflux 78 | webclient 79 | security 80 | stream-producer 81 | stream-consumer 82 | stream-reactive-producer 83 | stream-reactive-consumer 84 | openfeign 85 | gateway 86 | circuitbreaker 87 | circuitbreaker-reactive 88 | task 89 | config-server 90 | batch 91 | bus 92 | deployer 93 | rsocket-server 94 | rsocket-client 95 | data 96 | data-reactive 97 | vault-resttemplate 98 | vault-webclient 99 | cassandra 100 | cassandra-reactive 101 | baggage-producer 102 | baggage-consumer 103 | mongodb-reactive 104 | kafka-producer 105 | kafka-consumer 106 | kafka-reactive-producer 107 | kafka-reactive-consumer 108 | session 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /acceptance-tests/src/test/java/com/example/sleuthsamples/TracingAssertions.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.concurrent.TimeUnit; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | import java.util.stream.Collectors; 12 | 13 | import org.awaitility.Awaitility; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import org.springframework.stereotype.Component; 18 | 19 | import static org.assertj.core.api.BDDAssertions.then; 20 | 21 | @Component 22 | class TracingAssertions { 23 | 24 | private static final Logger log = LoggerFactory.getLogger(TracingAssertions.class); 25 | 26 | private static final Pattern tracePattern = Pattern.compile("^.* .*$"); 27 | private static final String expectedConsumerText = "Hello from consumer"; 28 | private static final String expectedProducerText = "Hello from producer"; 29 | 30 | private final ProjectDeployer projectDeployer; 31 | 32 | TracingAssertions(ProjectDeployer projectDeployer) { 33 | this.projectDeployer = projectDeployer; 34 | } 35 | 36 | void assertThatTraceIdGotPropagated(String... appIds) { 37 | try { 38 | Awaitility.await().pollInterval(1, TimeUnit.SECONDS) 39 | .atMost(40, TimeUnit.SECONDS).untilAsserted(() -> { 40 | AtomicBoolean consumerPresent = new AtomicBoolean(); 41 | AtomicBoolean producerPresent = new AtomicBoolean(); 42 | List traceIds = Arrays.stream(appIds).map(this.projectDeployer::getLog) 43 | .flatMap(s -> Arrays.stream(s.split(System.lineSeparator()))) 44 | .filter(s -> s.contains("ACCEPTANCE_TEST")).map(s -> { 45 | Matcher matcher = tracePattern.matcher(s); 46 | if (matcher.matches()) { 47 | if (s.contains(expectedConsumerText)) { 48 | consumerPresent.set(true); 49 | } 50 | else if (s.contains(expectedProducerText)) { 51 | producerPresent.set(true); 52 | } 53 | return matcher.group(1); 54 | } 55 | return null; 56 | }).filter(Objects::nonNull) 57 | .distinct() 58 | .collect(Collectors.toList()); 59 | log.info("Found the following trace id {}", traceIds); 60 | then(traceIds).as("TraceId should have only one value").hasSize(1); 61 | then(producerPresent).as("Producer code must be called").isTrue(); 62 | then(consumerPresent).as("Consumer code must be called").isTrue(); 63 | }); 64 | } catch (Throwable er) { 65 | log.error("Something went wrong! Will print out the application logs\n\n"); 66 | Arrays.stream(appIds).forEach(id -> log.error("App with id [" + id + "]\n\n" + this.projectDeployer.getLog(id))); 67 | throw er; 68 | } 69 | } 70 | 71 | void assertThatLogsContainPropagatedIdAtLeastXNumberOfTimes(String appId, String springApplicationName, int minNumberOfOccurrences) { 72 | Pattern pattern = Pattern.compile("^.*\\[" + springApplicationName + ",([a-z|0-9]+?),([a-z|0-9]+?)].*$"); 73 | try { 74 | Awaitility.await().pollInterval(1, TimeUnit.SECONDS) 75 | .atMost(120, TimeUnit.SECONDS).untilAsserted(() -> { 76 | AtomicInteger counter = new AtomicInteger(); 77 | List traceIds = Arrays.stream(this.projectDeployer.getLog(appId) 78 | .split(System.lineSeparator())) 79 | .map(s -> { 80 | Matcher matcher = pattern.matcher(s); 81 | if (matcher.matches()) { 82 | counter.incrementAndGet(); 83 | return matcher.group(1); 84 | } 85 | return null; 86 | }).filter(Objects::nonNull) 87 | .distinct() 88 | .collect(Collectors.toList()); 89 | log.info("Found the trace id {} [{}] times. Min required number [{}] ", traceIds, counter.get(), minNumberOfOccurrences); 90 | then(traceIds).as("TraceId should have only one value").hasSize(1); 91 | then(counter).as("There should be at least X number of times").hasValueGreaterThanOrEqualTo(minNumberOfOccurrences); 92 | }); 93 | } catch (Throwable er) { 94 | log.error("One of the assertions has failed! Will print out the application logs"); 95 | log.error(this.projectDeployer.getLog(appId)); 96 | throw er; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /mongodb-reactive/src/main/java/com/example/sleuthsamples/ReactiveMongoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.time.Duration; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.boot.WebApplicationType; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; 11 | import org.springframework.boot.builder.SpringApplicationBuilder; 12 | import org.springframework.cloud.sleuth.CurrentTraceContext; 13 | import org.springframework.cloud.sleuth.Span; 14 | import org.springframework.cloud.sleuth.TraceContext; 15 | import org.springframework.cloud.sleuth.Tracer; 16 | import org.springframework.cloud.sleuth.Tracer.SpanInScope; 17 | import org.springframework.context.annotation.Bean; 18 | 19 | import com.mongodb.RequestContext; 20 | import com.mongodb.event.CommandListener; 21 | import com.mongodb.event.CommandSucceededEvent; 22 | 23 | import reactor.core.publisher.Mono; 24 | 25 | @SpringBootApplication 26 | public class ReactiveMongoApplication { 27 | 28 | private static final Logger log = LoggerFactory.getLogger(ReactiveMongoApplication.class); 29 | 30 | public static void main(String... args) { 31 | new SpringApplicationBuilder(ReactiveMongoApplication.class).web(WebApplicationType.NONE).run(args); 32 | } 33 | 34 | @Bean 35 | public CommandLineRunner demo(BasicUserRepository basicUserRepository, Tracer tracer) { 36 | return (args) -> { 37 | Span nextSpan = tracer.nextSpan().name("mongo-reactive-app"); 38 | Mono.just(nextSpan).doOnNext(span -> tracer.withSpan(nextSpan.start())).flatMap(span -> { 39 | log.info(" Hello from consumer", 40 | tracer.currentSpan().context().traceId()); 41 | return basicUserRepository.save(new User("foo", "bar", "baz", null)) 42 | .flatMap(user -> basicUserRepository.findUserByUsername("foo")); 43 | }).contextWrite(context -> context.put(Span.class, nextSpan).put(TraceContext.class, nextSpan.context())) 44 | .doFinally(signalType -> nextSpan.end()).block(Duration.ofMinutes(1)); 45 | }; 46 | } 47 | 48 | // This is for tests only. You don't need this in your production code. 49 | @Bean 50 | public MongoClientSettingsBuilderCustomizer testMongoClientSettingsBuilderCustomizer(Tracer tracer, 51 | CurrentTraceContext currentTraceContext) { 52 | return new TestMongoClientSettingsBuilderCustomizer(tracer, currentTraceContext); 53 | } 54 | 55 | } 56 | 57 | //This is for tests only. You don't need this in your production code. 58 | class TestMongoClientSettingsBuilderCustomizer implements MongoClientSettingsBuilderCustomizer { 59 | 60 | private static final Logger log = LoggerFactory.getLogger(TestMongoClientSettingsBuilderCustomizer.class); 61 | 62 | private final Tracer tracer; 63 | 64 | private final CurrentTraceContext currentTraceContext; 65 | 66 | public TestMongoClientSettingsBuilderCustomizer(Tracer tracer, CurrentTraceContext currentTraceContext) { 67 | this.tracer = tracer; 68 | this.currentTraceContext = currentTraceContext; 69 | } 70 | 71 | @Override 72 | public void customize(com.mongodb.MongoClientSettings.Builder clientSettingsBuilder) { 73 | clientSettingsBuilder.addCommandListener(new CommandListener() { 74 | 75 | @Override 76 | public void commandSucceeded(CommandSucceededEvent event) { 77 | RequestContext requestContext = event.getRequestContext(); 78 | if (requestContext == null) { 79 | return; 80 | } 81 | Span parent = spanFromContext(tracer, currentTraceContext, requestContext); 82 | if (parent == null) { 83 | return; 84 | } 85 | try (SpanInScope withSpan = tracer.withSpan(parent)) { 86 | log.info(" Hello from producer", 87 | tracer.currentSpan().context().traceId()); 88 | } 89 | } 90 | }); 91 | } 92 | 93 | private static Span spanFromContext(Tracer tracer, CurrentTraceContext currentTraceContext, RequestContext context) { 94 | Span span = context.getOrDefault(Span.class, null); 95 | if (span != null) { 96 | if (log.isDebugEnabled()) { 97 | log.debug("Found a span in mongo context [" + span + "]"); 98 | } 99 | return span; 100 | } 101 | TraceContext traceContext = context.getOrDefault(TraceContext.class, null); 102 | if (traceContext != null) { 103 | try (CurrentTraceContext.Scope scope = currentTraceContext.maybeScope(traceContext)) { 104 | if (log.isDebugEnabled()) { 105 | log.debug("Found a trace context in mongo context [" + traceContext + "]"); 106 | } 107 | return tracer.currentSpan(); 108 | } 109 | } 110 | return null; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /kafka-reactive-consumer/src/main/java/com/example/sleuthsamples/KafkaReactiveConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sleuthsamples; 2 | 3 | import java.util.Collections; 4 | 5 | import org.apache.kafka.clients.admin.NewTopic; 6 | import org.apache.kafka.clients.consumer.ConsumerRecord; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import reactor.core.publisher.Flux; 10 | import reactor.kafka.receiver.KafkaReceiver; 11 | import reactor.kafka.receiver.ReceiverOptions; 12 | import reactor.util.function.Tuple2; 13 | import reactor.util.function.Tuples; 14 | 15 | import org.springframework.boot.CommandLineRunner; 16 | import org.springframework.boot.WebApplicationType; 17 | import org.springframework.boot.autoconfigure.SpringBootApplication; 18 | import org.springframework.boot.autoconfigure.kafka.KafkaProperties; 19 | import org.springframework.boot.builder.SpringApplicationBuilder; 20 | import org.springframework.cloud.sleuth.Span; 21 | import org.springframework.cloud.sleuth.SpanAndScope; 22 | import org.springframework.cloud.sleuth.Tracer; 23 | import org.springframework.cloud.sleuth.instrument.kafka.TracingKafkaConsumerFactory; 24 | import org.springframework.cloud.sleuth.propagation.Propagator; 25 | import org.springframework.context.annotation.Bean; 26 | import org.springframework.kafka.annotation.EnableKafka; 27 | 28 | @SpringBootApplication 29 | @EnableKafka 30 | public class KafkaReactiveConsumerApplication { 31 | 32 | public static void main(String... args) { 33 | new SpringApplicationBuilder(KafkaReactiveConsumerApplication.class).web(WebApplicationType.NONE).run(args); 34 | } 35 | 36 | @Bean 37 | NewTopic myTopic() { 38 | return new NewTopic("mytopic2", 1, (short) 1); 39 | } 40 | 41 | @Bean 42 | MyKafkaListener myKafkaListener(Tracer tracer, KafkaReceiver kafkaReceiver, Propagator.Getter> extractor, Propagator propagator) { 43 | return new MyKafkaListener(tracer, kafkaReceiver, extractor, propagator); 44 | } 45 | 46 | @Bean 47 | ReceiverOptions kafkaReceiverOptions(KafkaProperties kafkaProperties) { 48 | ReceiverOptions basicReceiverOptions = ReceiverOptions.create(kafkaProperties.buildConsumerProperties()); 49 | return basicReceiverOptions.subscription(Collections.singletonList("mytopic2")); 50 | } 51 | 52 | @Bean 53 | KafkaReceiver reactiveKafkaReceiver(TracingKafkaConsumerFactory tracingKafkaConsumerFactory, ReceiverOptions kafkaReceiverOptions) { 54 | return KafkaReceiver.create(tracingKafkaConsumerFactory, kafkaReceiverOptions); 55 | } 56 | 57 | @Bean 58 | MyRunner myRunner(MyKafkaListener myKafkaListener) { 59 | return new MyRunner(myKafkaListener); 60 | } 61 | } 62 | 63 | class MyRunner implements CommandLineRunner { 64 | 65 | private final MyKafkaListener myKafkaListener; 66 | 67 | MyRunner(MyKafkaListener myKafkaListener) { 68 | this.myKafkaListener = myKafkaListener; 69 | } 70 | 71 | @Override 72 | public void run(String... args) throws Exception { 73 | this.myKafkaListener.onMessage().subscribe(); 74 | } 75 | } 76 | 77 | class MyKafkaListener { 78 | 79 | private static final Logger log = LoggerFactory.getLogger(MyKafkaListener.class); 80 | 81 | private final Tracer tracer; 82 | 83 | private final KafkaReceiver kafkaReceiver; 84 | 85 | // for putting a span in scope 86 | private final Propagator.Getter> extractor; 87 | 88 | // for putting a span in scope 89 | private final Propagator propagator; 90 | 91 | MyKafkaListener(Tracer tracer, KafkaReceiver kafkaReceiver, Propagator.Getter> extractor, Propagator propagator) { 92 | this.tracer = tracer; 93 | this.kafkaReceiver = kafkaReceiver; 94 | this.extractor = extractor; 95 | this.propagator = propagator; 96 | } 97 | 98 | Flux onMessage() { 99 | return kafkaReceiver 100 | .receiveAutoAck() 101 | .flatMap(consumerRecord -> consumerRecord) 102 | // for putting a span in scope 103 | .flatMap(consumerRecord -> { 104 | Span.Builder builder = propagator.extract(consumerRecord, extractor); 105 | Span childSpan = builder.name("on-message").start(); 106 | SpanAndScope spanAndScope = new SpanAndScope(childSpan, tracer.withSpan(childSpan)); 107 | return Flux.just(Tuples.of(consumerRecord.value(), spanAndScope)) 108 | .doOnNext(consRecord -> log.info(" Hello from consumer", tracer.currentSpan().context().traceId())) // for tests - you don't need this in your code 109 | .doOnNext(objects -> log.info("Got message <{}>", objects.getT1())) 110 | .doOnError(throwable -> log.error("Exception occurred", throwable)) 111 | .doFinally(signalType -> spanAndScope.close()); 112 | }) 113 | .map(Tuple2::getT1); 114 | 115 | } 116 | 117 | } 118 | --------------------------------------------------------------------------------