Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ public void end(
public static AdviceScope onEnter(@Advice.Argument(0) RedisCommand<?, ?, ?> command) {

Context parentContext = currentContext();
if (!instrumenter().shouldStart(parentContext, command)) {
return null;
}

Context context = instrumenter().start(parentContext, command);
// remember the context that called dispatch, it is used in LettuceAsyncCommandInstrumentation
context = context.with(LettuceSingletons.COMMAND_CONTEXT_KEY, parentContext);
Expand All @@ -75,7 +79,9 @@ public static void onExit(
@Advice.Thrown Throwable throwable,
@Advice.Return AsyncCommand<?, ?, ?> asyncCommand,
@Advice.Enter AdviceScope adviceScope) {
adviceScope.end(throwable, command, asyncCommand);
if (adviceScope != null) {
adviceScope.end(throwable, command, asyncCommand);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ public void end(Throwable throwable, RedisURI redisUri) {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static AdviceScope onEnter(@Advice.Argument(1) RedisURI redisUri) {
Context context = connectInstrumenter().start(currentContext(), redisUri);
Context parentContext = currentContext();
if (!connectInstrumenter().shouldStart(parentContext, redisUri)) {
return null;
}

Context context = connectInstrumenter().start(parentContext, redisUri);
return new AdviceScope(context, context.makeCurrent());
}

Expand All @@ -63,7 +68,9 @@ public static void onExit(
@Advice.Argument(1) RedisURI redisUri,
@Advice.Thrown @Nullable Throwable throwable,
@Advice.Enter AdviceScope adviceScope) {
adviceScope.end(throwable, redisUri);
if (adviceScope != null) {
adviceScope.end(throwable, redisUri);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ public void end(
public static AdviceScope onEnter(@Advice.Argument(0) RedisCommand<?, ?, ?> command) {

Context parentContext = currentContext();
if (!instrumenter().shouldStart(parentContext, command)) {
return null;
}

Context context = instrumenter().start(parentContext, command);
// remember the context that called dispatch, it is used in LettuceAsyncCommandInstrumentation
context = context.with(LettuceSingletons.COMMAND_CONTEXT_KEY, parentContext);
Expand All @@ -88,7 +92,9 @@ public static void stopSpan(
@Advice.Return AsyncCommand<?, ?, ?> asyncCommand,
@Advice.Enter AdviceScope adviceScope) {

adviceScope.end(throwable, command, asyncCommand);
if (adviceScope != null) {
adviceScope.end(throwable, command, asyncCommand);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ public void end(

@Advice.OnMethodEnter(suppress = Throwable.class)
public static AdviceScope onEnter(@Advice.Argument(1) RedisURI redisUri) {
Context context = connectInstrumenter().start(currentContext(), redisUri);
Context parentContext = currentContext();
if (!connectInstrumenter().shouldStart(parentContext, redisUri)) {
return null;
}

Context context = connectInstrumenter().start(parentContext, redisUri);
return new AdviceScope(context, context.makeCurrent());
}

Expand All @@ -82,7 +87,9 @@ public static void stopSpan(
@Advice.Thrown @Nullable Throwable throwable,
@Advice.Return ConnectionFuture<?> connectionFuture,
@Advice.Enter AdviceScope adviceScope) {
adviceScope.end(throwable, redisUri, connectionFuture);
if (adviceScope != null) {
adviceScope.end(throwable, redisUri, connectionFuture);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
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.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener;
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;

/** Entrypoint for instrumenting Lettuce or clients. */
Expand All @@ -33,10 +35,12 @@ public static LettuceTelemetryBuilder builder(OpenTelemetry openTelemetry) {
private final Tracer tracer;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;
private final Instrumenter<Object, Void> instrumenter;

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

// Create minimal instrumenter only for shouldStart checks
// The actual span creation is handled by the existing SpanBuilder mechanism
instrumenter = Instrumenter.<Object, Void>builder(openTelemetry, INSTRUMENTATION_NAME, req -> "redis")
.setEnabled(instrumentationEnabled)
.buildInstrumenter();
}

/**
* 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, instrumenter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public final class LettuceTelemetryBuilder {
private final OpenTelemetry openTelemetry;

private boolean statementSanitizationEnabled = true;
private boolean instrumentationEnabled = true;

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

/**
* Sets whether instrumentation should be enabled. If set to {@code false}, no spans will be
* created by the constructed {@link LettuceTelemetry}. Enabled by default.
*/
@CanIgnoreReturnValue
public LettuceTelemetryBuilder setInstrumentationEnabled(boolean instrumentationEnabled) {
this.instrumentationEnabled = instrumentationEnabled;
return this;
}

/**
* Returns a new {@link LettuceTelemetry} with the settings of this {@link
* LettuceTelemetryBuilder}.
Expand All @@ -42,6 +53,7 @@ public LettuceTelemetry build() {
return new LettuceTelemetry(
openTelemetry,
statementSanitizationEnabled,
instrumentationEnabled,
DbClientMetrics.get().create(openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,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.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener;
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor;
Expand All @@ -54,13 +55,20 @@ final class OpenTelemetryTracing implements Tracing {
ServerAttributesExtractor.create(new LettuceServerAttributesGetter());
private static final AttributesExtractor<OpenTelemetryEndpoint, Void> networkAttributesExtractor =
NetworkAttributesExtractor.create(new LettuceServerAttributesGetter());

// Simple request object for shouldStart checks when we don't have full RedisCommand details
private static final Object REDIS_OPERATION_REQUEST = new Object();

private final TracerProvider tracerProvider;
private final Instrumenter<Object, Void> instrumenter;

OpenTelemetryTracing(
io.opentelemetry.api.trace.Tracer tracer,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
this.tracerProvider = new OpenTelemetryTracerProvider(tracer, sanitizer, metrics);
OperationListener metrics,
Instrumenter<Object, Void> instrumenter) {
this.tracerProvider = new OpenTelemetryTracerProvider(tracer, sanitizer, metrics, instrumenter);
this.instrumenter = instrumenter;
}

@Override
Expand Down Expand Up @@ -100,8 +108,9 @@ 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,
Instrumenter<Object, Void> instrumenter) {
openTelemetryTracer = new OpenTelemetryTracer(tracer, sanitizer, metrics, instrumenter);
}

@Override
Expand Down Expand Up @@ -143,14 +152,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 Instrumenter<Object, Void> instrumenter;

OpenTelemetryTracer(
io.opentelemetry.api.trace.Tracer tracer,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
OperationListener metrics,
Instrumenter<Object, Void> instrumenter) {
this.tracer = tracer;
this.sanitizer = sanitizer;
this.metrics = metrics;
this.instrumenter = instrumenter;
}

@Override
Expand Down Expand Up @@ -179,7 +191,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, instrumenter);
}
}

Expand All @@ -193,6 +205,7 @@ private static class OpenTelemetrySpan extends Tracer.Span {
private final SpanBuilder spanBuilder;
private final RedisCommandSanitizer sanitizer;
private final OperationListener metrics;
private final Instrumenter<Object, Void> instrumenter;

@Nullable private String name;
@Nullable private List<Object> events;
Expand All @@ -207,11 +220,13 @@ private static class OpenTelemetrySpan extends Tracer.Span {
Context context,
SpanBuilder spanBuilder,
RedisCommandSanitizer sanitizer,
OperationListener metrics) {
OperationListener metrics,
Instrumenter<Object, Void> instrumenter) {
this.context = context;
this.spanBuilder = spanBuilder;
this.sanitizer = sanitizer;
this.metrics = metrics;
this.instrumenter = instrumenter;
this.attributesBuilder = Attributes.builder();
if (SemconvStability.emitStableDatabaseSemconv()) {
attributesBuilder.put(DB_SYSTEM_NAME, REDIS);
Expand Down Expand Up @@ -261,7 +276,12 @@ private void fillEndpoint(OpenTelemetryEndpoint endpoint) {
@CanIgnoreReturnValue
@SuppressWarnings({"UnusedMethod", "EffectivelyPrivate"})
public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
start();
// Check if instrumentation should start for this command
if (!instrumenter.shouldStart(context, (Object) command)) {
return this;
}

startSpanInternal();
long startNanos = System.nanoTime();

Span span = this.span;
Expand Down Expand Up @@ -301,6 +321,15 @@ public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
@Override
@CanIgnoreReturnValue
public synchronized Tracer.Span start() {
// Check if instrumentation should start for generic redis operation
if (!instrumenter.shouldStart(context, REDIS_OPERATION_REQUEST)) {
return this;
}

return startSpanInternal();
}

private synchronized Tracer.Span startSpanInternal() {
span = spanBuilder.startSpan();
spanStartNanos = System.nanoTime();
if (name != null) {
Expand Down
Loading