Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -383,13 +382,10 @@ public void testBasicStatement(
assertDurationMetric(
testing,
"io.opentelemetry.jdbc",
DB_SYSTEM,
DB_COLLECTION_NAME,
DB_NAMESPACE,
DB_OPERATION_NAME);
asList(DB_SYSTEM, DB_COLLECTION_NAME, DB_NAMESPACE, DB_OPERATION_NAME));
} else {
assertDurationMetric(
testing, "io.opentelemetry.jdbc", DB_SYSTEM, DB_OPERATION_NAME, DB_NAMESPACE);
testing, "io.opentelemetry.jdbc", asList(DB_SYSTEM, DB_OPERATION_NAME, DB_NAMESPACE));
}
}

Expand Down Expand Up @@ -980,7 +976,7 @@ void testGetConnection(
trace -> {
List<Consumer<SpanDataAssert>> assertions =
new ArrayList<>(
Arrays.asList(
asList(
span1 -> span1.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
span1 ->
span1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand Down Expand Up @@ -54,11 +55,7 @@ void buildWithDefaults() throws SQLException {
assertDurationMetric(
testing,
"io.opentelemetry.jdbc",
DB_NAMESPACE,
DB_OPERATION_NAME,
DB_SYSTEM,
SERVER_ADDRESS,
SERVER_PORT);
Arrays.asList(DB_NAMESPACE, DB_OPERATION_NAME, DB_SYSTEM, SERVER_ADDRESS, SERVER_PORT));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import org.assertj.core.api.AbstractLongAssert;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
Expand Down Expand Up @@ -94,12 +95,13 @@ void setCommand() {
assertDurationMetric(
testing,
"io.opentelemetry.jedis-3.0",
DB_OPERATION_NAME,
DB_SYSTEM,
SERVER_ADDRESS,
SERVER_PORT,
NETWORK_PEER_ADDRESS,
NETWORK_PEER_PORT);
Arrays.asList(
DB_OPERATION_NAME,
DB_SYSTEM,
SERVER_ADDRESS,
SERVER_PORT,
NETWORK_PEER_ADDRESS,
NETWORK_PEER_PORT));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.TracerBuilder;
import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer;
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;

/** Entrypoint for instrumenting Lettuce or clients. */
Expand All @@ -31,8 +32,13 @@ public static LettuceTelemetryBuilder builder(OpenTelemetry openTelemetry) {

private final Tracer tracer;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;

LettuceTelemetry(OpenTelemetry openTelemetry, boolean statementSanitizationEnabled) {
LettuceTelemetry(
OpenTelemetry openTelemetry,
boolean statementSanitizationEnabled,
OperationListener metrics) {
this.metrics = metrics;
TracerBuilder tracerBuilder = openTelemetry.tracerBuilder(INSTRUMENTATION_NAME);
String version = EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
if (version != null) {
Expand All @@ -47,6 +53,6 @@ public static LettuceTelemetryBuilder builder(OpenTelemetry openTelemetry) {
* io.lettuce.core.resource.ClientResources.Builder#tracing(Tracing)}.
*/
public Tracing newTracing() {
return new OpenTelemetryTracing(tracer, sanitizer);
return new OpenTelemetryTracing(tracer, sanitizer, metrics);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@

package io.opentelemetry.instrumentation.lettuce.v5_1;

import static io.opentelemetry.instrumentation.lettuce.v5_1.LettuceTelemetry.INSTRUMENTATION_NAME;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;

/** A builder of {@link LettuceTelemetry}. */
public final class LettuceTelemetryBuilder {

private final OpenTelemetry openTelemetry;

private boolean statementSanitizationEnabled = true;
private OperationMetrics metrics;

LettuceTelemetryBuilder(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
metrics = DbClientMetrics.get();
}

/**
Expand All @@ -31,11 +37,20 @@ public LettuceTelemetryBuilder setStatementSanitizationEnabled(
return this;
}

@CanIgnoreReturnValue
public LettuceTelemetryBuilder setMetrics(OperationMetrics metrics) {
this.metrics = metrics;
return this;
}

/**
* Returns a new {@link LettuceTelemetry} with the settings of this {@link
* LettuceTelemetryBuilder}.
*/
public LettuceTelemetry build() {
return new LettuceTelemetry(openTelemetry, statementSanitizationEnabled);
return new LettuceTelemetry(
openTelemetry,
statementSanitizationEnabled,
metrics.create(openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener;
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor;
import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor;
Expand Down Expand Up @@ -54,8 +55,11 @@ final class OpenTelemetryTracing implements Tracing {
NetworkAttributesExtractor.create(new LettuceServerAttributesGetter());
private final TracerProvider tracerProvider;

OpenTelemetryTracing(io.opentelemetry.api.trace.Tracer tracer, RedisCommandSanitizer sanitizer) {
this.tracerProvider = new OpenTelemetryTracerProvider(tracer, sanitizer);
OpenTelemetryTracing(
io.opentelemetry.api.trace.Tracer tracer,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
this.tracerProvider = new OpenTelemetryTracerProvider(tracer, sanitizer, metrics);
}

@Override
Expand Down Expand Up @@ -93,8 +97,10 @@ private static class OpenTelemetryTracerProvider implements TracerProvider {
private final Tracer openTelemetryTracer;

OpenTelemetryTracerProvider(
io.opentelemetry.api.trace.Tracer tracer, RedisCommandSanitizer sanitizer) {
openTelemetryTracer = new OpenTelemetryTracer(tracer, sanitizer);
io.opentelemetry.api.trace.Tracer tracer,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
openTelemetryTracer = new OpenTelemetryTracer(tracer, sanitizer, metrics);
}

@Override
Expand Down Expand Up @@ -135,10 +141,15 @@ private static class OpenTelemetryTracer extends Tracer {

private final io.opentelemetry.api.trace.Tracer tracer;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;

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

@Override
Expand All @@ -165,7 +176,7 @@ private OpenTelemetrySpan nextSpan(Context context) {
.setSpanKind(SpanKind.CLIENT)
.setParent(context)
.setAttribute(DB_SYSTEM, REDIS);
return new OpenTelemetrySpan(context, spanBuilder, sanitizer);
return new OpenTelemetrySpan(context, spanBuilder, sanitizer, metrics);
}
}

Expand All @@ -178,18 +189,26 @@ private static class OpenTelemetrySpan extends Tracer.Span {
private final Context context;
private final SpanBuilder spanBuilder;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;

@Nullable private String name;
@Nullable private List<Object> events;
@Nullable private Throwable error;
@Nullable private Span span;
private long spanStartTime;
private final AttributesBuilder attributesBuilder = Attributes.builder().put(DB_SYSTEM, REDIS);
@Nullable private List<String> argsList;
@Nullable private String argsString;

OpenTelemetrySpan(Context context, SpanBuilder spanBuilder, RedisCommandSanitizer sanitizer) {
OpenTelemetrySpan(
Context context,
SpanBuilder spanBuilder,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
this.context = context;
this.spanBuilder = spanBuilder;
this.sanitizer = sanitizer;
this.metrics = metrics;
}

@Override
Expand Down Expand Up @@ -218,11 +237,13 @@ private void fillEndpoint(OpenTelemetryEndpoint endpoint) {
Context currentContext = span == null ? context : context.with(span);
serverAttributesExtractor.onStart(attributesBuilder, currentContext, endpoint);
networkAttributesExtractor.onEnd(attributesBuilder, currentContext, endpoint, null, null);
Attributes attributes = attributesBuilder.build();
if (span != null) {
span.setAllAttributes(attributesBuilder.build());
span.setAllAttributes(attributes);
} else {
spanBuilder.setAllAttributes(attributesBuilder.build());
spanBuilder.setAllAttributes(attributes);
}
this.attributesBuilder.putAll(attributes);
}

// Added and called in 6.0+
Expand All @@ -231,6 +252,7 @@ private void fillEndpoint(OpenTelemetryEndpoint endpoint) {
@SuppressWarnings("UnusedMethod")
public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
start();
long startTime = System.nanoTime();

Span span = this.span;
if (span == null) {
Expand Down Expand Up @@ -258,7 +280,7 @@ public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
}
}

finish(span);
finish(span, startTime);
});
}

Expand All @@ -270,6 +292,7 @@ public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
@CanIgnoreReturnValue
public synchronized Tracer.Span start() {
span = spanBuilder.startSpan();
spanStartTime = System.nanoTime();
if (name != null) {
span.updateName(name);
}
Expand Down Expand Up @@ -330,6 +353,7 @@ public synchronized Tracer.Span tag(String key, String value) {
} else {
spanBuilder.setAttribute(key, value);
}
attributesBuilder.put(key, value);
return this;
}

Expand All @@ -347,16 +371,20 @@ public synchronized Tracer.Span error(Throwable throwable) {
@Override
public synchronized void finish() {
if (span != null) {
finish(span);
finish(span, spanStartTime);
}
}

private void finish(Span span) {
private void finish(Span span, long startTime) {
if (name != null) {
String statement =
sanitizer.sanitize(name, argsList != null ? argsList : splitArgs(argsString));
if (SemconvStability.emitStableDatabaseSemconv()) {
span.setAttribute(DB_QUERY_TEXT, statement);
metrics.onEnd(
metrics.onStart(Context.current(), Attributes.empty(), startTime),
attributesBuilder.build(),
System.nanoTime());
}
if (SemconvStability.emitOldDatabaseSemconv()) {
span.setAttribute(DB_STATEMENT, statement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package io.opentelemetry.instrumentation.lettuce.v5_1;

import static io.opentelemetry.instrumentation.testing.junit.db.DbClientMetricsTestUtil.assertDurationMetric;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
Expand All @@ -13,6 +14,7 @@
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_TYPE;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAMESPACE;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static java.nio.charset.StandardCharsets.UTF_8;
Expand All @@ -31,7 +33,10 @@
import io.opentelemetry.instrumentation.test.utils.PortUtils;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
Expand Down Expand Up @@ -135,6 +140,15 @@ void testSetCommand() {
.hasEventsSatisfyingExactly(
event -> event.hasName("redis.encode.start"),
event -> event.hasName("redis.encode.end"))));

List<AttributeKey<?>> expected =
new ArrayList<>(
Arrays.asList(
DB_SYSTEM, SERVER_ADDRESS, SERVER_PORT, NETWORK_PEER_ADDRESS, NETWORK_PEER_PORT));
if (Boolean.getBoolean("testLatestDeps")) {
expected.add(DB_NAMESPACE);
}
assertDurationMetric(testing(), "io.opentelemetry.lettuce-5.1", expected);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import java.util.List;

public class DbClientMetricsTestUtil {

Expand All @@ -18,7 +19,10 @@ private DbClientMetricsTestUtil() {}
public static void assertDurationMetric(
InstrumentationExtension testing,
String instrumentationName,
AttributeKey<?>... expectedKeys) {
List<AttributeKey<?>> expectedKeys) {
// db.system is required - see
// https://opentelemetry.io/docs/specs/semconv/database/database-metrics/#metric-dbclientoperationduration
assertThat(expectedKeys).extracting(AttributeKey::getKey).contains("db.system");
if (!emitStableDatabaseSemconv()) {
return;
}
Expand Down
Loading