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 SpanProcessor for OTEL #2357

Merged
merged 6 commits into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
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"
romtsn marked this conversation as resolved.
Show resolved Hide resolved
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