Skip to content

Commit

Permalink
Cleanups to OpenTelemetry tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraaga committed Mar 9, 2021
1 parent 3b88e11 commit 4b5f194
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,36 @@
import com.couchbase.client.test.ClusterAwareIntegrationTest;
import com.couchbase.client.test.Services;
import com.couchbase.client.test.TestNodeConfig;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Scope;
import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension;
import java.time.Duration;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.time.Duration;
import org.junit.jupiter.api.extension.RegisterExtension;

import static com.couchbase.client.java.ClusterOptions.clusterOptions;
import static com.couchbase.client.test.Util.waitUntilCondition;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;

class OpenTelemetryIntegrationTest extends ClusterAwareIntegrationTest {

private static ClusterEnvironment environment;
private static Cluster cluster;
private static Collection collection;
private static final InMemorySpanExporter exporter = InMemorySpanExporter.create();
private static SdkTracerProvider tracerProvider;

@RegisterExtension
static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();

@BeforeAll
static void beforeAll() {
tracerProvider = SdkTracerProvider.builder().addSpanProcessor(SimpleSpanProcessor.create(exporter)).build();

TestNodeConfig config = config().firstNodeWith(Services.KV).get();

environment = ClusterEnvironment
.builder()
.requestTracer(OpenTelemetryRequestTracer.wrap(tracerProvider.get("integrationTest")))
.requestTracer(OpenTelemetryRequestTracer.wrap(otelTesting.getOpenTelemetry()))
.build();

cluster = Cluster.connect(
Expand All @@ -72,11 +71,51 @@ static void beforeAll() {
static void afterAll() {
cluster.disconnect();
environment.shutdown();
tracerProvider.shutdown();
}

@Test
void capturesTraceSpans() {
Span parent = otelTesting.getOpenTelemetry().getTracer("integrationtest")
.spanBuilder("test")
.setSpanKind(SpanKind.SERVER)
.startSpan();
try (Scope ignored = parent.makeCurrent()) {
collection.get("myid");
} catch (DocumentNotFoundException ignored) {
// expected
} finally {
parent.end();
}

waitUntilCondition(() -> {
otelTesting.assertTraces()
.hasTracesSatisfyingExactly(
trace -> trace.hasSpansSatisfyingExactly(
span -> span
.hasName("test")
.hasKind(SpanKind.SERVER),
span -> span
.hasName("get")
.hasParentSpanId(parent.getSpanContext().getSpanId())
.hasKind(SpanKind.INTERNAL)
.hasAttributesSatisfying(attributes -> assertThat(attributes)
.containsEntry("db.system", "couchbase")
.containsEntry("db.operation", "get")
.containsEntry("db.couchbase.service", "kv")
.containsEntry("db.couchbase.collection", "_default")
.containsEntry("db.couchbase.scope", "_default")),
span -> span
.hasName("dispatch_to_server")
.hasKind(SpanKind.INTERNAL)
.hasAttributesSatisfying(attributes -> assertThat(attributes)
.containsEntry("db.system", "couchbase"))
));
return true;
});
}

@Test
void stressTest() {
int numRequests = 100;
for (int i = 0; i < 100; i++) {
try {
Expand All @@ -86,7 +125,10 @@ void capturesTraceSpans() {
}
}

waitUntilCondition(() -> exporter.getFinishedSpanItems().size() >= numRequests);
waitUntilCondition(() -> {
otelTesting.assertTraces().hasSizeGreaterThanOrEqualTo(numRequests);
return true;
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ public void addEvent(String name, Instant timestamp) {

@Override
public void end() {
try (Scope scope = span.makeCurrent()) {
span.end();
}
span.end();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.couchbase.client.core.cnc.RequestSpan;
import com.couchbase.client.core.cnc.RequestTracer;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.Tracer;
Expand All @@ -33,23 +34,23 @@
public class OpenTelemetryRequestTracer implements RequestTracer {

/**
* Holds the actual OT tracer.
* Holds the actual OTel tracer.
*/
private final Tracer tracer;

/**
* Wraps the OpenTelemetry tracer and returns a datatype that can be passed into the requestTracer method of the
* Wraps OpenTelemetry and returns a datatype that can be passed into the requestTracer method of the
* environment.
*
* @param tracer the tracer to wrap.
* @return the wrapped tracer ready to be passed in.
* @param openTelemetry the OpenTelemetry instance to wrap.
* @return the wrapped OpenTelemetry ready to be passed in.
*/
public static OpenTelemetryRequestTracer wrap(final Tracer tracer) {
return new OpenTelemetryRequestTracer(tracer);
public static OpenTelemetryRequestTracer wrap(final OpenTelemetry openTelemetry) {
return new OpenTelemetryRequestTracer(openTelemetry);
}

private OpenTelemetryRequestTracer(Tracer tracer) {
this.tracer = tracer;
private OpenTelemetryRequestTracer(OpenTelemetry openTelemetry) {
this.tracer = openTelemetry.getTracer("com.couchbase.client");
}

private Span castSpan(final RequestSpan requestSpan) {
Expand All @@ -68,19 +69,17 @@ private Span castSpan(final RequestSpan requestSpan) {
* Returns the inner OpenTelemetry tracer.
*/
public Tracer tracer() {
return tracer;
return tracer;
}

@Override
public RequestSpan requestSpan(String operationName, RequestSpan parent) {
SpanBuilder spanBuilder = tracer.spanBuilder(operationName);
Context parentContext = Context.current();
if (parent != null) {
spanBuilder.setParent(Context.current().with(castSpan(parent)));
} else {
spanBuilder.setNoParent();
parentContext = parentContext.with(castSpan(parent));
}
Span span = spanBuilder.startSpan();
span.makeCurrent().close();
Span span = spanBuilder.setParent(parentContext).startSpan();
return OpenTelemetryRequestSpan.wrap(span);
}

Expand Down

0 comments on commit 4b5f194

Please sign in to comment.