Skip to content

Commit 1f667e4

Browse files
committed
Tracing: added OpenTelemetry integration test.
The test verifies that span tree structure and status code are valid.
1 parent 05589b8 commit 1f667e4

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* Copyright (C) 2021 ScyllaDB
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+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.datastax.driver.opentelemetry;
17+
18+
import static org.testng.Assert.assertEquals;
19+
import static org.testng.Assert.assertTrue;
20+
21+
import com.datastax.driver.core.CCMTestsSupport;
22+
import com.datastax.driver.core.Session;
23+
import com.datastax.driver.core.tracing.NoopTracingInfoFactory;
24+
import com.datastax.driver.core.tracing.TracingInfoFactory;
25+
import io.opentelemetry.api.common.Attributes;
26+
import io.opentelemetry.api.trace.Span;
27+
import io.opentelemetry.api.trace.StatusCode;
28+
import io.opentelemetry.api.trace.Tracer;
29+
import io.opentelemetry.context.Context;
30+
import io.opentelemetry.context.Scope;
31+
import io.opentelemetry.sdk.OpenTelemetrySdk;
32+
import io.opentelemetry.sdk.resources.Resource;
33+
import io.opentelemetry.sdk.trace.ReadWriteSpan;
34+
import io.opentelemetry.sdk.trace.ReadableSpan;
35+
import io.opentelemetry.sdk.trace.SdkTracerProvider;
36+
import io.opentelemetry.sdk.trace.SpanProcessor;
37+
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
38+
import java.util.ArrayList;
39+
import java.util.Collection;
40+
import java.util.Collections;
41+
import java.util.List;
42+
import java.util.function.BiConsumer;
43+
import java.util.stream.Collectors;
44+
import org.testng.annotations.Test;
45+
46+
/** Tests for OpenTelemetry integration. */
47+
public class OpenTelemetryTest extends CCMTestsSupport {
48+
/** Collects and saves spans. */
49+
private static final class SpansCollector implements SpanProcessor {
50+
final Collection<ReadableSpan> startedSpans =
51+
Collections.synchronizedList(new ArrayList<ReadableSpan>());
52+
final Collection<ReadableSpan> spans =
53+
Collections.synchronizedList(new ArrayList<ReadableSpan>());
54+
55+
@Override
56+
public void onStart(Context parentContext, ReadWriteSpan span) {
57+
startedSpans.add(span);
58+
}
59+
60+
@Override
61+
public boolean isStartRequired() {
62+
return true;
63+
}
64+
65+
@Override
66+
public void onEnd(ReadableSpan span) {
67+
spans.add(span);
68+
}
69+
70+
@Override
71+
public boolean isEndRequired() {
72+
return true;
73+
}
74+
75+
public Collection<ReadableSpan> getSpans() {
76+
for (ReadableSpan span : startedSpans) {
77+
assertTrue(span.hasEnded());
78+
}
79+
80+
return spans;
81+
}
82+
}
83+
84+
private Session session;
85+
86+
/**
87+
* Prepare OpenTelemetry configuration and run test with it.
88+
*
89+
* @param test test to run.
90+
* @return collected spans.
91+
*/
92+
private Collection<ReadableSpan> collectSpans(BiConsumer<Tracer, TracingInfoFactory> test) {
93+
final Resource serviceNameResource =
94+
Resource.create(
95+
Attributes.of(ResourceAttributes.SERVICE_NAME, "Scylla Java driver - test"));
96+
97+
final SpansCollector collector = new SpansCollector();
98+
99+
final SdkTracerProvider tracerProvider =
100+
SdkTracerProvider.builder()
101+
.addSpanProcessor(collector)
102+
.setResource(Resource.getDefault().merge(serviceNameResource))
103+
.build();
104+
final OpenTelemetrySdk openTelemetry =
105+
OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).buildAndRegisterGlobal();
106+
107+
final Tracer tracer = openTelemetry.getTracerProvider().get("this");
108+
final OpenTelemetryTracingInfoFactory tracingInfoFactory =
109+
new OpenTelemetryTracingInfoFactory(tracer);
110+
cluster().setTracingInfoFactory(tracingInfoFactory);
111+
session = cluster().connect();
112+
113+
session.execute("USE " + keyspace);
114+
session.execute("CREATE TABLE t (k int PRIMARY KEY, v int)");
115+
collector.getSpans().clear();
116+
117+
test.accept(tracer, tracingInfoFactory);
118+
119+
tracerProvider.close();
120+
cluster().setTracingInfoFactory(new NoopTracingInfoFactory());
121+
122+
return collector.getSpans();
123+
}
124+
125+
/** Basic test for creating spans. */
126+
@Test(groups = "short")
127+
public void simpleTracingTest() {
128+
final Collection<ReadableSpan> spans =
129+
collectSpans(
130+
(tracer, tracingInfoFactory) -> {
131+
Span userSpan = tracer.spanBuilder("user span").startSpan();
132+
Scope scope = userSpan.makeCurrent();
133+
134+
session.execute("INSERT INTO t(k, v) VALUES (4, 2)");
135+
session.execute("INSERT INTO t(k, v) VALUES (2, 1)");
136+
137+
scope.close();
138+
userSpan.end();
139+
});
140+
141+
// Retrieve span created directly by tracer.
142+
final List<ReadableSpan> userSpans =
143+
spans.stream()
144+
.filter(span -> !span.getParentSpanContext().isValid())
145+
.collect(Collectors.toList());
146+
assertEquals(userSpans.size(), 1);
147+
final ReadableSpan userSpan = userSpans.get(0);
148+
149+
for (ReadableSpan span : spans) {
150+
assertTrue(span.getSpanContext().isValid());
151+
assertTrue(
152+
span.getSpanContext().equals(userSpan.getSpanContext())
153+
|| span.getParentSpanContext().isValid());
154+
}
155+
156+
// Retrieve spans representing requests.
157+
final Collection<ReadableSpan> rootSpans =
158+
spans.stream()
159+
.filter(span -> span.getParentSpanContext().equals(userSpan.getSpanContext()))
160+
.collect(Collectors.toList());
161+
assertEquals(rootSpans.size(), 2);
162+
163+
rootSpans.stream()
164+
.map(ReadableSpan::toSpanData)
165+
.forEach(
166+
spanData -> {
167+
assertEquals(spanData.getName(), "request");
168+
assertEquals(spanData.getStatus().getStatusCode(), StatusCode.OK);
169+
});
170+
}
171+
}

0 commit comments

Comments
 (0)