Skip to content

Commit 1382a67

Browse files
csabakospavolloffay
authored andcommitted
Add support for Reactor instrumentation. (opentracing-contrib#208)
* Add Spring Boot autoconfiguration for Reactor instrumentation. * Bump opentracing-spring-web version to 1.1.1.
1 parent 1bb4069 commit 1382a67

File tree

8 files changed

+271
-3
lines changed

8 files changed

+271
-3
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ This repository provides OpenTracing instrumentation for Spring Boot and its var
55
compatible implementation.
66

77
It contains auto-configurations which instruments and trace following Spring Boot projects:
8-
* Spring Web (RestControllers, RestTemplates, WebAsyncTask)
8+
* Spring Web (RestControllers, RestTemplates, WebAsyncTask, WebClient, WebFlux)
99
* @Async, @Scheduled, Executors
1010
* WebSocket STOMP
1111
* Feign, HystrixFeign
@@ -14,6 +14,7 @@ It contains auto-configurations which instruments and trace following Spring Boo
1414
* JDBC
1515
* Mongo
1616
* Zuul
17+
* Reactor
1718
* RxJava
1819
* Redis
1920
* Standard logging - logs are added to active span
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2017-2019 The OpenTracing Authors
5+
6+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7+
in compliance with the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software distributed under the License
12+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13+
or implied. See the License for the specific language governing permissions and limitations under
14+
the License.
15+
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
18+
<parent>
19+
<artifactId>opentracing-spring-cloud-parent</artifactId>
20+
<groupId>io.opentracing.contrib</groupId>
21+
<version>0.2.5-SNAPSHOT</version>
22+
<relativePath>../../</relativePath>
23+
</parent>
24+
<modelVersion>4.0.0</modelVersion>
25+
26+
<artifactId>opentracing-spring-cloud-reactor-starter</artifactId>
27+
28+
<properties>
29+
<main.basedir>${project.basedir}/../..</main.basedir>
30+
</properties>
31+
32+
<dependencies>
33+
<dependency>
34+
<groupId>org.springframework.boot</groupId>
35+
<artifactId>spring-boot-autoconfigure</artifactId>
36+
</dependency>
37+
<dependency>
38+
<groupId>io.opentracing.contrib</groupId>
39+
<artifactId>opentracing-spring-tracer-configuration-starter</artifactId>
40+
</dependency>
41+
42+
<dependency>
43+
<groupId>io.opentracing.contrib</groupId>
44+
<artifactId>opentracing-concurrent</artifactId>
45+
<version>${version.io.opentracing.contrib-java-concurrent}</version>
46+
</dependency>
47+
<dependency>
48+
<groupId>io.opentracing.contrib</groupId>
49+
<artifactId>opentracing-reactor</artifactId>
50+
<version>${version.io.opentracing.contrib-opentracing-reactor}</version>
51+
</dependency>
52+
<dependency>
53+
<groupId>io.projectreactor</groupId>
54+
<artifactId>reactor-core</artifactId>
55+
<version>${version.reactor-core}</version>
56+
<optional>true</optional>
57+
</dependency>
58+
59+
<dependency>
60+
<groupId>org.springframework.boot</groupId>
61+
<artifactId>spring-boot-starter-test</artifactId>
62+
<scope>test</scope>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.springframework.boot</groupId>
66+
<artifactId>spring-boot-starter-web</artifactId>
67+
<scope>test</scope>
68+
</dependency>
69+
<dependency>
70+
<groupId>io.opentracing.contrib</groupId>
71+
<artifactId>opentracing-spring-web-starter</artifactId>
72+
<version>${version.io.opentracing.contrib-opentracing-spring-web}</version>
73+
<scope>test</scope>
74+
</dependency>
75+
</dependencies>
76+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2013-2019 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 io.opentracing.contrib.spring.cloud.reactor;
17+
18+
import io.opentracing.Tracer;
19+
import io.opentracing.contrib.concurrent.TracedScheduledExecutorService;
20+
import io.opentracing.contrib.reactor.TracedSubscriber;
21+
import io.opentracing.contrib.spring.tracer.configuration.TracerAutoConfiguration;
22+
import javax.annotation.PreDestroy;
23+
import org.springframework.beans.factory.annotation.Autowired;
24+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
26+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
27+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
28+
import org.springframework.context.annotation.Configuration;
29+
import reactor.core.publisher.Hooks;
30+
import reactor.core.scheduler.Schedulers;
31+
32+
/**
33+
* Spring Boot auto-configuration to enable tracing of Reactor components.
34+
*
35+
* Similar to {@code TraceReactorAutoConfiguration} from spring-cloud-sleuth.
36+
*
37+
* @author Csaba Kos
38+
*/
39+
@Configuration
40+
@AutoConfigureAfter(TracerAutoConfiguration.class)
41+
@ConditionalOnBean(Tracer.class)
42+
@ConditionalOnClass(Hooks.class)
43+
@ConditionalOnProperty(name = "opentracing.spring.cloud.reactor.enabled", havingValue = "true", matchIfMissing = true)
44+
public class ReactorTracingAutoConfiguration {
45+
private static final String EXECUTOR_SERVICE_DECORATOR_KEY = ReactorTracingAutoConfiguration.class.getName();
46+
private static final String HOOK_KEY = ReactorTracingAutoConfiguration.class.getName();
47+
48+
@Autowired
49+
public ReactorTracingAutoConfiguration(final Tracer tracer) {
50+
Hooks.onEachOperator(HOOK_KEY, TracedSubscriber.asOperator(tracer));
51+
Schedulers.setExecutorServiceDecorator(
52+
EXECUTOR_SERVICE_DECORATOR_KEY,
53+
(scheduler, scheduledExecutorService) ->
54+
new TracedScheduledExecutorService(scheduledExecutorService, tracer)
55+
);
56+
}
57+
58+
@PreDestroy
59+
public void cleanupHooks() {
60+
Hooks.resetOnEachOperator(HOOK_KEY);
61+
Schedulers.removeExecutorServiceDecorator(EXECUTOR_SERVICE_DECORATOR_KEY);
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"properties": [
3+
{
4+
"name": "opentracing.spring.cloud.reactor.enabled",
5+
"type": "java.lang.Boolean",
6+
"description": "Enable Reactor tracing.",
7+
"defaultValue": true
8+
}
9+
]
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
2+
io.opentracing.contrib.spring.cloud.reactor.ReactorTracingAutoConfiguration
3+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/**
2+
* Copyright 2017-2019 The OpenTracing Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
package io.opentracing.contrib.spring.cloud.reactor;
15+
16+
import static org.awaitility.Awaitility.await;
17+
import static org.junit.Assert.assertEquals;
18+
import static org.junit.Assert.assertNotNull;
19+
20+
import io.opentracing.contrib.spring.cloud.reactor.ReactorTracingAutoConfigurationTest.MockTracingConfiguration;
21+
import io.opentracing.contrib.spring.cloud.reactor.ReactorTracingAutoConfigurationTest.TestController;
22+
import io.opentracing.mock.MockSpan;
23+
import io.opentracing.mock.MockTracer;
24+
import java.util.List;
25+
import org.junit.Before;
26+
import org.junit.Test;
27+
import org.junit.runner.RunWith;
28+
import org.springframework.beans.factory.annotation.Autowired;
29+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
30+
import org.springframework.boot.test.context.SpringBootTest;
31+
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
32+
import org.springframework.boot.test.web.client.TestRestTemplate;
33+
import org.springframework.context.annotation.Bean;
34+
import org.springframework.context.annotation.Configuration;
35+
import org.springframework.http.ResponseEntity;
36+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
37+
import org.springframework.web.bind.annotation.RequestMapping;
38+
import org.springframework.web.bind.annotation.RequestMethod;
39+
import org.springframework.web.bind.annotation.RestController;
40+
import reactor.core.publisher.Flux;
41+
import reactor.core.publisher.Mono;
42+
import reactor.core.scheduler.Schedulers;
43+
44+
@SpringBootTest(
45+
webEnvironment = WebEnvironment.RANDOM_PORT,
46+
classes = {MockTracingConfiguration.class, TestController.class},
47+
properties = {"opentracing.spring.web.client.enabled=false"})
48+
@RunWith(SpringJUnit4ClassRunner.class)
49+
public class ReactorTracingAutoConfigurationTest {
50+
51+
@Configuration
52+
@EnableAutoConfiguration
53+
public static class MockTracingConfiguration {
54+
@Bean
55+
public MockTracer tracer() {
56+
return new MockTracer();
57+
}
58+
}
59+
60+
@RestController
61+
public static class TestController {
62+
63+
@Autowired
64+
private MockTracer mockTracer;
65+
66+
@RequestMapping(method = RequestMethod.GET, value = "/single")
67+
public Mono<Integer> single() {
68+
return Flux.range(1, 10)
69+
.subscribeOn(Schedulers.elastic())
70+
.publishOn(Schedulers.parallel())
71+
.map(x -> {
72+
// without enabled Reactor instrumentation active span will be null
73+
assertNotNull(mockTracer.activeSpan());
74+
mockTracer.activeSpan().setTag("reactor", "reactor");
75+
return x * 2;
76+
}).take(1).single();
77+
}
78+
}
79+
80+
@Autowired
81+
private MockTracer mockTracer;
82+
83+
@Autowired
84+
private TestRestTemplate testRestTemplate;
85+
86+
@Before
87+
public void before() {
88+
mockTracer.reset();
89+
}
90+
91+
@Test
92+
public void testControllerTracing() throws Exception {
93+
ResponseEntity<String> responseEntity = testRestTemplate.getForEntity("/single", String.class);
94+
95+
// span is created in spring-web
96+
await().until(() -> mockTracer.finishedSpans().size() == 1);
97+
assertEquals(200, responseEntity.getStatusCode().value());
98+
List<MockSpan> spans = mockTracer.finishedSpans();
99+
assertEquals(1, spans.size());
100+
assertEquals("reactor", spans.get(0).tags().get("reactor"));
101+
}
102+
}

opentracing-spring-cloud-starter/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
<groupId>${project.groupId}</groupId>
6363
<artifactId>opentracing-spring-cloud-hystrix-starter</artifactId>
6464
</dependency>
65+
<dependency>
66+
<groupId>${project.groupId}</groupId>
67+
<artifactId>opentracing-spring-cloud-reactor-starter</artifactId>
68+
</dependency>
6569
<dependency>
6670
<groupId>${project.groupId}</groupId>
6771
<artifactId>opentracing-spring-cloud-rxjava-starter</artifactId>

pom.xml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<module>instrument-starters/opentracing-spring-cloud-websocket-starter</module>
3131
<module>instrument-starters/opentracing-spring-cloud-zuul-starter</module>
3232
<module>instrument-starters/opentracing-spring-cloud-hystrix-starter</module>
33+
<module>instrument-starters/opentracing-spring-cloud-reactor-starter</module>
3334
<module>instrument-starters/opentracing-spring-cloud-rxjava-starter</module>
3435
<module>instrument-starters/opentracing-spring-cloud-redis-starter</module>
3536
</modules>
@@ -72,13 +73,14 @@
7273

7374
<version.io.opentracing>0.31.0</version.io.opentracing>
7475
<version.io.opentracing.contrib-opentracing-spring-tracer-configuration-starter>0.1.0</version.io.opentracing.contrib-opentracing-spring-tracer-configuration-starter>
75-
<version.io.opentracing.contrib-opentracing-spring-web>0.3.4</version.io.opentracing.contrib-opentracing-spring-web>
76+
<version.io.opentracing.contrib-opentracing-spring-web>1.1.1</version.io.opentracing.contrib-opentracing-spring-web>
7677
<version.io.opentracing.contrib-opentracing-spring-jms>0.0.10</version.io.opentracing.contrib-opentracing-spring-jms>
7778
<version.io.opentracing.contrib-opentracing-spring-messaging>0.0.5</version.io.opentracing.contrib-opentracing-spring-messaging>
7879
<version.io.opentracing.contrib-opentracing-spring-rabbitmq>0.1.1</version.io.opentracing.contrib-opentracing-spring-rabbitmq>
7980
<version.io.opentracing.contrib-java-jdbc>0.0.12</version.io.opentracing.contrib-java-jdbc>
8081
<version.io.opentracing.contrib-opentracing-spring-redis>0.0.10</version.io.opentracing.contrib-opentracing-spring-redis>
81-
<version.io.opentracing.contrib-java-concurrent>0.1.0</version.io.opentracing.contrib-java-concurrent>
82+
<version.io.opentracing.contrib-java-concurrent>0.2.0</version.io.opentracing.contrib-java-concurrent>
83+
<version.io.opentracing.contrib-opentracing-reactor>0.0.2</version.io.opentracing.contrib-opentracing-reactor>
8284
<version.io.opentracing.contrib-opentracing-rxjava-1>0.0.9</version.io.opentracing.contrib-opentracing-rxjava-1>
8385
<version.io.opentracing.contrib-opentracing-spring-mongo>0.0.6</version.io.opentracing.contrib-opentracing-spring-mongo>
8486
<version.io.github.openfeign-feign-okhttp>9.5.0</version.io.github.openfeign-feign-okhttp>
@@ -91,6 +93,7 @@
9193
<version.de.flapdoodle-embed.mongo>2.0.3</version.de.flapdoodle-embed.mongo>
9294
<version.cz.jirutka.spring-embedmongo-spring>1.3.1</version.cz.jirutka.spring-embedmongo-spring>
9395
<version.org.slf4j-log4j-over-slf4j>1.7.25</version.org.slf4j-log4j-over-slf4j>
96+
<version.reactor-core>3.2.3.RELEASE</version.reactor-core>
9497

9598
<version.javax.jms>1.1-rev-1</version.javax.jms>
9699

@@ -140,6 +143,11 @@
140143
<artifactId>opentracing-spring-cloud-hystrix-starter</artifactId>
141144
<version>${project.version}</version>
142145
</dependency>
146+
<dependency>
147+
<groupId>${project.groupId}</groupId>
148+
<artifactId>opentracing-spring-cloud-reactor-starter</artifactId>
149+
<version>${project.version}</version>
150+
</dependency>
143151
<dependency>
144152
<groupId>${project.groupId}</groupId>
145153
<artifactId>opentracing-spring-cloud-rxjava-starter</artifactId>
@@ -380,6 +388,7 @@
380388
<exclude>**/ExecutorBeanPostProcessor.java</exclude>
381389
<exclude>**/TraceEnvironmentPostProcessor.java</exclude>
382390
<exclude>**/test/resources/application.yml</exclude>
391+
<exclude>**/ReactorTracingAutoConfiguration.java</exclude>
383392
</excludes>
384393
</configuration>
385394
<dependencies>

0 commit comments

Comments
 (0)