Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OTEL propagator #2380

Merged
merged 4 commits into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ public final class io/sentry/opentelemetry/SentryBootstrapPackagesProvider : io/
public fun configure (Lio/opentelemetry/javaagent/tooling/bootstrap/BootstrapPackagesBuilder;Lio/opentelemetry/sdk/autoconfigure/spi/ConfigProperties;)V
}

public final class io/sentry/opentelemetry/SentryPropagatorProvider : io/opentelemetry/sdk/autoconfigure/spi/ConfigurablePropagatorProvider {
public fun <init> ()V
public fun getName ()Ljava/lang/String;
public fun getPropagator (Lio/opentelemetry/sdk/autoconfigure/spi/ConfigProperties;)Lio/opentelemetry/context/propagation/TextMapPropagator;
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,29 @@
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import java.util.HashMap;
import java.util.Map;

public final class SentryAutoConfigurationCustomizerProvider
implements AutoConfigurationCustomizerProvider {

@Override
public void customize(AutoConfigurationCustomizer autoConfiguration) {
autoConfiguration.addTracerProviderCustomizer(this::configureSdkTracerProvider);
// .addPropertiesSupplier(this::getDefaultProperties);
autoConfiguration
.addTracerProviderCustomizer(this::configureSdkTracerProvider)
.addPropertiesSupplier(this::getDefaultProperties);
}

private SdkTracerProviderBuilder configureSdkTracerProvider(
SdkTracerProviderBuilder tracerProvider, ConfigProperties config) {

return tracerProvider.addSpanProcessor(new SentrySpanProcessor());
}

// private Map<String, String> getDefaultProperties() {
// Map<String, String> properties = new HashMap<>();
// properties.put("otel.exporter.otlp.endpoint", "http://backend:8080");
// properties.put("otel.exporter.otlp.insecure", "true");
// properties.put("otel.config.max.attrs", "16");
// properties.put("otel.traces.sampler", "demo");
// return properties;
// }
private Map<String, String> getDefaultProperties() {
Map<String, String> properties = new HashMap<>();
properties.put("otel.traces.exporter", "none");
properties.put("otel.metrics.exporter", "none");
properties.put("otel.propagators", "sentry");
return properties;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.sentry.opentelemetry;

import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider;

public final class SentryPropagatorProvider implements ConfigurablePropagatorProvider {
@Override
public TextMapPropagator getPropagator(ConfigProperties config) {
return new SentryPropagator();
}

@Override
public String getName() {
return "sentry";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.sentry.opentelemetry.SentryPropagatorProvider
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
public final class io/sentry/opentelemetry/OtelSpanInfo {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V
public fun getDescription ()Ljava/lang/String;
public fun getOp ()Ljava/lang/String;
public fun getTransactionNameSource ()Lio/sentry/protocol/TransactionNameSource;
}

public final class io/sentry/opentelemetry/SentryOtelKeys {
public static final field SENTRY_BAGGAGE_KEY Lio/opentelemetry/context/ContextKey;
public static final field SENTRY_TRACE_KEY Lio/opentelemetry/context/ContextKey;
public fun <init> ()V
}

public final class io/sentry/opentelemetry/SentryPropagator : io/opentelemetry/context/propagation/TextMapPropagator {
public fun <init> ()V
public fun extract (Lio/opentelemetry/context/Context;Ljava/lang/Object;Lio/opentelemetry/context/propagation/TextMapGetter;)Lio/opentelemetry/context/Context;
public fun fields ()Ljava/util/Collection;
public fun inject (Lio/opentelemetry/context/Context;Ljava/lang/Object;Lio/opentelemetry/context/propagation/TextMapSetter;)V
}

public final class io/sentry/opentelemetry/SentrySpanProcessor : io/opentelemetry/sdk/trace/SpanProcessor {
public fun <init> ()V
public fun isEndRequired ()Z
Expand All @@ -6,21 +26,23 @@ public final class io/sentry/opentelemetry/SentrySpanProcessor : io/opentelemetr
public fun onStart (Lio/opentelemetry/context/Context;Lio/opentelemetry/sdk/trace/ReadWriteSpan;)V
}

public final class io/sentry/opentelemetry/SpanDescription {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V
public fun getDescription ()Ljava/lang/String;
public fun getOp ()Ljava/lang/String;
public fun getTransactionNameSource ()Lio/sentry/protocol/TransactionNameSource;
public final class io/sentry/opentelemetry/SentrySpanStorage {
public fun get (Ljava/lang/String;)Lio/sentry/ISpan;
public static fun getInstance ()Lio/sentry/opentelemetry/SentrySpanStorage;
public fun removeAndGet (Ljava/lang/String;)Lio/sentry/ISpan;
public fun store (Ljava/lang/String;Lio/sentry/ISpan;)V
}

public final class io/sentry/opentelemetry/SpanDescriptionExtractor {
public fun <init> ()V
public fun extractSpanDescription (Lio/opentelemetry/sdk/trace/ReadableSpan;)Lio/sentry/opentelemetry/SpanDescription;
public fun extractSpanDescription (Lio/opentelemetry/sdk/trace/ReadableSpan;)Lio/sentry/opentelemetry/OtelSpanInfo;
}

public final class io/sentry/opentelemetry/TraceData {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/sentry/SentryTraceHeader;Lio/sentry/Baggage;)V
public fun getBaggage ()Lio/sentry/Baggage;
public fun getParentSpanId ()Ljava/lang/String;
public fun getSentryTraceHeader ()Lio/sentry/SentryTraceHeader;
public fun getSpanId ()Ljava/lang/String;
public fun getTraceId ()Ljava/lang/String;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import org.jetbrains.annotations.NotNull;

@ApiStatus.Internal
public final class SpanDescription {
public final class OtelSpanInfo {

private final @NotNull String op;
private final @NotNull String description;
private final @NotNull TransactionNameSource transactionNameSource;

public SpanDescription(
public OtelSpanInfo(
final @NotNull String op,
final @NotNull String description,
final @NotNull TransactionNameSource transactionNameSource) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.sentry.opentelemetry;

import io.opentelemetry.context.ContextKey;
import io.sentry.Baggage;
import io.sentry.SentryTraceHeader;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

@ApiStatus.Internal
public final class SentryOtelKeys {

public static final @NotNull ContextKey<SentryTraceHeader> SENTRY_TRACE_KEY =
ContextKey.named("sentry.trace");
public static final @NotNull ContextKey<Baggage> SENTRY_BAGGAGE_KEY =
ContextKey.named("sentry.baggage");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package io.sentry.opentelemetry;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.context.propagation.TextMapSetter;
import io.sentry.Baggage;
import io.sentry.BaggageHeader;
import io.sentry.ISpan;
import io.sentry.SentryTraceHeader;
import io.sentry.exception.InvalidSentryTraceHeaderException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public final class SentryPropagator implements TextMapPropagator {

private static final @NotNull List<String> FIELDS =
Arrays.asList(SentryTraceHeader.SENTRY_TRACE_HEADER, BaggageHeader.BAGGAGE_HEADER);
private final @NotNull SentrySpanStorage spanStorage = SentrySpanStorage.getInstance();

@Override
public Collection<String> fields() {
return FIELDS;
}

@Override
public <C> void inject(final Context context, final C carrier, final TextMapSetter<C> setter) {
final @NotNull Span otelSpan = Span.fromContext(context);
final @NotNull SpanContext otelSpanContext = otelSpan.getSpanContext();
if (!otelSpanContext.isValid()) {
return;
}
final @Nullable ISpan sentrySpan = spanStorage.get(otelSpanContext.getSpanId());
if (sentrySpan == null) {
return;
}

final @NotNull SentryTraceHeader sentryTraceHeader = sentrySpan.toSentryTrace();
setter.set(carrier, sentryTraceHeader.getName(), sentryTraceHeader.getValue());
final @Nullable BaggageHeader baggageHeader =
sentrySpan.toBaggageHeader(Collections.emptyList());
if (baggageHeader != null) {
setter.set(carrier, baggageHeader.getName(), baggageHeader.getValue());
}
}

@Override
public <C> Context extract(
final Context context, final C carrier, final TextMapGetter<C> getter) {
final @Nullable String sentryTraceString =
getter.get(carrier, SentryTraceHeader.SENTRY_TRACE_HEADER);
if (sentryTraceString == null) {
return context;
}

try {
SentryTraceHeader sentryTraceHeader = new SentryTraceHeader(sentryTraceString);

SpanContext otelSpanContext =
SpanContext.createFromRemoteParent(
sentryTraceHeader.getTraceId().toString(),
sentryTraceHeader.getSpanId().toString(),
TraceFlags.getSampled(),
TraceState.getDefault());

@NotNull
Context modifiedContext = context.with(SentryOtelKeys.SENTRY_TRACE_KEY, sentryTraceHeader);

final @Nullable String baggageString = getter.get(carrier, BaggageHeader.BAGGAGE_HEADER);
if (baggageString != null) {
Baggage baggage = Baggage.fromHeader(baggageString);
modifiedContext = modifiedContext.with(SentryOtelKeys.SENTRY_BAGGAGE_KEY, baggage);
}

Span wrappedSpan = Span.wrap(otelSpanContext);
modifiedContext = modifiedContext.with(wrappedSpan);

return modifiedContext;
} catch (InvalidSentryTraceHeaderException e) {
return context;
}
}
}