Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions instrumentation/lettuce/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Settings for the Lettuce instrumentation

| System property | Type | Default | Description |
|-------------------------------------------------------------|---------|---------|-----------------------------------------------------|
| `otel.instrumentation.lettuce.experimental-span-attributes` | Boolean | `false` | Enable the capture of experimental span attributes. |
| `otel.instrumentation.lettuce.connection-telemetry.enabled` | Boolean | `false` | Enable the creation of Connect spans. |
| System property | Type | Default | Description |
|-----------------------------------------------------------------------------|---------|---------|--------------------------------------------------------|
| `otel.instrumentation.lettuce.experimental-span-attributes` | Boolean | `false` | Enable the capture of experimental span attributes. |
| `otel.instrumentation.lettuce.connection-telemetry.enabled` | Boolean | `false` | Enable the creation of Connect spans. |
| `otel.instrumentation.lettuce.experimental.command-encoding-events.enabled` | Boolean | `false` | Enable the capture of command encoding as span events. |
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ dependencies {

tasks {
withType<Test>().configureEach {
// TODO run tests both with and without experimental span attributes
// TODO run tests both with and without experimental span attributes and span events
jvmArgs("-Dotel.instrumentation.lettuce.experimental-span-attributes=true")
jvmArgs("-Dotel.instrumentation.lettuce.connection-telemetry.enabled=true")
jvmArgs("-Dotel.instrumentation.lettuce.experimental.command-encoding-events.enabled=true")
usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ dependencies {

tasks {
withType<Test>().configureEach {
// TODO run tests both with and without experimental span attributes
// TODO run tests both with and without experimental span attributes and span events
jvmArgs("-Dotel.instrumentation.lettuce.experimental-span-attributes=true")
jvmArgs("-Dotel.instrumentation.lettuce.connection-telemetry.enabled=true")
jvmArgs("-Dotel.instrumentation.lettuce.experimental.command-encoding-events.enabled=true")
usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.lettuce.v5_1.LettuceTelemetry;
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig;

public final class TracingHolder {

private static final boolean CAPTURE_COMMAND_ENCODING_EVENTS =
AgentInstrumentationConfig.get()
.getBoolean(
"otel.instrumentation.lettuce.experimental.command-encoding-events.enabled", false);

public static final Tracing TRACING =
LettuceTelemetry.builder(GlobalOpenTelemetry.get())
.setStatementSanitizationEnabled(AgentCommonConfig.get().isStatementSanitizationEnabled())
.setEncodingSpanEventsEnabled(CAPTURE_COMMAND_ENCODING_EVENTS)
.build()
.newTracing();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,37 +53,35 @@ void testAsyncSubscriberWithSpecificThreadPool() {
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("test-parent").hasAttributes(Attributes.empty()),
span ->
span.hasName("SET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
addExtraAttributes(
equalTo(NETWORK_TYPE, "ipv4"),
equalTo(NETWORK_PEER_ADDRESS, ip),
equalTo(NETWORK_PEER_PORT, port),
equalTo(SERVER_ADDRESS, host),
equalTo(SERVER_PORT, port),
equalTo(maybeStable(DB_SYSTEM), "redis"),
equalTo(maybeStable(DB_STATEMENT), "SET a ?")))
.hasEventsSatisfyingExactly(
event -> event.hasName("redis.encode.start"),
event -> event.hasName("redis.encode.end")),
span ->
span.hasName("GET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
addExtraAttributes(
equalTo(NETWORK_TYPE, "ipv4"),
equalTo(NETWORK_PEER_ADDRESS, ip),
equalTo(NETWORK_PEER_PORT, port),
equalTo(SERVER_ADDRESS, host),
equalTo(SERVER_PORT, port),
equalTo(maybeStable(DB_SYSTEM), "redis"),
equalTo(maybeStable(DB_STATEMENT), "GET a")))
.hasEventsSatisfyingExactly(
event -> event.hasName("redis.encode.start"),
event -> event.hasName("redis.encode.end"))));
span -> {
span.hasName("SET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
addExtraAttributes(
equalTo(NETWORK_TYPE, "ipv4"),
equalTo(NETWORK_PEER_ADDRESS, ip),
equalTo(NETWORK_PEER_PORT, port),
equalTo(SERVER_ADDRESS, host),
equalTo(SERVER_PORT, port),
equalTo(maybeStable(DB_SYSTEM), "redis"),
equalTo(maybeStable(DB_STATEMENT), "SET a ?")));
assertCommandEncodeEvents(span);
},
span -> {
span.hasName("GET")
.hasKind(SpanKind.CLIENT)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
addExtraAttributes(
equalTo(NETWORK_TYPE, "ipv4"),
equalTo(NETWORK_PEER_ADDRESS, ip),
equalTo(NETWORK_PEER_PORT, port),
equalTo(SERVER_ADDRESS, host),
equalTo(SERVER_PORT, port),
equalTo(maybeStable(DB_SYSTEM), "redis"),
equalTo(maybeStable(DB_STATEMENT), "GET a")));
assertCommandEncodeEvents(span);
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ public static LettuceTelemetryBuilder builder(OpenTelemetry openTelemetry) {
private final Tracer tracer;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;
private final boolean encodingEventsEnabled;

LettuceTelemetry(
OpenTelemetry openTelemetry,
boolean statementSanitizationEnabled,
boolean encodingEventsEnabled,
OperationListener metrics) {
this.metrics = metrics;
TracerBuilder tracerBuilder = openTelemetry.tracerBuilder(INSTRUMENTATION_NAME);
Expand All @@ -46,13 +48,14 @@ public static LettuceTelemetryBuilder builder(OpenTelemetry openTelemetry) {
}
tracer = tracerBuilder.build();
sanitizer = RedisCommandSanitizer.create(statementSanitizationEnabled);
this.encodingEventsEnabled = encodingEventsEnabled;
}

/**
* Returns a new {@link Tracing} which can be used with methods like {@link
* io.lettuce.core.resource.ClientResources.Builder#tracing(Tracing)}.
*/
public Tracing newTracing() {
return new OpenTelemetryTracing(tracer, sanitizer, metrics);
return new OpenTelemetryTracing(tracer, sanitizer, metrics, encodingEventsEnabled);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public final class LettuceTelemetryBuilder {

private boolean statementSanitizationEnabled = true;

private boolean encodingEventsEnabled = true;

LettuceTelemetryBuilder(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
}
Expand All @@ -34,6 +36,16 @@ public LettuceTelemetryBuilder setStatementSanitizationEnabled(
return this;
}

/**
* Sets whether the {@code redis.encode.start} and {@code redis.encode.end} span events should be
* emitted by the constructed {@link LettuceTelemetry}. Enabled by default.
*/
@CanIgnoreReturnValue
public LettuceTelemetryBuilder setEncodingSpanEventsEnabled(boolean encodingEventsEnabled) {
this.encodingEventsEnabled = encodingEventsEnabled;
return this;
}

/**
* Returns a new {@link LettuceTelemetry} with the settings of this {@link
* LettuceTelemetryBuilder}.
Expand All @@ -42,6 +54,7 @@ public LettuceTelemetry build() {
return new LettuceTelemetry(
openTelemetry,
statementSanitizationEnabled,
encodingEventsEnabled,
DbClientMetrics.get().create(openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ final class OpenTelemetryTracing implements Tracing {
OpenTelemetryTracing(
io.opentelemetry.api.trace.Tracer tracer,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
this.tracerProvider = new OpenTelemetryTracerProvider(tracer, sanitizer, metrics);
OperationListener metrics,
boolean encodingEventsEnabled) {
this.tracerProvider =
new OpenTelemetryTracerProvider(tracer, sanitizer, metrics, encodingEventsEnabled);
}

@Override
Expand Down Expand Up @@ -100,8 +102,10 @@ private static class OpenTelemetryTracerProvider implements TracerProvider {
OpenTelemetryTracerProvider(
io.opentelemetry.api.trace.Tracer tracer,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
openTelemetryTracer = new OpenTelemetryTracer(tracer, sanitizer, metrics);
OperationListener metrics,
boolean encodingEventsEnabled) {
openTelemetryTracer =
new OpenTelemetryTracer(tracer, sanitizer, metrics, encodingEventsEnabled);
}

@Override
Expand Down Expand Up @@ -143,14 +147,17 @@ private static class OpenTelemetryTracer extends Tracer {
private final io.opentelemetry.api.trace.Tracer tracer;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;
private final boolean encodingEventsEnabled;

OpenTelemetryTracer(
io.opentelemetry.api.trace.Tracer tracer,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
OperationListener metrics,
boolean encodingEventsEnabled) {
this.tracer = tracer;
this.sanitizer = sanitizer;
this.metrics = metrics;
this.encodingEventsEnabled = encodingEventsEnabled;
}

@Override
Expand Down Expand Up @@ -179,7 +186,7 @@ private OpenTelemetrySpan nextSpan(Context context) {
if (SemconvStability.emitOldDatabaseSemconv()) {
spanBuilder.setAttribute(DB_SYSTEM, REDIS);
}
return new OpenTelemetrySpan(context, spanBuilder, sanitizer, metrics);
return new OpenTelemetrySpan(context, spanBuilder, sanitizer, metrics, encodingEventsEnabled);
}
}

Expand All @@ -193,6 +200,7 @@ private static class OpenTelemetrySpan extends Tracer.Span {
private final SpanBuilder spanBuilder;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;
private final boolean encodingEventsEnabled;

@Nullable private String name;
@Nullable private List<Object> events;
Expand All @@ -207,12 +215,14 @@ private static class OpenTelemetrySpan extends Tracer.Span {
Context context,
SpanBuilder spanBuilder,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
OperationListener metrics,
boolean encodingEventsEnabled) {
this.context = context;
this.spanBuilder = spanBuilder;
this.sanitizer = sanitizer;
this.metrics = metrics;
this.attributesBuilder = Attributes.builder();
this.encodingEventsEnabled = encodingEventsEnabled;
if (SemconvStability.emitStableDatabaseSemconv()) {
attributesBuilder.put(DB_SYSTEM_NAME, REDIS);
}
Expand Down Expand Up @@ -326,6 +336,11 @@ public synchronized Tracer.Span start() {
@Override
@CanIgnoreReturnValue
public synchronized Tracer.Span annotate(String value) {
if (!encodingEventsEnabled && value.startsWith("redis.encode.")) {
// skip noisy encode events produced by io.lettuce.core.protocol.TracedCommand
return this;
}

if (span != null) {
span.addEvent(value);
} else {
Expand Down
Loading