Skip to content

Commit

Permalink
Add SpanProcessor for OTEL (#2357)
Browse files Browse the repository at this point in the history
  • Loading branch information
adinauer authored Nov 28, 2022
1 parent 6b344be commit 5095c0f
Show file tree
Hide file tree
Showing 49 changed files with 1,045 additions and 107 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixes

- Fix `Gpu.vendorId` should be a String ([#2343](https://github.com/getsentry/sentry-java/pull/2343))
- Do not attach empty `sentry-trace` and `baggage` headers ([#2385](https://github.com/getsentry/sentry-java/pull/2385))

### Features

Expand Down
2 changes: 2 additions & 0 deletions buildSrc/src/main/java/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ object Config {
val apolloKotlin = "com.apollographql.apollo3:apollo-runtime:3.3.0"

val otelVersion = "1.19.0"
val otelAlphaVersion = "1.19.0-alpha"
val otelJavaagentVersion = "1.19.2"
val otelJavaagentAlphaVersion = "1.19.2-alpha"
}
Expand Down Expand Up @@ -199,6 +200,7 @@ object Config {
val SENTRY_SPRING_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring"
val SENTRY_SPRING_BOOT_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring-boot"
val SENTRY_SPRING_BOOT_JAKARTA_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.spring-boot.jakarta"
val SENTRY_OPENTELEMETRY_AGENT_SDK_NAME = "$SENTRY_JAVA_SDK_NAME.opentelemetry.agent"
val group = "io.sentry"
val description = "SDK for sentry.io"
val versionNameProp = "versionName"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class SentryOkHttpInterceptor(
var code: Int? = null
try {
val requestBuilder = request.newBuilder()
if (span != null &&
if (span != null && !span.isNoOp &&
PropagationTargetsUtils.contain(hub.options.tracePropagationTargets, request.url.toString())
) {
span.toSentryTrace().let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class SentryApollo3HttpInterceptor @JvmOverloads constructor(private val hub: IH

var cleanedHeaders = removeSentryInternalHeaders(request.headers).toMutableList()

if (PropagationTargetsUtils.contain(hub.options.tracePropagationTargets, request.url)) {
if (!span.isNoOp && PropagationTargetsUtils.contain(hub.options.tracePropagationTargets, request.url)) {
val sentryTraceHeader = span.toSentryTrace()
val baggageHeader = span.toBaggageHeader(request.headers.filter { it.name == BaggageHeader.BAGGAGE_HEADER }.map { it.value })
cleanedHeaders.add(HttpHeader(sentryTraceHeader.name, sentryTraceHeader.value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,23 @@ class SentryApolloInterceptor(
chain.proceedAsync(request, dispatcher, callBack)
} else {
val span = startChild(request, activeSpan)
val sentryTraceHeader = span.toSentryTrace()

// we have no access to URI, no way to verify tracing origins
val requestHeaderBuilder = request.requestHeaders.toBuilder()
requestHeaderBuilder.addHeader(sentryTraceHeader.name, sentryTraceHeader.value)
span.toBaggageHeader(listOf(request.requestHeaders.headerValue(BaggageHeader.BAGGAGE_HEADER)))?.let {
requestHeaderBuilder.addHeader(it.name, it.value)
val requestWithHeader = if (span.isNoOp) {
request
} else {
val sentryTraceHeader = span.toSentryTrace()

// we have no access to URI, no way to verify tracing origins
val requestHeaderBuilder = request.requestHeaders.toBuilder()
requestHeaderBuilder.addHeader(sentryTraceHeader.name, sentryTraceHeader.value)
span.toBaggageHeader(listOf(request.requestHeaders.headerValue(BaggageHeader.BAGGAGE_HEADER)))
?.let {
requestHeaderBuilder.addHeader(it.name, it.value)
}
val headers = requestHeaderBuilder.build()
request.toBuilder().requestHeaders(headers).build()
}
val headers = requestHeaderBuilder.build()
val requestWithHeader = request.toBuilder().requestHeaders(headers).build()

span.setData("operationId", requestWithHeader.operation.operationId())
span.setData("variables", requestWithHeader.operation.variables().valueMap().toString())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public SentryJdbcEventListener() {
@Override
public void onBeforeAnyExecute(final @NotNull StatementInformation statementInformation) {
final ISpan parent = hub.getSpan();
if (parent != null) {
if (parent != null && !parent.isNoOp()) {
final ISpan span = parent.startChild("db.query", statementInformation.getSql());
CURRENT_SPAN.set(span);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public Response execute(final @NotNull Request request, final @NotNull Request.O

final RequestWrapper requestWrapper = new RequestWrapper(request);

if (PropagationTargetsUtils.contain(hub.getOptions().getTracePropagationTargets(), url)) {
if (!span.isNoOp()
&& PropagationTargetsUtils.contain(hub.getOptions().getTracePropagationTargets(), url)) {
final SentryTraceHeader sentryTraceHeader = span.toSentryTrace();
final @Nullable Collection<String> requestBaggageHeader =
request.headers().get(BaggageHeader.BAGGAGE_HEADER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,12 @@ tasks {
attributes.put("Premain-Class", "io.opentelemetry.javaagent.OpenTelemetryAgent")
attributes.put("Can-Redefine-Classes", "true")
attributes.put("Can-Retransform-Classes", "true")
attributes.put("Implementation-Vendor", "Demo")
attributes.put("Implementation-Version", "demo-${project.version}-otel-${Config.Libs.otelJavaagentVersion}")
attributes.put("Implementation-Vendor", "Sentry")
attributes.put("Implementation-Version", "sentry-${project.version}-otel-${Config.Libs.otelJavaagentVersion}")
attributes.put("Sentry-Version-Name", project.version)
attributes.put("Sentry-Opentelemetry-SDK-Name", Config.Sentry.SENTRY_OPENTELEMETRY_AGENT_SDK_NAME)
attributes.put("Sentry-Opentelemetry-Version-Name", Config.Libs.otelVersion)
attributes.put("Sentry-Opentelemetry-Javaagent-Version-Name", Config.Libs.otelJavaagentVersion)
}
}

Expand Down
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,97 @@
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.sentry.Instrumenter;
import io.sentry.Sentry;
import io.sentry.SentryOptions;
import io.sentry.protocol.SdkVersion;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public final class SentryAutoConfigurationCustomizerProvider
implements AutoConfigurationCustomizerProvider {

@Override
public void customize(AutoConfigurationCustomizer autoConfiguration) {
autoConfiguration.addTracerProviderCustomizer(this::configureSdkTracerProvider);
// .addPropertiesSupplier(this::getDefaultProperties);
final @Nullable String sentryPropertiesFile = System.getenv("SENTRY_PROPERTIES_FILE");
final @Nullable String sentryDsn = System.getenv("SENTRY_DSN");

if (sentryPropertiesFile != null || sentryDsn != null) {
Sentry.init(
options -> {
options.setEnableExternalConfiguration(true);
options.setInstrumenter(Instrumenter.OTEL);
final @Nullable SdkVersion sdkVersion = createSdkVersion(options);
if (sdkVersion != null) {
options.setSdkVersion(sdkVersion);
}
});
}

autoConfiguration
.addTracerProviderCustomizer(this::configureSdkTracerProvider)
.addPropertiesSupplier(this::getDefaultProperties);
}

private @Nullable SdkVersion createSdkVersion(final @NotNull SentryOptions sentryOptions) {
SdkVersion sdkVersion = sentryOptions.getSdkVersion();

try {
final @NotNull Enumeration<URL> resources =
ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
try {
final @NotNull Manifest manifest = new Manifest(resources.nextElement().openStream());
final @Nullable Attributes mainAttributes = manifest.getMainAttributes();
if (mainAttributes != null) {
final @Nullable String name = mainAttributes.getValue("Sentry-Opentelemetry-SDK-Name");
final @Nullable String version = mainAttributes.getValue("Sentry-Version-Name");

if (name != null && version != null) {
sdkVersion = SdkVersion.updateSdkVersion(sdkVersion, name, version);
sdkVersion.addPackage("maven:io.sentry:sentry-opentelemetry-agent", version);
final @Nullable String otelVersion =
mainAttributes.getValue("Sentry-Opentelemetry-Version-Name");
if (otelVersion != null) {
sdkVersion.addPackage("maven:io.opentelemetry:opentelemetry-sdk", otelVersion);
}
final @Nullable String otelJavaagentVersion =
mainAttributes.getValue("Sentry-Opentelemetry-Javaagent-Version-Name");
if (otelJavaagentVersion != null) {
sdkVersion.addPackage(
"maven:io.opentelemetry.javaagent:opentelemetry-javaagent",
otelJavaagentVersion);
}
}
}
} catch (Exception e) {
// ignore
}
}
} catch (IOException e) {
// ignore
}

return sdkVersion;
}

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,3 +26,24 @@ 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/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/OtelSpanInfo;
}

public final class io/sentry/opentelemetry/TraceData {
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;
}

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies {
compileOnly(projects.sentry)

compileOnly("io.opentelemetry:opentelemetry-sdk:${Config.Libs.otelVersion}")
compileOnly("io.opentelemetry:opentelemetry-semconv:${Config.Libs.otelAlphaVersion}")

compileOnly(Config.CompileOnly.nopen)
errorprone(Config.CompileOnly.nopenChecker)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.sentry.opentelemetry;

import io.sentry.protocol.TransactionNameSource;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

@ApiStatus.Internal
public final class OtelSpanInfo {

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

public OtelSpanInfo(
final @NotNull String op,
final @NotNull String description,
final @NotNull TransactionNameSource transactionNameSource) {
this.op = op;
this.description = description;
this.transactionNameSource = transactionNameSource;
}

public @NotNull String getOp() {
return op;
}

public @NotNull String getDescription() {
return description;
}

public @NotNull TransactionNameSource getTransactionNameSource() {
return transactionNameSource;
}
}
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");
}
Loading

0 comments on commit 5095c0f

Please sign in to comment.