├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ ├── maven-wrapper.properties
│ └── MavenWrapperDownloader.java
├── sleuth-camel-core
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ └── spring.factories
│ │ └── java
│ │ │ └── com.playtika.sleuth.camel
│ │ │ ├── SleuthCamelConstants.java
│ │ │ ├── SleuthCamelAutoConfiguration.java
│ │ │ ├── SentEventNotifier.java
│ │ │ └── CreatedEventNotifier.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── playtika
│ │ └── sleuth
│ │ └── camel
│ │ ├── functional
│ │ ├── TestApp.java
│ │ └── FunctionalTest.java
│ │ ├── SentEventNotifierTest.java
│ │ └── CreatedEventNotifierTest.java
└── pom.xml
├── .gitignore
├── .circleci
├── circleci.settings.xml
├── gpg.playtika.pub
└── config.yml
├── LICENSE
├── README.md
├── mvnw.cmd
├── mvnw
└── pom.xml
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PlaytikaOSS/sleuth-camel/HEAD/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
--------------------------------------------------------------------------------
/sleuth-camel-core/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
2 | com.playtika.sleuth.camel.SleuthCamelAutoConfiguration
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 |
12 | ### IntelliJ IDEA ###
13 | .idea
14 | *.iws
15 | *.iml
16 | *.ipr
17 |
18 | ### NetBeans ###
19 | nbproject/private/
20 | build/
21 | nbbuild/
22 | dist/
23 | nbdist/
24 | .nb-gradle/
--------------------------------------------------------------------------------
/.circleci/circleci.settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ossrh
5 | ${JIRA_USER}
6 | ${JIRA_PASSWORD}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.circleci/gpg.playtika.pub:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 |
3 | mQENBFoESb4BCACsvwcKLlZKdMO112dyRnZQpVlRg+N/8uGPYT5FUcmEfQAMDAvn
4 | AlabchhRhuJkWODzntYcX6wIBPxrkh1oFazag/y7fsqmS8JHIWbrC6sD8OrvjenP
5 | FFFxIBb6dhOemj5QeP0Rcvdhxoha9BjJUj0UP0rqaykh7GOKIekZQyidYQkeTTu4
6 | 8z+ddKLXKFYaQp5JkIX4B8BPnAgsQWbrmZWvGZtOohSbLerj2b77w3ffZS8foRdz
7 | +N6EoITJZ+lVMSB4xVdchZbOqCfPNGRbI0LTcZ9TCyAQcWtAeuP+minPx7a2lzZe
8 | WKsuU6ky9I/gs6jZdD//Gsi/Zlf33/VvwSSNABEBAAG0HFBsYXl0aWthIDxpbmZv
9 | QHBsYXl0aWthLmNvbT6JAVQEEwEIAD4WIQRyzg+3tQ4ZVgpkqv8QblwTPu8kxwUC
10 | WgRJvgIbAwUJA8JnAAULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAQblwTPu8k
11 | x4HDB/9RMn06G/d8dnzXd2jg79/YGn1c/xMBig3bC110AyJAIx3HZ1Xu0br7Qnma
12 | 1XG7FaXme7WzwFZLaCS5pP4iWViVdbb/wm2eUGkVY4t7Q/h4nkdFNGCeJJzhjbLI
13 | /KYjvzlKiESNVmLjcWru7GbUq5fefiLbWIGEf8axiLQpRz5k3P3ogBvZNaOEunta
14 | MrZN9Y+qCzIne5PaUSA6hTzZOln2daVR9SvqJ6ldoaWSXpRnYrjsBYeQiZaA7sRO
15 | 1rece2M2YuRgMOfi39aVDrPthoX+l9AMVptequjBu3bzJhkkSyCWthbqIl/nTqd9
16 | i/mVHn24t8Ht/VkplLYOwuq3SlZo
17 | =PiBY
18 | -----END PGP PUBLIC KEY BLOCK-----
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Playtika
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/main/java/com.playtika.sleuth.camel/SleuthCamelConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel;
26 |
27 | import lombok.experimental.UtilityClass;
28 |
29 | @UtilityClass
30 | public class SleuthCamelConstants {
31 |
32 | public static final String EXCHANGE_IS_TRACED_BY_BRAVE = "ExchangeIsInTracingContext";
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | # Java Maven CircleCI 2.0 configuration file
2 | #
3 | # Check https://circleci.com/docs/2.0/language-java/ for more details
4 | #
5 | version: 2
6 | jobs:
7 | build:
8 | machine:
9 | image: circleci/classic:201708-01
10 |
11 | # working_directory: ~/repo
12 |
13 | environment:
14 | # Customize the JVM maximum heap limit
15 | MAVEN_OPTS: -Xmx1024m
16 |
17 | steps:
18 | - add_ssh_keys:
19 | fingerprints:
20 | - "ae:b8:4a:86:da:b3:7f:35:f5:62:68:61:d6:29:8b:ac"
21 | - checkout
22 | - run:
23 | name: Run build with tests
24 | command: if [[ -z "$GIT_USER_EMAIL" ]]; then mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn ;fi
25 | - run:
26 | name: Save test results
27 | command: |
28 | mkdir -p ~/junit/
29 | find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/junit/ \;
30 | bash <(curl -s https://codecov.io/bash)
31 | when: always
32 | - store_test_results:
33 | path: ~/junit
34 | - store_artifacts:
35 | path: ~/junit
36 | - run:
37 | name: Save artifacts
38 | command: |
39 | mkdir -p ~/artifacts/
40 | find . -type f -regex ".*/target/.*jar" -exec cp {} ~/artifacts/ \;
41 | when: always
42 | - store_test_results:
43 | path: ~/artifacts
44 | - store_artifacts:
45 | path: ~/artifacts
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://circleci.com/gh/Playtika/sleuth-camel/tree/develop)
2 | [](https://codecov.io/gh/Playtika/sleuth-camel)
3 | [](https://www.codacy.com/app/PlaytikaGithub/sleuth-camel?utm_source=github.com&utm_medium=referral&utm_content=Playtika/sleuth-camel&utm_campaign=Badge_Grade)
4 | [](https://maven-badges.herokuapp.com/maven-central/com.playtika.sleuth/sleuth-camel)
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | # Sleuth-camel library
14 | If you are using camel along with spring boot and willing to have your routes to be traced - this library is what you need.
15 |
16 | ## Usage
17 | In order to integrate functionality provided by this library tou need to add following dependency:
18 |
19 | ```xml
20 |
21 | com.playtika.sleuth
22 | sleuth-camel-core
23 |
24 | ```
25 | And that is pretty all, library contains spring boot auto-configuration which will do the magic with your camel context for you.
26 | If for some reason integration should be disabled - just add following property:
27 | ```properties
28 | spring.sleuth.camel.enabled=false
29 | ```
30 |
31 | Planning to use threads() dsl in camel route?
32 | Use [TraceableExecutorService](https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/html/integrations.html#sleuth-async-executor-service-integration)
33 |
34 | ```
35 | TraceableExecutorService traceableExecutorService = new TraceableExecutorService(beanFactory, executorService);
36 |
37 | from(kafkaProperties)
38 | .threads()
39 | .executorService(traceableExecutorService)
40 | .routeId(ROUTE_ID)
41 | ```
42 |
43 | Version correspondence:
44 | * Spring Boot 1.5.x: sleuth-camel-core 1.x.
45 | * Spring Boot 2.0.x-2.3.x: sleuth-camel-core 2.0.x.
46 | * Spring Boot 2.4+: sleuth-camel-core 2.1.x.
47 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/main/java/com.playtika.sleuth.camel/SleuthCamelAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel;
26 |
27 | import brave.Tracer;
28 | import brave.Tracing;
29 | import brave.propagation.ThreadLocalSpan;
30 | import lombok.AllArgsConstructor;
31 | import org.apache.camel.CamelContext;
32 | import org.springframework.boot.autoconfigure.AutoConfigureAfter;
33 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
34 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
35 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
36 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
37 | import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
38 | import org.springframework.context.annotation.Bean;
39 | import org.springframework.context.annotation.Configuration;
40 |
41 | @AllArgsConstructor
42 | @Configuration
43 | @ConditionalOnBean(Tracer.class)
44 | @ConditionalOnClass({CamelContext.class})
45 | @AutoConfigureAfter({BraveAutoConfiguration.class})
46 | @ConditionalOnProperty(value = "spring.sleuth.camel.enabled", matchIfMissing = true)
47 | public class SleuthCamelAutoConfiguration {
48 |
49 | private final CamelContext camelContext;
50 | private final Tracer tracer;
51 |
52 | @Bean
53 | @ConditionalOnMissingBean
54 | public CreatedEventNotifier createdEventNotifier(Tracing tracing, ThreadLocalSpan threadLocalSpan) {
55 | CreatedEventNotifier createdEventNotifier = new CreatedEventNotifier(tracing, threadLocalSpan, tracer);
56 | camelContext.getManagementStrategy().addEventNotifier(createdEventNotifier);
57 | return createdEventNotifier;
58 | }
59 |
60 | @Bean
61 | @ConditionalOnMissingBean
62 | public SentEventNotifier sentEventNotifier(ThreadLocalSpan threadLocalSpan) {
63 | SentEventNotifier sentEventNotifier = new SentEventNotifier(tracer, threadLocalSpan);
64 | camelContext.getManagementStrategy().addEventNotifier(sentEventNotifier);
65 | return sentEventNotifier;
66 | }
67 |
68 | @Bean
69 | public ThreadLocalSpan threadLocalSpan() {
70 | return ThreadLocalSpan.create(this.tracer);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/sleuth-camel-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | sleuth-camel
7 | com.playtika.sleuth
8 | 2.1.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | sleuth-camel-core
13 |
14 |
15 |
16 | org.springframework.cloud
17 | spring-cloud-starter-sleuth
18 | compile
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-aop
23 | provided
24 |
25 |
26 | spring-boot-starter-logging
27 | org.springframework.boot
28 |
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-autoconfigure
34 | provided
35 |
36 |
37 |
38 | org.apache.camel.springboot
39 | camel-spring-boot-starter
40 | provided
41 |
42 |
43 |
44 | org.apache.camel.springboot
45 | camel-direct-starter
46 | ${camel.version}
47 | test
48 |
49 |
50 |
51 | org.projectlombok
52 | lombok
53 | provided
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-starter-test
59 | test
60 |
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-starter-log4j2
65 | test
66 |
67 |
68 |
69 | org.apache.camel
70 | camel-mock
71 | ${camel.version}
72 | test
73 |
74 |
75 |
76 | org.mockito
77 | mockito-inline
78 | test
79 |
80 |
81 |
82 |
83 | io.zipkin.brave
84 | brave-tests
85 | ${brave-test.version}
86 | test
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/test/java/com/playtika/sleuth/camel/functional/TestApp.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel.functional;
26 |
27 | import brave.sampler.Sampler;
28 | import brave.test.TestSpanHandler;
29 | import lombok.extern.slf4j.Slf4j;
30 | import org.apache.camel.Processor;
31 | import org.apache.camel.RoutesBuilder;
32 | import org.apache.camel.builder.RouteBuilder;
33 | import org.springframework.boot.autoconfigure.SpringBootApplication;
34 | import org.springframework.cloud.sleuth.annotation.NewSpan;
35 | import org.springframework.context.annotation.Bean;
36 | import org.springframework.context.annotation.Configuration;
37 |
38 | import static org.apache.camel.LoggingLevel.INFO;
39 |
40 | @SpringBootApplication
41 | @Configuration
42 | public class TestApp {
43 |
44 | static final String DIRECT_ROUTE_URI = "direct:directRoute";
45 | static final String ASYNC_DIRECT_ROUTE_URI = "direct:asyncDirectRoute";
46 | static final String MOCK_DIRECT_ROUTE_TO_URI = "mock:directRouteTo";
47 | static final String MOCK_EXCEPTION_ROUTE_TO_URI = "mock:exceptionRouteTo";
48 | static final String DIRECT_ROUTE_ID = "directRoute";
49 | static final String ASYNC_DIRECT_ROUTE_ID = "asyncDirectRoute";
50 |
51 | @Bean
52 | public Sampler alwaysSampler() {
53 | return Sampler.ALWAYS_SAMPLE;
54 | }
55 |
56 | @Bean
57 | public TestSpanHandler testSpanHandler() {
58 | return new TestSpanHandler();
59 | }
60 |
61 | @Bean
62 | public SomeTracedService someService() {
63 | return new SomeTracedService();
64 | }
65 |
66 | @Bean
67 | public RoutesBuilder camelRoutes(SomeTracedService someTracedService, Processor mockProcessor) {
68 | return new RouteBuilder() {
69 | @Override
70 | public void configure() {
71 | onException(RuntimeException.class)
72 | .log(INFO, "Exception caught. Processing fallback...")
73 | .to(MOCK_EXCEPTION_ROUTE_TO_URI)
74 | .routeId("exceptionRoute");
75 |
76 | from(DIRECT_ROUTE_URI)
77 | .log(INFO, "Message is going to be processed...")
78 | .process(mockProcessor)
79 | .process(exchange -> someTracedService.newSpanMethod())
80 | .to(MOCK_DIRECT_ROUTE_TO_URI)
81 | .routeId(DIRECT_ROUTE_ID);
82 |
83 | from(ASYNC_DIRECT_ROUTE_URI)
84 | .log(INFO, "Message is going to be processed in async way...")
85 | .process(mockProcessor)
86 | .process(exchange -> someTracedService.newSpanMethod())
87 | .threads()
88 | .to(MOCK_DIRECT_ROUTE_TO_URI)
89 | .routeId(ASYNC_DIRECT_ROUTE_ID);
90 | }
91 | };
92 | }
93 |
94 | @Slf4j
95 | public static class SomeTracedService {
96 | @NewSpan
97 | void newSpanMethod() {
98 | log.info("Some service has been invoked.");
99 | }
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.net.*;
21 | import java.io.*;
22 | import java.nio.channels.*;
23 | import java.util.Properties;
24 |
25 | public class MavenWrapperDownloader {
26 |
27 | /**
28 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
29 | */
30 | private static final String DEFAULT_DOWNLOAD_URL =
31 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
32 |
33 | /**
34 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
35 | * use instead of the default one.
36 | */
37 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
38 | ".mvn/wrapper/maven-wrapper.properties";
39 |
40 | /**
41 | * Path where the maven-wrapper.jar will be saved to.
42 | */
43 | private static final String MAVEN_WRAPPER_JAR_PATH =
44 | ".mvn/wrapper/maven-wrapper.jar";
45 |
46 | /**
47 | * Name of the property which should be used to override the default download url for the wrapper.
48 | */
49 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
50 |
51 | public static void main(String args[]) {
52 | System.out.println("- Downloader started");
53 | File baseDirectory = new File(args[0]);
54 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
55 |
56 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
57 | // wrapperUrl parameter.
58 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
59 | String url = DEFAULT_DOWNLOAD_URL;
60 | if(mavenWrapperPropertyFile.exists()) {
61 | FileInputStream mavenWrapperPropertyFileInputStream = null;
62 | try {
63 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
64 | Properties mavenWrapperProperties = new Properties();
65 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
66 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
67 | } catch (IOException e) {
68 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
69 | } finally {
70 | try {
71 | if(mavenWrapperPropertyFileInputStream != null) {
72 | mavenWrapperPropertyFileInputStream.close();
73 | }
74 | } catch (IOException e) {
75 | // Ignore ...
76 | }
77 | }
78 | }
79 | System.out.println("- Downloading from: : " + url);
80 |
81 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
82 | if(!outputFile.getParentFile().exists()) {
83 | if(!outputFile.getParentFile().mkdirs()) {
84 | System.out.println(
85 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
86 | }
87 | }
88 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
89 | try {
90 | downloadFileFromURL(url, outputFile);
91 | System.out.println("Done");
92 | System.exit(0);
93 | } catch (Throwable e) {
94 | System.out.println("- Error downloading");
95 | e.printStackTrace();
96 | System.exit(1);
97 | }
98 | }
99 |
100 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
101 | URL website = new URL(urlString);
102 | ReadableByteChannel rbc;
103 | rbc = Channels.newChannel(website.openStream());
104 | FileOutputStream fos = new FileOutputStream(destination);
105 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
106 | fos.close();
107 | rbc.close();
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/main/java/com.playtika.sleuth.camel/SentEventNotifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel;
26 |
27 | import brave.Span;
28 | import brave.Tags;
29 | import brave.Tracer;
30 | import brave.propagation.ThreadLocalSpan;
31 | import lombok.AllArgsConstructor;
32 | import lombok.extern.slf4j.Slf4j;
33 | import org.apache.camel.Exchange;
34 | import org.apache.camel.impl.event.AbstractExchangeEvent;
35 | import org.apache.camel.impl.event.ExchangeSentEvent;
36 | import org.apache.camel.spi.CamelEvent;
37 | import org.apache.camel.support.EventNotifierSupport;
38 |
39 | import java.util.Objects;
40 |
41 | import static com.playtika.sleuth.camel.SleuthCamelConstants.EXCHANGE_IS_TRACED_BY_BRAVE;
42 |
43 | @Slf4j
44 | @AllArgsConstructor
45 | public class SentEventNotifier extends EventNotifierSupport {
46 |
47 | public static final String EXCHANGE_EVENT_SENT_ANNOTATION = "camel-exchange-event-sent";
48 |
49 | private final Tracer tracer;
50 | private final ThreadLocalSpan threadLocalSpan;
51 |
52 | @Override
53 | public void notify(CamelEvent event) {
54 | if (!(event instanceof CamelEvent.ExchangeFailedEvent) && !(event instanceof CamelEvent.ExchangeCompletedEvent) && !(event instanceof CamelEvent.ExchangeSentEvent)) {
55 | return;
56 | }
57 |
58 | log.trace("Caught an event [{} - {}] - processing...", event.getClass().getSimpleName(), event);
59 | Span currentSpan = tracer.currentSpan();
60 | if (currentSpan == null) {
61 | log.debug("Skipping event [{}] since it's not tracing...", event);
62 | return;
63 | }
64 |
65 | Exchange exchange = ((AbstractExchangeEvent) event).getExchange();
66 | if (!isCamelSpan(exchange)) {
67 | log.debug("Skipping span {}, since it's not camel one.", currentSpan);
68 | return;
69 | }
70 |
71 | if (!isFromSourceEndpoint(event)) {
72 | log.debug("Skipping span {}, since exchange came not from its source route. Event - [{}].", currentSpan, event);
73 | return;
74 | }
75 |
76 | exchange.removeProperty(EXCHANGE_IS_TRACED_BY_BRAVE);
77 |
78 | Span spanToFinish = threadLocalSpan.remove();
79 | logExceptionIfExists(event, spanToFinish);
80 | spanToFinish.annotate(EXCHANGE_EVENT_SENT_ANNOTATION);
81 | spanToFinish.finish();
82 | log.debug("Span {} successfully closed.", spanToFinish);
83 | }
84 |
85 | private boolean isCamelSpan(Exchange exchange) {
86 | Boolean isTracing = exchange.getProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.class);
87 | return isTracing != null && isTracing;
88 | }
89 |
90 | /**
91 | * Handling the case when exchange goes to child route, assuming to have single span for all nested routes.
92 | */
93 | private boolean isFromSourceEndpoint(CamelEvent event) {
94 | if (!(event instanceof ExchangeSentEvent)) {
95 | return true;
96 | }
97 | ExchangeSentEvent exchangeSentEvent = (ExchangeSentEvent) event;
98 | Exchange exchange = exchangeSentEvent.getExchange();
99 | String exchangeEndpointKey = exchange.getFromEndpoint().getEndpointKey();
100 | String eventEndpointKey = exchangeSentEvent.getEndpoint().getEndpointKey();
101 | return Objects.equals(exchangeEndpointKey, eventEndpointKey);
102 | }
103 |
104 | private void logExceptionIfExists(CamelEvent event, Span span) {
105 | AbstractExchangeEvent abstractExchangeEvent = (AbstractExchangeEvent) event;
106 | Exception exception = abstractExchangeEvent.getExchange().getException();
107 | if (exception != null) {
108 | Tags.ERROR.tag(exception, span);
109 | }
110 | }
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/main/java/com.playtika.sleuth.camel/CreatedEventNotifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel;
26 |
27 | import brave.Span;
28 | import brave.Tracer;
29 | import brave.Tracing;
30 | import brave.propagation.ThreadLocalSpan;
31 | import brave.propagation.TraceContext;
32 | import brave.propagation.TraceContextOrSamplingFlags;
33 | import lombok.extern.slf4j.Slf4j;
34 | import org.apache.camel.Endpoint;
35 | import org.apache.camel.Exchange;
36 | import org.apache.camel.Message;
37 | import org.apache.camel.spi.CamelEvent;
38 | import org.apache.camel.support.EventNotifierSupport;
39 | import org.springframework.cloud.sleuth.internal.SpanNameUtil;
40 |
41 | import static com.playtika.sleuth.camel.SleuthCamelConstants.EXCHANGE_IS_TRACED_BY_BRAVE;
42 |
43 | @Slf4j
44 | public class CreatedEventNotifier extends EventNotifierSupport {
45 |
46 | static final String EXCHANGE_EVENT_CREATED_ANNOTATION = "camel-exchange-event-created";
47 | static final String EXCHANGE_ID_TAG_ANNOTATION = "camel-exchange-id";
48 | private static final String MESSAGE_COMPONENT = "camel";
49 |
50 | private final ThreadLocalSpan threadLocalSpan;
51 |
52 | private final TraceContext.Injector injector;
53 | private final TraceContext.Extractor extractor;
54 | private final Tracer tracer;
55 |
56 | public CreatedEventNotifier(Tracing tracing, ThreadLocalSpan threadLocalSpan, Tracer tracer) {
57 | this.threadLocalSpan = threadLocalSpan;
58 | this.tracer = tracer;
59 | this.injector = tracing.propagation().injector(Message::setHeader);
60 | this.extractor = tracing.propagation().extractor((carrier, key) -> carrier.getHeader(key, String.class));
61 | }
62 |
63 | @Override
64 | public void notify(CamelEvent event) {
65 | log.trace("Caught an event [{} - {}] - processing...", event.getClass().getSimpleName(), event);
66 | CamelEvent.ExchangeCreatedEvent exchangeCreatedEvent = (CamelEvent.ExchangeCreatedEvent) event;
67 | Exchange exchange = exchangeCreatedEvent.getExchange();
68 | Endpoint endpoint = exchange.getFromEndpoint();
69 | Message message = exchange.getIn();
70 | TraceContextOrSamplingFlags extractedContext = extractor.extract(message);
71 | boolean isExternalContext = TraceContextOrSamplingFlags.EMPTY != extractedContext;
72 | Span possiblyExistingSpan = tracer.currentSpan();
73 |
74 | Span span = threadLocalSpan.next(extractedContext);
75 | String spanName = getSpanName(endpoint);
76 | span.name(spanName);
77 | span.start();
78 |
79 | span.annotate(EXCHANGE_EVENT_CREATED_ANNOTATION);
80 | span.tag(EXCHANGE_ID_TAG_ANNOTATION, exchange.getExchangeId());
81 |
82 | exchange.setProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.TRUE);
83 |
84 | // If an external tracing context could be extracted from the message, there is no
85 | // need to set a different one.
86 | if (!isExternalContext) {
87 | if (null != possiblyExistingSpan) {
88 | // A span already existed prior to being called, so put that span context into the message
89 | injector.inject(possiblyExistingSpan.context(), message);
90 | } else {
91 | // The span was created in this notifier, so use it.
92 | injector.inject(span.context(), message);
93 | }
94 | }
95 | log.debug("Created/continued span [{}]", span);
96 | }
97 |
98 | private String getSpanName(Endpoint endpoint) {
99 | return SpanNameUtil.shorten(MESSAGE_COMPONENT + "::" + endpoint.getEndpointKey());
100 | }
101 |
102 | @Override
103 | public boolean isEnabled(CamelEvent event) {
104 | return event instanceof CamelEvent.ExchangeCreatedEvent;
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/test/java/com/playtika/sleuth/camel/SentEventNotifierTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel;
26 |
27 | import brave.Span;
28 | import brave.Tracer;
29 | import brave.propagation.ThreadLocalSpan;
30 | import org.apache.camel.Endpoint;
31 | import org.apache.camel.Exchange;
32 | import org.apache.camel.impl.event.ExchangeCompletedEvent;
33 | import org.apache.camel.impl.event.ExchangeSentEvent;
34 | import org.apache.camel.spi.CamelEvent;
35 | import org.junit.jupiter.api.AfterEach;
36 | import org.junit.jupiter.api.Test;
37 | import org.junit.jupiter.api.TestInstance;
38 | import org.junit.jupiter.api.extension.ExtendWith;
39 | import org.mockito.InjectMocks;
40 | import org.mockito.Mock;
41 | import org.mockito.Mockito;
42 | import org.mockito.junit.jupiter.MockitoExtension;
43 | import org.mockito.junit.jupiter.MockitoSettings;
44 |
45 | import static com.playtika.sleuth.camel.SentEventNotifier.EXCHANGE_EVENT_SENT_ANNOTATION;
46 | import static com.playtika.sleuth.camel.SleuthCamelConstants.EXCHANGE_IS_TRACED_BY_BRAVE;
47 | import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD;
48 | import static org.mockito.Mockito.*;
49 | import static org.mockito.quality.Strictness.STRICT_STUBS;
50 |
51 | @ExtendWith(MockitoExtension.class)
52 | @MockitoSettings(strictness = STRICT_STUBS)
53 | @TestInstance(PER_METHOD)
54 | public class SentEventNotifierTest {
55 |
56 | @Mock()
57 | private Tracer tracer;
58 | @Mock
59 | private ThreadLocalSpan threadLocalSpan;
60 | @InjectMocks
61 | private SentEventNotifier sentEventNotifier;
62 |
63 | @AfterEach
64 | public void tearDown() {
65 | verifyNoMoreInteractions(tracer);
66 | }
67 |
68 | @Test
69 | public void shouldProceedRemoteSpan() {
70 | Exchange exchange = mock(Exchange.class);
71 | CamelEvent event = new ExchangeCompletedEvent(exchange);
72 | Span currentSpan = mock(Span.class);
73 | Span spanToSend = mock(Span.class);
74 |
75 | when(tracer.currentSpan()).thenReturn(currentSpan);
76 | when(threadLocalSpan.remove()).thenReturn(spanToSend);
77 | when(exchange.getException()).thenReturn(null);
78 | when(exchange.getProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.class)).thenReturn(Boolean.TRUE);
79 |
80 | sentEventNotifier.notify(event);
81 |
82 | verify(tracer).currentSpan();
83 | verify(exchange).removeProperty(EXCHANGE_IS_TRACED_BY_BRAVE);
84 | verify(spanToSend).annotate(EXCHANGE_EVENT_SENT_ANNOTATION);
85 | verify(spanToSend).finish();
86 | verifyNoMoreInteractions(currentSpan, spanToSend);
87 | }
88 |
89 | @Test
90 | public void shouldProceedWithFailureMessage() {
91 | Exchange exchange = mock(Exchange.class);
92 | CamelEvent event = new ExchangeCompletedEvent(exchange);
93 | Span currentSpan = mock(Span.class);
94 | Span spanToSend = mock(Span.class);
95 | RuntimeException exception = new RuntimeException("some error");
96 |
97 | when(tracer.currentSpan()).thenReturn(currentSpan);
98 | when(threadLocalSpan.remove()).thenReturn(spanToSend);
99 | when(exchange.getException()).thenReturn(exception);
100 | when(exchange.getProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.class)).thenReturn(Boolean.TRUE);
101 |
102 | sentEventNotifier.notify(event);
103 |
104 | verify(tracer).currentSpan();
105 | verify(exchange).removeProperty(EXCHANGE_IS_TRACED_BY_BRAVE);
106 | verify(spanToSend).annotate(EXCHANGE_EVENT_SENT_ANNOTATION);
107 | verify(spanToSend).finish();
108 | verify(spanToSend).tag(Mockito.any(), Mockito.any());
109 | verify(spanToSend).annotate(Mockito.any());
110 | verify(spanToSend).finish();
111 | verify(spanToSend).isNoop();
112 | verify(spanToSend).context();
113 | verifyNoMoreInteractions(currentSpan, spanToSend);
114 | }
115 |
116 | @Test
117 | public void shouldNotProceedIfCameFromDifferentRoute() {
118 | Endpoint eventEndpoint = mock(Endpoint.class);
119 | Endpoint exchangeEndpoint = mock(Endpoint.class);
120 | Exchange exchange = mock(Exchange.class);
121 | Span currentSpan = mock(Span.class);
122 | CamelEvent event = new ExchangeSentEvent(exchange, eventEndpoint, 0);
123 |
124 | when(tracer.currentSpan()).thenReturn(currentSpan);
125 | when(exchange.getProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.class)).thenReturn(Boolean.TRUE);
126 | when(exchange.getFromEndpoint()).thenReturn(exchangeEndpoint);
127 | when(eventEndpoint.getEndpointKey()).thenReturn("direct:/test1");
128 | when(exchangeEndpoint.getEndpointKey()).thenReturn("direct:/test2");
129 |
130 | sentEventNotifier.notify(event);
131 |
132 | verify(tracer).currentSpan();
133 | verifyNoMoreInteractions(currentSpan);
134 | }
135 |
136 | @Test
137 | public void shouldNotProceedIfSpanNotFromCamel() {
138 | Exchange exchange = mock(Exchange.class);
139 | CamelEvent event = new ExchangeCompletedEvent(exchange);
140 | Span currentSpan = mock(Span.class);
141 |
142 | when(tracer.currentSpan()).thenReturn(currentSpan);
143 | when(exchange.getProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.class)).thenReturn(Boolean.FALSE);
144 |
145 | sentEventNotifier.notify(event);
146 |
147 | verify(tracer).currentSpan();
148 | verifyNoMoreInteractions(currentSpan);
149 | }
150 |
151 | @Test
152 | public void shouldNotProceedIfNotTracing() {
153 | CamelEvent event = new ExchangeCompletedEvent(mock(Exchange.class));
154 |
155 | when(tracer.currentSpan()).thenReturn(null);
156 |
157 | sentEventNotifier.notify(event);
158 |
159 | verify(tracer).currentSpan();
160 | }
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/test/java/com/playtika/sleuth/camel/CreatedEventNotifierTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel;
26 |
27 | import brave.Span;
28 | import brave.Tracer;
29 | import brave.Tracing;
30 | import brave.propagation.Propagation;
31 | import brave.propagation.ThreadLocalSpan;
32 | import brave.propagation.TraceContext;
33 | import brave.propagation.TraceContextOrSamplingFlags;
34 | import org.apache.camel.Endpoint;
35 | import org.apache.camel.Exchange;
36 | import org.apache.camel.Message;
37 | import org.apache.camel.impl.event.ExchangeCreatedEvent;
38 | import org.apache.camel.impl.event.ExchangeSentEvent;
39 | import org.apache.camel.spi.CamelEvent;
40 | import org.junit.jupiter.api.BeforeEach;
41 | import org.junit.jupiter.api.Test;
42 | import org.junit.jupiter.api.TestInstance;
43 | import org.junit.jupiter.api.extension.ExtendWith;
44 | import org.mockito.Mock;
45 | import org.mockito.Mockito;
46 | import org.mockito.junit.jupiter.MockitoExtension;
47 | import org.mockito.junit.jupiter.MockitoSettings;
48 | import org.mockito.quality.Strictness;
49 |
50 | import static com.playtika.sleuth.camel.CreatedEventNotifier.EXCHANGE_EVENT_CREATED_ANNOTATION;
51 | import static com.playtika.sleuth.camel.CreatedEventNotifier.EXCHANGE_ID_TAG_ANNOTATION;
52 | import static com.playtika.sleuth.camel.SleuthCamelConstants.EXCHANGE_IS_TRACED_BY_BRAVE;
53 | import static org.junit.jupiter.api.Assertions.assertFalse;
54 | import static org.junit.jupiter.api.Assertions.assertTrue;
55 | import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
56 | import static org.mockito.Mockito.*;
57 |
58 | @ExtendWith(MockitoExtension.class)
59 | @MockitoSettings(strictness = Strictness.STRICT_STUBS)
60 | @TestInstance(PER_CLASS)
61 | public class CreatedEventNotifierTest {
62 |
63 | @Mock
64 | private ThreadLocalSpan threadLocalSpan;
65 | @Mock
66 | private Tracing tracing;
67 | @Mock
68 | private Propagation propagation;
69 |
70 | @Mock
71 | private TraceContext.Injector injector;
72 | @Mock
73 | private TraceContext.Extractor extractor;
74 | @Mock
75 | private TraceContextOrSamplingFlags extractedContext;
76 |
77 | @Mock
78 | private Tracer tracer;
79 |
80 | private CreatedEventNotifier notifier;
81 |
82 | @BeforeEach
83 | public void setUp() throws Exception {
84 | when(tracing.propagation()).thenReturn(propagation);
85 | when(propagation.extractor(any(Propagation.Getter.class))).thenReturn(extractor);
86 | when(propagation.injector(any(Propagation.Setter.class))).thenReturn(injector);
87 | notifier = new CreatedEventNotifier(tracing, threadLocalSpan, tracer);
88 | }
89 |
90 | @Test
91 | public void shouldContinueSpan() {
92 | CamelEvent.ExchangeCreatedEvent event = mock(CamelEvent.ExchangeCreatedEvent.class);
93 | Exchange exchange = mock(Exchange.class);
94 | Endpoint endpoint = mock(Endpoint.class);
95 | Message message = mock(Message.class);
96 | Span span = mock(Span.class);
97 | TraceContext traceContext = mock(TraceContext.class);
98 | String someExchangeId = "some exchange Id";
99 | String endpointKet = "camelDirectRoute";
100 |
101 | when(event.getExchange()).thenReturn(exchange);
102 | when(exchange.getFromEndpoint()).thenReturn(endpoint);
103 | when(exchange.getIn()).thenReturn(message);
104 | when(exchange.getExchangeId()).thenReturn(someExchangeId);
105 | when(endpoint.getEndpointKey()).thenReturn(endpointKet);
106 |
107 | when(extractor.extract(message)).thenReturn(TraceContextOrSamplingFlags.EMPTY);
108 | when(threadLocalSpan.next(TraceContextOrSamplingFlags.EMPTY)).thenReturn(span);
109 | when(span.context()).thenReturn(traceContext);
110 |
111 | notifier.notify(event);
112 |
113 | verify(tracing, times(2)).propagation();
114 | verify(threadLocalSpan).next(Mockito.any());
115 | verify(tracer).currentSpan();
116 | verify(span).name("camel::" + endpointKet);
117 | verify(span).start();
118 | verify(span).annotate(EXCHANGE_EVENT_CREATED_ANNOTATION);
119 | verify(span).tag(EXCHANGE_ID_TAG_ANNOTATION, exchange.getExchangeId());
120 | verify(span).context();
121 | verify(exchange).setProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.TRUE);
122 | verify(injector).inject(traceContext, message);
123 |
124 | verifyNoMoreInteractions(tracing, threadLocalSpan, span);
125 | }
126 |
127 | @Test
128 | public void shouldStartNewSpan() {
129 | CamelEvent.ExchangeCreatedEvent event = mock(CamelEvent.ExchangeCreatedEvent.class);
130 | Exchange exchange = mock(Exchange.class);
131 | Endpoint endpoint = mock(Endpoint.class);
132 | Message message = mock(Message.class);
133 | Span span = mock(Span.class);
134 | TraceContext traceContext = mock(TraceContext.class);
135 | String someExchangeId = "some exchange Id";
136 | String endpointKet = "camelDirectRoute";
137 |
138 | when(event.getExchange()).thenReturn(exchange);
139 | when(exchange.getFromEndpoint()).thenReturn(endpoint);
140 | when(exchange.getIn()).thenReturn(message);
141 | when(exchange.getExchangeId()).thenReturn(someExchangeId);
142 | when(endpoint.getEndpointKey()).thenReturn(endpointKet);
143 |
144 | when(tracer.currentSpan()).thenReturn(span);
145 | when(extractor.extract(message)).thenReturn(TraceContextOrSamplingFlags.EMPTY);
146 | when(threadLocalSpan.next(TraceContextOrSamplingFlags.EMPTY)).thenReturn(span);
147 | when(span.context()).thenReturn(traceContext);
148 |
149 | notifier.notify(event);
150 |
151 | verify(tracing, times(2)).propagation();
152 | verify(tracer).currentSpan();
153 | verify(threadLocalSpan).next(Mockito.any());
154 | verify(span).name("camel::" + endpointKet);
155 | verify(span).start();
156 | verify(span).annotate(EXCHANGE_EVENT_CREATED_ANNOTATION);
157 | verify(span).tag(EXCHANGE_ID_TAG_ANNOTATION, exchange.getExchangeId());
158 | verify(span).context();
159 | verify(exchange).setProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.TRUE);
160 | verify(injector).inject(traceContext, message);
161 |
162 | verifyNoMoreInteractions(tracing, threadLocalSpan, span);
163 | }
164 |
165 | @Test
166 | public void shouldHonourRemoteSpanFromMessage() {
167 | CamelEvent.ExchangeCreatedEvent event = mock(CamelEvent.ExchangeCreatedEvent.class);
168 | Exchange exchange = mock(Exchange.class);
169 | Endpoint endpoint = mock(Endpoint.class);
170 | Message message = mock(Message.class);
171 | Span span = mock(Span.class);
172 | String someExchangeId = "some exchange Id";
173 | String endpointKet = "camelDirectRoute";
174 |
175 | when(event.getExchange()).thenReturn(exchange);
176 | when(exchange.getFromEndpoint()).thenReturn(endpoint);
177 | when(exchange.getIn()).thenReturn(message);
178 | when(exchange.getExchangeId()).thenReturn(someExchangeId);
179 | when(endpoint.getEndpointKey()).thenReturn(endpointKet);
180 |
181 | when(extractor.extract(message)).thenReturn(extractedContext);
182 | when(threadLocalSpan.next(extractedContext)).thenReturn(span);
183 |
184 | notifier.notify(event);
185 |
186 | verify(tracing, times(2)).propagation();
187 | verify(tracer).currentSpan();
188 | verify(threadLocalSpan).next(Mockito.any());
189 | verify(span).name("camel::" + endpointKet);
190 | verify(span).start();
191 | verify(span).annotate(EXCHANGE_EVENT_CREATED_ANNOTATION);
192 | verify(span).tag(EXCHANGE_ID_TAG_ANNOTATION, exchange.getExchangeId());
193 | verify(exchange).setProperty(EXCHANGE_IS_TRACED_BY_BRAVE, Boolean.TRUE);
194 |
195 | verifyNoMoreInteractions(tracing, threadLocalSpan, span);
196 | }
197 |
198 | @Test
199 | public void shouldBeEnabledInCaseOfCreatedEvent() {
200 | CamelEvent event = new ExchangeCreatedEvent(mock(Exchange.class));
201 |
202 | boolean result = notifier.isEnabled(event);
203 |
204 | assertTrue(result);
205 | }
206 |
207 | @Test
208 | public void shouldNotBeEnabledInCaseOfSentEvent() {
209 | CamelEvent event = new ExchangeSentEvent(mock(Exchange.class), null, 100);
210 |
211 | boolean result = notifier.isEnabled(event);
212 |
213 | assertFalse(result);
214 | }
215 |
216 | }
217 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Mingw, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | ##########################################################################################
204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
205 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
206 | ##########################################################################################
207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
208 | if [ "$MVNW_VERBOSE" = true ]; then
209 | echo "Found .mvn/wrapper/maven-wrapper.jar"
210 | fi
211 | else
212 | if [ "$MVNW_VERBOSE" = true ]; then
213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
214 | fi
215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
216 | while IFS="=" read key value; do
217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
218 | esac
219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
220 | if [ "$MVNW_VERBOSE" = true ]; then
221 | echo "Downloading from: $jarUrl"
222 | fi
223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
224 |
225 | if command -v wget > /dev/null; then
226 | if [ "$MVNW_VERBOSE" = true ]; then
227 | echo "Found wget ... using wget"
228 | fi
229 | wget "$jarUrl" -O "$wrapperJarPath"
230 | elif command -v curl > /dev/null; then
231 | if [ "$MVNW_VERBOSE" = true ]; then
232 | echo "Found curl ... using curl"
233 | fi
234 | curl -o "$wrapperJarPath" "$jarUrl"
235 | else
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Falling back to using Java to download"
238 | fi
239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
240 | if [ -e "$javaClass" ]; then
241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
242 | if [ "$MVNW_VERBOSE" = true ]; then
243 | echo " - Compiling MavenWrapperDownloader.java ..."
244 | fi
245 | # Compiling the Java class
246 | ("$JAVA_HOME/bin/javac" "$javaClass")
247 | fi
248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
249 | # Running the downloader
250 | if [ "$MVNW_VERBOSE" = true ]; then
251 | echo " - Running MavenWrapperDownloader.java ..."
252 | fi
253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
254 | fi
255 | fi
256 | fi
257 | fi
258 | ##########################################################################################
259 | # End of extension
260 | ##########################################################################################
261 |
262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
263 | if [ "$MVNW_VERBOSE" = true ]; then
264 | echo $MAVEN_PROJECTBASEDIR
265 | fi
266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
267 |
268 | # For Cygwin, switch paths to Windows format before running java
269 | if $cygwin; then
270 | [ -n "$M2_HOME" ] &&
271 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
272 | [ -n "$JAVA_HOME" ] &&
273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
274 | [ -n "$CLASSPATH" ] &&
275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
276 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
278 | fi
279 |
280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
281 |
282 | exec "$JAVACMD" \
283 | $MAVEN_OPTS \
284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
287 |
--------------------------------------------------------------------------------
/sleuth-camel-core/src/test/java/com/playtika/sleuth/camel/functional/FunctionalTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Playtika
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.playtika.sleuth.camel.functional;
26 |
27 | import brave.ScopedSpan;
28 | import brave.Tracer;
29 | import brave.handler.MutableSpan;
30 | import brave.propagation.B3SingleFormat;
31 | import brave.test.TestSpanHandler;
32 | import org.apache.camel.*;
33 | import org.apache.camel.component.mock.MockEndpoint;
34 | import org.junit.jupiter.api.AfterEach;
35 | import org.junit.jupiter.api.Test;
36 | import org.junit.jupiter.api.TestInstance;
37 | import org.springframework.beans.factory.annotation.Autowired;
38 | import org.springframework.boot.test.context.SpringBootTest;
39 | import org.springframework.boot.test.mock.mockito.MockBean;
40 |
41 | import java.util.HashMap;
42 | import java.util.List;
43 | import java.util.Map;
44 |
45 | import static com.playtika.sleuth.camel.functional.TestApp.*;
46 | import static org.apache.camel.component.mock.MockEndpoint.resetMocks;
47 | import static org.assertj.core.api.Assertions.assertThat;
48 | import static org.assertj.core.api.Assertions.assertThatThrownBy;
49 | import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
50 | import static org.mockito.Mockito.*;
51 |
52 | @TestInstance(PER_CLASS)
53 | @SpringBootTest(
54 | classes = TestApp.class,
55 | webEnvironment = SpringBootTest.WebEnvironment.NONE,
56 | properties = {
57 | "logging.level.com.playtika.sleuth.camel=trace"
58 | })
59 | public class FunctionalTest {
60 |
61 | private static final String SPAN_ID_HEADER_NAME = "X-B3-SpanId";
62 | private static final String TRACE_ID_HEADER_NAME = "X-B3-TraceId";
63 | private static final String SAMPLED_ID_HEADER_NAME = "X-B3-Sampled";
64 | private static final String PARENT_ID_HEADER_BANE = "X-B3-ParentSpanId";
65 | private static final String SINGLE_B3_HEADER_NAME = "b3";
66 |
67 | private static final Object TEST_BODY = "Some body";
68 |
69 | @Produce(DIRECT_ROUTE_URI)
70 | private ProducerTemplate directRouteProducer;
71 |
72 | @Produce(ASYNC_DIRECT_ROUTE_URI)
73 | private ProducerTemplate asyncDirectRouteProducer;
74 |
75 | @EndpointInject(MOCK_DIRECT_ROUTE_TO_URI)
76 | private MockEndpoint directRouteMockEndpoint;
77 |
78 | @EndpointInject(MOCK_EXCEPTION_ROUTE_TO_URI)
79 | private MockEndpoint exceptionRouteMockEndpoint;
80 |
81 | @Autowired
82 | private TestSpanHandler testSpanHandler;
83 | @Autowired
84 | private Tracer tracer;
85 | @Autowired
86 | private CamelContext camelContext;
87 |
88 | @MockBean
89 | private Processor mockProcessor;
90 |
91 | private ScopedSpan existingSpan;
92 |
93 | @AfterEach
94 | public void tearDown() throws Exception {
95 | resetMocks(camelContext);
96 | if (existingSpan != null) {
97 | existingSpan.finish();
98 | existingSpan = null;
99 | }
100 | testSpanHandler.clear();
101 |
102 | verify(mockProcessor).process(any(Exchange.class));
103 | verifyNoMoreInteractions(mockProcessor);
104 | }
105 |
106 | @Test
107 | public void shouldSendToRouteWithoutTracing() throws Exception {
108 | assertSentToRouteWithoutTracing(directRouteProducer, DIRECT_ROUTE_ID);
109 | }
110 |
111 | @Test
112 | public void shouldSendToRouteWithoutTracingToAsyncRoute() throws Exception {
113 | assertSentToRouteWithoutTracing(asyncDirectRouteProducer, ASYNC_DIRECT_ROUTE_ID);
114 | }
115 |
116 | private void assertSentToRouteWithoutTracing(ProducerTemplate routeProducer, String route) throws InterruptedException {
117 | directRouteMockEndpoint.expectedMessageCount(1);
118 | directRouteMockEndpoint.expectedBodiesReceived(TEST_BODY);
119 |
120 | routeProducer.sendBody(TEST_BODY);
121 |
122 | directRouteMockEndpoint.assertIsSatisfied();
123 |
124 | //assert current span
125 | assertThat(tracer.currentSpan()).isNull();
126 |
127 | //assert message sent with span headers
128 | Map headers = getFirstMessageHeaders(directRouteMockEndpoint);
129 | assertThat(headers.size()).isEqualTo(1);
130 | assertThat(headers.get(SINGLE_B3_HEADER_NAME)).isNotNull();
131 |
132 | //assert span logs
133 | assertAccumulatedSpans(route);
134 | }
135 |
136 | @Test
137 | public void shouldSendToRouteWithExistingSpan() throws Exception {
138 | assertSentToRouteWithExistingSpan(directRouteProducer, DIRECT_ROUTE_ID);
139 | }
140 |
141 | @Test
142 | public void shouldSendToRouteWithExistingSpanToAsyncRoute() throws Exception {
143 | assertSentToRouteWithExistingSpan(asyncDirectRouteProducer, ASYNC_DIRECT_ROUTE_ID);
144 | }
145 |
146 | private void assertSentToRouteWithExistingSpan(ProducerTemplate routeProducer, String route) throws Exception {
147 | existingSpan = tracer.startScopedSpan("existingSpan");
148 | String spanString = B3SingleFormat.writeB3SingleFormat(existingSpan.context());
149 |
150 | directRouteMockEndpoint.expectedMessageCount(1);
151 | directRouteMockEndpoint.expectedBodiesReceived(TEST_BODY);
152 |
153 | routeProducer.sendBody(TEST_BODY);
154 |
155 | directRouteMockEndpoint.assertIsSatisfied();
156 |
157 | //assert current span
158 | assertThat(tracer.currentSpan().context()).isEqualTo(existingSpan.context());
159 |
160 | //assert message sent with span headers
161 | Map headers = getFirstMessageHeaders(directRouteMockEndpoint);
162 | System.out.println("headers:" + headers);
163 | assertThat(headers.size()).isEqualTo(1);
164 | assertThat(headers.get(SINGLE_B3_HEADER_NAME)).isNotNull();
165 | assertThat(headers.get(SINGLE_B3_HEADER_NAME)).isEqualTo(spanString);
166 |
167 | assertAccumulatedSpans(route);
168 |
169 | verify(mockProcessor).process(any(Exchange.class));
170 | }
171 |
172 | @Test
173 | public void shouldSendToRouteWithSpanInHeaders() throws Exception {
174 | assertSentToRouteWithSpanInHeaders(directRouteProducer, DIRECT_ROUTE_ID);
175 | }
176 |
177 | @Test
178 | public void shouldSendToRouteWithSpanInHeadersToAsyncRoute() throws Exception {
179 | assertSentToRouteWithSpanInHeaders(asyncDirectRouteProducer, ASYNC_DIRECT_ROUTE_ID);
180 | }
181 |
182 | private void assertSentToRouteWithSpanInHeaders(ProducerTemplate routeProducer, String route) throws Exception {
183 | directRouteMockEndpoint.expectedMessageCount(1);
184 | directRouteMockEndpoint.expectedBodiesReceived(TEST_BODY);
185 |
186 | String spanId = Long.toHexString(735676786785678L);
187 | String traceId = Long.toHexString(656565656565656L);
188 | String sampled = "1";
189 |
190 | Map incomingMessageHeaders = new HashMap<>();
191 | incomingMessageHeaders.put(SINGLE_B3_HEADER_NAME, spanId + "-" + traceId + "-" + sampled);
192 |
193 | routeProducer.sendBodyAndHeaders(TEST_BODY, incomingMessageHeaders);
194 |
195 | directRouteMockEndpoint.assertIsSatisfied();
196 |
197 | //assert current span
198 | assertThat(tracer.currentSpan()).isNull();
199 |
200 | //assert message sent with span headers
201 | Map headers = getFirstMessageHeaders(directRouteMockEndpoint);
202 | assertThat(headers.size()).isEqualTo(1);
203 | assertThat((String) headers.get(SINGLE_B3_HEADER_NAME)).endsWith(sampled);
204 |
205 | //assert span logs
206 | assertAccumulatedSpans(route);
207 |
208 | verify(mockProcessor).process(any(Exchange.class));
209 | }
210 |
211 | @Test
212 | public void shouldSendFailureSpan() throws Exception {
213 | assertFailureSpanSent(directRouteProducer, DIRECT_ROUTE_ID);
214 | }
215 |
216 | @Test
217 | public void shouldSendFailureSpanToAsyncRoute() throws Exception {
218 | assertFailureSpanSent(asyncDirectRouteProducer, ASYNC_DIRECT_ROUTE_ID);
219 | }
220 |
221 | private void assertFailureSpanSent(ProducerTemplate routeProducer, String routeName) throws Exception {
222 | String errorMessage = "Something went wrong";
223 |
224 | directRouteMockEndpoint.expectedMessageCount(0);
225 | exceptionRouteMockEndpoint.expectedBodiesReceived(1);
226 | exceptionRouteMockEndpoint.expectedBodiesReceived(TEST_BODY);
227 |
228 | doThrow(new RuntimeException(errorMessage)).when(mockProcessor).process(any(Exchange.class));
229 |
230 | //test
231 | assertThatThrownBy(() -> routeProducer.sendBody(TEST_BODY))
232 | .isInstanceOf(CamelExecutionException.class);
233 |
234 | directRouteMockEndpoint.assertIsSatisfied();
235 | exceptionRouteMockEndpoint.assertIsSatisfied();
236 |
237 | //assert current span
238 | assertThat(tracer.currentSpan()).isNull();
239 |
240 | //assert message sent with span headers
241 | Map headers = getFirstMessageHeaders(exceptionRouteMockEndpoint);
242 | assertThat(headers.size()).isGreaterThanOrEqualTo(1);
243 | assertThat(headers.get(SINGLE_B3_HEADER_NAME)).isNotNull();
244 |
245 | //assert span logs
246 | MutableSpan span = getSingleAccumulatedSpan();
247 | assertTagApplied(span, "error", errorMessage);
248 |
249 | verify(mockProcessor).process(any(Exchange.class));
250 | }
251 |
252 | private void assertTagApplied(MutableSpan span, String tag, String value) {
253 | String sampledErrorMessage = span.tags().get(tag);
254 | assertThat(sampledErrorMessage).isEqualTo(value);
255 | }
256 |
257 | private Map getFirstMessageHeaders(MockEndpoint endpoint) {
258 | Message message = endpoint.getExchanges().get(0).getIn();
259 | assertThat(message).isNotNull();
260 | return message.getHeaders();
261 | }
262 |
263 | private MutableSpan getSingleAccumulatedSpan() {
264 | List spans = testSpanHandler.spans();
265 | assertThat(spans.size()).isEqualTo(1);
266 | return spans.get(0);
267 | }
268 |
269 | private void assertAccumulatedSpans(String routeName) {
270 | List spans = testSpanHandler.spans();
271 | assertThat(spans.size()).isEqualTo(2);
272 |
273 | MutableSpan childSpan = spans.get(0);
274 | MutableSpan span = spans.get(1);
275 |
276 | assertSpanParameters(span, childSpan, routeName);
277 | }
278 |
279 | private void assertSpanParameters(MutableSpan parent, MutableSpan child, String routeName) {
280 | assertThat(child.traceId()).isEqualTo(parent.traceId());
281 | assertThat(child.parentId()).isEqualTo(parent.id());
282 | assertThat(parent.name()).isEqualTo("camel::direct://" + routeName);
283 | }
284 |
285 | }
286 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.playtika.sleuth
8 | sleuth-camel
9 | pom
10 | 2.1.1-SNAPSHOT
11 |
12 |
13 | org.springframework.boot
14 | spring-boot-starter-parent
15 | 2.4.4
16 |
17 |
18 | sleuth-camel
19 | sleuth-camel
20 | https://github.com/Playtika/sleuth-camel
21 |
22 |
23 |
24 | MIT
25 | http://opensource.org/licenses/MIT
26 |
27 |
28 |
29 |
30 | https://svn.apache.org/viewvc/maven
31 | scm:git:git://github.com/Playtika/sleuth-camel.git
32 | scm:git:git@github.com:Playtika/sleuth-camel.git
33 | HEAD
34 |
35 |
36 |
37 | sleuth-camel-core
38 |
39 |
40 |
41 | 1.8
42 | 1.8
43 |
44 | 2020.0.2
45 | 3.9.0
46 | 5.13.3
47 |
48 |
49 | 3.2.0
50 | 3.0.0-M3
51 | 3.2.0
52 | 1.6.8
53 | 1.6
54 | 3.0.0-M1
55 |
56 |
57 | 3.0.0-M5
58 | jacoco
59 | reuseReports
60 | ${project.basedir}/../target/jacoco.exec
61 | java
62 | 0.8.6
63 |
64 |
65 | 3EEF24C7
66 | false
67 | true
68 | never
69 |
70 |
71 |
72 |
73 |
74 | org.springframework.cloud
75 | spring-cloud-dependencies
76 | ${spring-cloud-dependencies.version}
77 | pom
78 | import
79 |
80 |
81 |
82 | org.apache.camel.springboot
83 | camel-spring-boot-starter
84 | ${camel.version}
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | spring-milestones
93 | Spring Milestones
94 | http://repo.spring.io/milestone
95 |
96 | false
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | org.apache.maven.plugins
105 | maven-enforcer-plugin
106 | ${maven.enforcer.plugin.version}
107 |
108 |
109 | enforce
110 |
111 |
112 |
113 |
114 | log4j:log4j
115 | org.slf4j:slf4j-log4j12
116 | org.springframework.boot:spring-boot-starter-logging
117 | commons-logging:commons-logging
118 | ch.qos.logback:logback-core
119 | ch.qos.logback:logback-classic
120 |
121 |
122 |
123 |
124 |
125 | enforce
126 |
127 |
128 |
129 |
130 |
131 | org.apache.maven.plugins
132 | maven-source-plugin
133 | ${maven.source.plugin.version}
134 |
135 |
136 | attach-sources
137 |
138 | jar
139 |
140 |
141 |
142 |
143 |
144 | org.apache.maven.plugins
145 | maven-javadoc-plugin
146 | ${maven.javadoc.plugin.version}
147 |
148 |
149 | attach-javadocs
150 |
151 | jar
152 |
153 |
154 |
155 |
156 | -Xdoclint:none
157 | false
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 | sonar
166 |
167 |
168 |
169 | org.jacoco
170 | jacoco-maven-plugin
171 | ${jacoco-maven-plugin.version}
172 |
173 |
174 | pre-unit-test
175 |
176 | prepare-agent
177 |
178 |
179 | surefireArgLine
180 | ${project.build.directory}/jacoco.exec
181 |
182 |
183 |
184 | post-unit-test
185 | test
186 |
187 | report
188 |
189 |
190 |
191 | ${project.build.directory}/jacoco.exec
192 |
193 |
194 |
195 |
196 |
197 | org.apache.maven.plugins
198 | maven-surefire-plugin
199 |
200 |
201 | ${surefireArgLine}
202 |
203 |
204 |
205 | org.apache.maven.plugins
206 | maven-release-plugin
207 | ${maven-release-plugin.version}
208 |
209 | true
210 | false
211 | release
212 | deploy
213 |
214 |
215 |
216 |
217 |
218 |
219 | ossrh
220 |
221 |
222 |
223 | org.sonatype.plugins
224 | nexus-staging-maven-plugin
225 | ${nexus-staging-maven-plugin.version}
226 | true
227 |
228 | ossrh
229 | https://oss.sonatype.org/
230 | true
231 |
232 |
233 |
234 | org.apache.maven.plugins
235 | maven-gpg-plugin
236 | ${maven-gpg-plugin.version}
237 |
238 |
239 | sign-artifacts
240 | verify
241 |
242 | sign
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | ossrh
255 | https://oss.sonatype.org/content/repositories/snapshots
256 |
257 |
258 | ossrh
259 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
260 |
261 |
262 |
263 |
264 |
--------------------------------------------------------------------------------