Skip to content

Commit c782f7b

Browse files
committed
Couchbase 3.4
1 parent 83846d4 commit c782f7b

File tree

9 files changed

+261
-2
lines changed

9 files changed

+261
-2
lines changed

instrumentation/couchbase/couchbase-3.2/javaagent/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ muzzle {
66
pass {
77
group.set("com.couchbase.client")
88
module.set("java-client")
9-
versions.set("[3.2.0,)")
9+
versions.set("[3.2.0,3.4.0)")
1010
// these versions were released as ".bundle" instead of ".jar"
1111
skip("2.7.5", "2.7.8")
1212
assertInverse.set(true)

instrumentation/couchbase/couchbase-3.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v3_2/CouchbaseInstrumentationModule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package io.opentelemetry.javaagent.instrumentation.couchbase.v3_2;
77

88
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
9+
import static net.bytebuddy.matcher.ElementMatchers.not;
910

1011
import com.google.auto.service.AutoService;
1112
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
@@ -25,7 +26,9 @@ public CouchbaseInstrumentationModule() {
2526
@Override
2627
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
2728
// New class introduced in 3.2.
28-
return hasClassesNamed("com.couchbase.client.core.cnc.RequestSpan$StatusCode");
29+
// ConfigurationProfile was introduced in 3.4.
30+
return hasClassesNamed("com.couchbase.client.core.cnc.RequestSpan$StatusCode")
31+
.and(not(hasClassesNamed("com.couchbase.client.core.env.ConfigurationProfile")));
2932
}
3033

3134
@Override
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
plugins {
2+
id("otel.javaagent-instrumentation")
3+
}
4+
5+
muzzle {
6+
pass {
7+
group.set("com.couchbase.client")
8+
module.set("java-client")
9+
versions.set("[3.4.0,)")
10+
// these versions were released as ".bundle" instead of ".jar"
11+
skip("2.7.5", "2.7.8")
12+
assertInverse.set(true)
13+
}
14+
}
15+
16+
sourceSets {
17+
main {
18+
val shadedDep = project(":instrumentation:couchbase:couchbase-3.4:tracing-opentelemetry-shaded")
19+
output.dir(
20+
shadedDep.file("build/extracted/shadow"),
21+
"builtBy" to ":instrumentation:couchbase:couchbase-3.4:tracing-opentelemetry-shaded:extractShadowJar",
22+
)
23+
}
24+
}
25+
26+
dependencies {
27+
compileOnly(
28+
project(
29+
path = ":instrumentation:couchbase:couchbase-3.4:tracing-opentelemetry-shaded",
30+
configuration = "shadow",
31+
),
32+
)
33+
34+
library("com.couchbase.client:java-client:3.4.0")
35+
36+
testImplementation("org.testcontainers:couchbase")
37+
}
38+
39+
tasks {
40+
withType<Test>().configureEach {
41+
systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean)
42+
usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service)
43+
}
44+
45+
val testStableSemconv by registering(Test::class) {
46+
testClassesDirs = sourceSets.test.get().output.classesDirs
47+
classpath = sourceSets.test.get().runtimeClasspath
48+
49+
jvmArgs("-Dotel.semconv-stability.opt-in=database")
50+
}
51+
52+
check {
53+
dependsOn(testStableSemconv)
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.couchbase.v3_4;
7+
8+
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
9+
import static net.bytebuddy.matcher.ElementMatchers.named;
10+
11+
import com.couchbase.client.core.env.CoreEnvironment;
12+
import io.opentelemetry.api.GlobalOpenTelemetry;
13+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
14+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
15+
import io.opentelemetry.javaagent.instrumentation.couchbase.v3_4.shaded.com.couchbase.client.tracing.opentelemetry.OpenTelemetryRequestTracer;
16+
import net.bytebuddy.asm.Advice;
17+
import net.bytebuddy.description.type.TypeDescription;
18+
import net.bytebuddy.matcher.ElementMatcher;
19+
20+
public class CouchbaseEnvironmentInstrumentation implements TypeInstrumentation {
21+
22+
@Override
23+
public ElementMatcher<TypeDescription> typeMatcher() {
24+
return named("com.couchbase.client.core.env.CoreEnvironment$Builder");
25+
}
26+
27+
@Override
28+
public void transform(TypeTransformer transformer) {
29+
transformer.applyAdviceToMethod(
30+
isConstructor(),
31+
CouchbaseEnvironmentInstrumentation.class.getName() + "$ConstructorAdvice");
32+
}
33+
34+
@SuppressWarnings("unused")
35+
public static class ConstructorAdvice {
36+
37+
@Advice.OnMethodExit(suppress = Throwable.class)
38+
public static void onExit(@Advice.This CoreEnvironment.Builder<?> builder) {
39+
builder.requestTracer(OpenTelemetryRequestTracer.wrap(GlobalOpenTelemetry.get()));
40+
}
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.couchbase.v3_4;
7+
8+
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
9+
10+
import com.google.auto.service.AutoService;
11+
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
12+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
14+
import java.util.Collections;
15+
import java.util.List;
16+
import net.bytebuddy.matcher.ElementMatcher;
17+
18+
@AutoService(InstrumentationModule.class)
19+
public class CouchbaseInstrumentationModule extends InstrumentationModule
20+
implements ExperimentalInstrumentationModule {
21+
public CouchbaseInstrumentationModule() {
22+
super("couchbase", "couchbase-3.4");
23+
}
24+
25+
@Override
26+
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
27+
// ConfigurationProfile was introduced in 3.4
28+
return hasClassesNamed("com.couchbase.client.core.env.ConfigurationProfile");
29+
}
30+
31+
@Override
32+
public List<TypeInstrumentation> typeInstrumentations() {
33+
return Collections.singletonList(new CouchbaseEnvironmentInstrumentation());
34+
}
35+
36+
@Override
37+
public boolean isIndyReady() {
38+
return true;
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.couchbase.v3_4;
7+
8+
import static io.opentelemetry.api.trace.SpanKind.CLIENT;
9+
10+
import com.couchbase.client.core.error.DocumentNotFoundException;
11+
import com.couchbase.client.java.Bucket;
12+
import com.couchbase.client.java.Cluster;
13+
import com.couchbase.client.java.Collection;
14+
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
15+
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
16+
import io.opentelemetry.sdk.trace.data.StatusData;
17+
import java.time.Duration;
18+
import org.junit.jupiter.api.AfterAll;
19+
import org.junit.jupiter.api.BeforeAll;
20+
import org.junit.jupiter.api.Test;
21+
import org.junit.jupiter.api.extension.RegisterExtension;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
import org.testcontainers.containers.output.Slf4jLogConsumer;
25+
import org.testcontainers.couchbase.BucketDefinition;
26+
import org.testcontainers.couchbase.CouchbaseContainer;
27+
import org.testcontainers.couchbase.CouchbaseService;
28+
29+
// Couchbase instrumentation is owned upstream so we don't assert on the contents of the spans, only
30+
// that the instrumentation is properly registered by the agent, meaning some spans were generated.
31+
class CouchbaseClient34Test {
32+
@RegisterExtension
33+
private static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
34+
35+
private static final Logger logger = LoggerFactory.getLogger("couchbase-container");
36+
37+
static CouchbaseContainer couchbase;
38+
static Cluster cluster;
39+
static Collection collection;
40+
41+
@BeforeAll
42+
static void setup() {
43+
couchbase =
44+
new CouchbaseContainer("couchbase/server:6.5.1")
45+
.withExposedPorts(8091)
46+
.withEnabledServices(CouchbaseService.KV)
47+
.withBucket(new BucketDefinition("test"))
48+
.withLogConsumer(new Slf4jLogConsumer(logger))
49+
.withStartupTimeout(Duration.ofMinutes(2));
50+
couchbase.start();
51+
52+
cluster =
53+
Cluster.connect(
54+
couchbase.getConnectionString(), couchbase.getUsername(), couchbase.getPassword());
55+
Bucket bucket = cluster.bucket("test");
56+
collection = bucket.defaultCollection();
57+
bucket.waitUntilReady(Duration.ofSeconds(30));
58+
}
59+
60+
@AfterAll
61+
static void cleanup() {
62+
cluster.disconnect();
63+
couchbase.stop();
64+
}
65+
66+
@Test
67+
void testEmitsSpans() {
68+
try {
69+
collection.get("id");
70+
} catch (DocumentNotFoundException e) {
71+
// Expected
72+
}
73+
74+
testing.waitAndAssertTracesWithoutScopeVersionVerification(
75+
trace ->
76+
trace.hasSpansSatisfyingExactly(
77+
span -> {
78+
span.hasKind(CLIENT)
79+
.hasName("get")
80+
.hasStatus(StatusData.error());
81+
},
82+
span -> span.hasName("dispatch_to_server")));
83+
}
84+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
description: >
2+
Couchbase instrumentation is owned by the Couchbase project for versions 3+. This instrumentation
3+
automatically configures the instrumentation provided by the Couchbase library.
4+
library_link: https://github.com/couchbase/couchbase-java-client
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
plugins {
2+
id("com.gradleup.shadow")
3+
id("otel.java-conventions")
4+
}
5+
6+
group = "io.opentelemetry.javaagent.instrumentation"
7+
8+
dependencies {
9+
implementation("com.couchbase.client:tracing-opentelemetry:1.2.0")
10+
}
11+
12+
tasks {
13+
shadowJar {
14+
dependencies {
15+
// including only tracing-opentelemetry excludes its transitive dependencies
16+
include(dependency("com.couchbase.client:tracing-opentelemetry"))
17+
}
18+
relocate(
19+
"com.couchbase.client.tracing.opentelemetry",
20+
"io.opentelemetry.javaagent.instrumentation.couchbase.v3_4.shaded.com.couchbase.client.tracing.opentelemetry"
21+
)
22+
}
23+
24+
val extractShadowJar by registering(Copy::class) {
25+
dependsOn(shadowJar)
26+
from(zipTree(shadowJar.get().archiveFile))
27+
into("build/extracted/shadow")
28+
}
29+
}

settings.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ include(":instrumentation:couchbase:couchbase-3.1.6:javaagent")
204204
include(":instrumentation:couchbase:couchbase-3.1.6:tracing-opentelemetry-shaded")
205205
include(":instrumentation:couchbase:couchbase-3.2:javaagent")
206206
include(":instrumentation:couchbase:couchbase-3.2:tracing-opentelemetry-shaded")
207+
include(":instrumentation:couchbase:couchbase-3.4:javaagent")
208+
include(":instrumentation:couchbase:couchbase-3.4:tracing-opentelemetry-shaded")
207209
include(":instrumentation:couchbase:couchbase-common:testing")
208210
include(":instrumentation:dropwizard:dropwizard-metrics-4.0:javaagent")
209211
include(":instrumentation:dropwizard:dropwizard-testing")

0 commit comments

Comments
 (0)