diff --git a/CHANGELOG.md b/CHANGELOG.md index 295f7d46508..84663ffa36e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - Manually constructed `SentryTimberIntegration` and `SentryTimberTree` instances require a `logsEnabled` argument. Pass `false` to keep Sentry Logs disabled. - Remove the Apache HttpClient transport and stop publishing `sentry-apache-http-client-5` ([#6214](https://github.com/getsentry/sentry-java/pull/6214)) +- Remove deprecated OpenTelemetry integration classes and the legacy `SentrySpanStorage` ([#6243](https://github.com/getsentry/sentry-java/pull/6243)) ### Features diff --git a/sentry-opentelemetry/README.md b/sentry-opentelemetry/README.md index 2a7e629e78c..b31c43e2211 100644 --- a/sentry-opentelemetry/README.md +++ b/sentry-opentelemetry/README.md @@ -18,7 +18,7 @@ application. Please see the module [README](sentry-opentelemetry-agent/README.md ### `sentry-opentelemetry-agentcustomization` This contains customizations to the OpenTelemetry Java Agent such as registering the -`SentrySpanProcessor` and `SentryPropagator` as well as providing default properties that +`OtelSentrySpanProcessor` and `OtelSentryPropagator` as well as providing default properties that enable the `sentry` propagator. ### `sentry-opentelemetry-bootstrap` @@ -33,7 +33,7 @@ you also need this module as a dependency. ### `sentry-opentelemetry-core` -Contains `SentrySpanProcessor` and `SentryPropagator` which are used by our Java Agent but can also +Contains `OtelSentrySpanProcessor` and `OtelSentryPropagator` which are used by our Java Agent but can also be used when manually instrumenting using OpenTelemetry. If you want to use OpenTelemetry without the agent but still want some configuration convenience, you should rather use the `sentry-opentelemetry-agentless` module or the `sentry-opentelemetry-agentless-spring` module if you are using Spring Boot. @@ -58,7 +58,7 @@ Alternatively you can initialize OpenTelemetry programmatically like this: ```java // Initialize OpenTelemetry by using the AutoConfiguredOpenTelemetrySdk which automatically -// registers the `SentrySpanProcessor` and `SentryPropagator` and others. +// registers the `OtelSentrySpanProcessor` and `OtelSentryPropagator` and others. // Also, you need to disable the OTEL exporters if you do not use them. AutoConfiguredOpenTelemetrySdk.builder() .setResultAsGlobal() diff --git a/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md b/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md index 8663a6caa98..1a82d03cd44 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md +++ b/sentry-opentelemetry/sentry-opentelemetry-agentless/README.md @@ -29,7 +29,7 @@ Alternatively you can initialize OpenTelemetry programmatically like this: ```java // Initialize OpenTelemetry by using the AutoConfiguredOpenTelemetrySdk which automatically -// registers the `SentrySpanProcessor` and `SentryPropagator` and others. +// registers the `OtelSentrySpanProcessor` and `OtelSentryPropagator` and others. // Also, you need to disable the OTEL exporters if you do not use them. AutoConfiguredOpenTelemetrySdk.builder() .setResultAsGlobal() diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api b/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api index 3ed25d1a9cf..d10d2844cab 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api +++ b/sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api @@ -4,12 +4,6 @@ public final class io/sentry/opentelemetry/OpenTelemetryAttributesExtractor { public fun extractUrl (Lio/opentelemetry/api/common/Attributes;Lio/sentry/SentryOptions;)Ljava/lang/String; } -public final class io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor : io/sentry/EventProcessor { - public fun ()V - public fun getOrder ()Ljava/lang/Long; - public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent; -} - public final class io/sentry/opentelemetry/OtelInternalSpanDetectionUtil { public fun ()V public static fun isSentryRequest (Lio/sentry/IScopes;Lio/opentelemetry/api/trace/SpanKind;Lio/opentelemetry/api/common/Attributes;)Z @@ -110,13 +104,6 @@ public final class io/sentry/opentelemetry/OtelSpanWrapper : io/sentry/opentelem public fun updateEndDate (Lio/sentry/SentryDate;)Z } -public final class io/sentry/opentelemetry/SentryPropagator : io/opentelemetry/context/propagation/TextMapPropagator { - public fun ()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/SentrySampler : io/opentelemetry/sdk/trace/samplers/Sampler { public fun ()V public fun (Lio/sentry/IScopes;)V @@ -140,14 +127,6 @@ public final class io/sentry/opentelemetry/SentrySpanExporter : io/opentelemetry public fun shutdown ()Lio/opentelemetry/sdk/common/CompletableResultCode; } -public final class io/sentry/opentelemetry/SentrySpanProcessor : io/opentelemetry/sdk/trace/SpanProcessor { - public fun ()V - public fun isEndRequired ()Z - public fun isStartRequired ()Z - public fun onEnd (Lio/opentelemetry/sdk/trace/ReadableSpan;)V - public fun onStart (Lio/opentelemetry/context/Context;Lio/opentelemetry/sdk/trace/ReadWriteSpan;)V -} - public final class io/sentry/opentelemetry/SpanDescriptionExtractor { public fun ()V public fun extractSpanInfo (Lio/opentelemetry/sdk/trace/data/SpanData;Lio/sentry/opentelemetry/IOtelSpanWrapper;Lio/sentry/SentryOptions;)Lio/sentry/opentelemetry/OtelSpanInfo; @@ -165,12 +144,3 @@ public final class io/sentry/opentelemetry/SpanNode { public fun setSpan (Lio/opentelemetry/sdk/trace/data/SpanData;)V } -public final class io/sentry/opentelemetry/TraceData { - public fun (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; -} - diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor.java deleted file mode 100644 index cf1e530cd9e..00000000000 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OpenTelemetryLinkErrorEventProcessor.java +++ /dev/null @@ -1,113 +0,0 @@ -package io.sentry.opentelemetry; - -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanId; -import io.opentelemetry.api.trace.TraceId; -import io.sentry.EventProcessor; -import io.sentry.Hint; -import io.sentry.IScopes; -import io.sentry.ISpan; -import io.sentry.Instrumenter; -import io.sentry.ScopesAdapter; -import io.sentry.SentryEvent; -import io.sentry.SentryLevel; -import io.sentry.SpanContext; -import io.sentry.protocol.SentryId; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; - -/** - * @deprecated this is no longer needed for the latest version of our OpenTelemetry integration. - */ -@Deprecated -public final class OpenTelemetryLinkErrorEventProcessor implements EventProcessor { - - private final @NotNull IScopes scopes; - - @SuppressWarnings("deprecation") - private final @NotNull io.sentry.SentrySpanStorage spanStorage = - io.sentry.SentrySpanStorage.getInstance(); - - public OpenTelemetryLinkErrorEventProcessor() { - this(ScopesAdapter.getInstance()); - } - - @TestOnly - OpenTelemetryLinkErrorEventProcessor(final @NotNull IScopes scopes) { - this.scopes = scopes; - } - - @Override - public @Nullable SentryEvent process(final @NotNull SentryEvent event, final @NotNull Hint hint) { - final @NotNull Instrumenter instrumenter = scopes.getOptions().getInstrumenter(); - if (Instrumenter.OTEL.equals(instrumenter)) { - @NotNull final Span otelSpan = Span.current(); - @NotNull final String traceId = otelSpan.getSpanContext().getTraceId(); - @NotNull final String spanId = otelSpan.getSpanContext().getSpanId(); - - if (TraceId.isValid(traceId) && SpanId.isValid(spanId)) { - final @Nullable ISpan sentrySpan = spanStorage.get(spanId); - if (sentrySpan != null) { - final @NotNull SpanContext sentrySpanSpanContext = sentrySpan.getSpanContext(); - final @NotNull String operation = sentrySpanSpanContext.getOperation(); - final @Nullable io.sentry.SpanId parentSpanId = sentrySpanSpanContext.getParentSpanId(); - final @NotNull SpanContext spanContext = - new SpanContext( - new SentryId(traceId), - new io.sentry.SpanId(spanId), - operation, - parentSpanId, - null); - - event.getContexts().setTrace(spanContext); - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Linking Sentry event %s to span %s created via OpenTelemetry (trace %s).", - event.getEventId(), - spanId, - traceId); - } else { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not linking Sentry event %s to any transaction created via OpenTelemetry as none has been found for span %s (trace %s).", - event.getEventId(), - spanId, - traceId); - } - } else { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not linking Sentry event %s to any transaction created via OpenTelemetry as traceId %s or spanId %s are invalid.", - event.getEventId(), - traceId, - spanId); - } - } else { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not linking Sentry event %s to any transaction created via OpenTelemetry as instrumenter is set to %s.", - event.getEventId(), - instrumenter); - } - - return event; - } - - @Override - public @Nullable Long getOrder() { - return 6000L; - } -} diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java deleted file mode 100644 index 4016debf2bb..00000000000 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentryPropagator.java +++ /dev/null @@ -1,144 +0,0 @@ -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.IScopes; -import io.sentry.ISpan; -import io.sentry.ScopesAdapter; -import io.sentry.SentryLevel; -import io.sentry.SentryTraceHeader; -import io.sentry.exception.InvalidSentryTraceHeaderException; -import io.sentry.util.TracingUtils; -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; - -/** - * @deprecated please use {@link OtelSentryPropagator} instead - */ -@Deprecated -public final class SentryPropagator implements TextMapPropagator { - - private static final @NotNull List FIELDS = - Arrays.asList(SentryTraceHeader.SENTRY_TRACE_HEADER, BaggageHeader.BAGGAGE_HEADER); - - @SuppressWarnings("deprecation") - private final @NotNull io.sentry.SentrySpanStorage spanStorage = - io.sentry.SentrySpanStorage.getInstance(); - - private final @NotNull IScopes scopes; - - public SentryPropagator() { - this(ScopesAdapter.getInstance()); - } - - SentryPropagator(final @NotNull IScopes scopes) { - this.scopes = scopes; - } - - @Override - public Collection fields() { - return FIELDS; - } - - @Override - public void inject(final Context context, final C carrier, final TextMapSetter setter) { - final @NotNull Span otelSpan = Span.fromContext(context); - final @NotNull SpanContext otelSpanContext = otelSpan.getSpanContext(); - if (!otelSpanContext.isValid()) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not injecting Sentry tracing information for invalid OpenTelemetry span."); - return; - } - final @Nullable ISpan sentrySpan = spanStorage.get(otelSpanContext.getSpanId()); - if (sentrySpan == null || sentrySpan.isNoOp()) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not injecting Sentry tracing information for span %s as no Sentry span has been found or it is a NoOp (trace %s). This might simply mean this is a request to Sentry.", - otelSpanContext.getSpanId(), - otelSpanContext.getTraceId()); - 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 Context extract( - final Context context, final C carrier, final TextMapGetter getter) { - final @Nullable String sentryTraceString = - getter.get(carrier, SentryTraceHeader.SENTRY_TRACE_HEADER); - if (sentryTraceString == null) { - return context; - } - - try { - SentryTraceHeader sentryTraceHeader = new SentryTraceHeader(sentryTraceString); - - final @Nullable String baggageString = getter.get(carrier, BaggageHeader.BAGGAGE_HEADER); - Baggage baggage = Baggage.fromHeader(baggageString); - if (!TracingUtils.shouldContinueTrace(scopes.getOptions(), baggage)) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, "Not continuing trace due to strict org ID validation failure."); - return context; - } - - SpanContext otelSpanContext = - SpanContext.createFromRemoteParent( - sentryTraceHeader.getTraceId().toString(), - sentryTraceHeader.getSpanId().toString(), - TraceFlags.getSampled(), - TraceState.getDefault()); - - @NotNull - Context modifiedContext = context.with(SentryOtelKeys.SENTRY_TRACE_KEY, sentryTraceHeader); - modifiedContext = modifiedContext.with(SentryOtelKeys.SENTRY_BAGGAGE_KEY, baggage); - - Span wrappedSpan = Span.wrap(otelSpanContext); - modifiedContext = modifiedContext.with(wrappedSpan); - - scopes - .getOptions() - .getLogger() - .log(SentryLevel.DEBUG, "Continuing Sentry trace %s", sentryTraceHeader.getTraceId()); - - return modifiedContext; - } catch (InvalidSentryTraceHeaderException e) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.ERROR, - "Unable to extract Sentry tracing information from invalid header.", - e); - return context; - } - } -} diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanProcessor.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanProcessor.java deleted file mode 100644 index 31bd6368318..00000000000 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/SentrySpanProcessor.java +++ /dev/null @@ -1,382 +0,0 @@ -package io.sentry.opentelemetry; - -import static io.sentry.TransactionContext.DEFAULT_TRANSACTION_NAME; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.trace.ReadWriteSpan; -import io.opentelemetry.sdk.trace.ReadableSpan; -import io.opentelemetry.sdk.trace.SpanProcessor; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.opentelemetry.sdk.trace.data.StatusData; -import io.opentelemetry.semconv.HttpAttributes; -import io.opentelemetry.semconv.UrlAttributes; -import io.sentry.Baggage; -import io.sentry.DsnUtil; -import io.sentry.IScopes; -import io.sentry.ISpan; -import io.sentry.ITransaction; -import io.sentry.Instrumenter; -import io.sentry.PropagationContext; -import io.sentry.ScopesAdapter; -import io.sentry.SentryDate; -import io.sentry.SentryLevel; -import io.sentry.SentryLongDate; -import io.sentry.SentryTraceHeader; -import io.sentry.SpanId; -import io.sentry.SpanOptions; -import io.sentry.SpanStatus; -import io.sentry.TransactionContext; -import io.sentry.TransactionOptions; -import io.sentry.protocol.SentryId; -import io.sentry.protocol.TransactionNameSource; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @deprecated please use {@link OtelSentrySpanProcessor} instead. - */ -@Deprecated -public final class SentrySpanProcessor implements SpanProcessor { - - private static final String TRACE_ORIGN = "auto.otel"; - - private final @NotNull List spanKindsConsideredForSentryRequests = - Arrays.asList(SpanKind.CLIENT, SpanKind.INTERNAL); - private final @NotNull SpanDescriptionExtractor spanDescriptionExtractor = - new SpanDescriptionExtractor(); - - @SuppressWarnings("deprecation") - private final @NotNull io.sentry.SentrySpanStorage spanStorage = - io.sentry.SentrySpanStorage.getInstance(); - - private final @NotNull IScopes scopes; - - public SentrySpanProcessor() { - this(ScopesAdapter.getInstance()); - } - - SentrySpanProcessor(final @NotNull IScopes scopes) { - this.scopes = scopes; - } - - @Override - public void onStart(final @NotNull Context parentContext, final @NotNull ReadWriteSpan otelSpan) { - if (!ensurePrerequisites(otelSpan)) { - return; - } - - final @NotNull TraceData traceData = getTraceData(otelSpan, parentContext); - - if (isSentryRequest(otelSpan)) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not forwarding OpenTelemetry span %s to Sentry as this looks like a span for a request to Sentry (trace %s).", - traceData.getSpanId(), - traceData.getTraceId()); - return; - } - final @Nullable ISpan sentryParentSpan = - traceData.getParentSpanId() == null ? null : spanStorage.get(traceData.getParentSpanId()); - - if (sentryParentSpan != null) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Creating Sentry child span for OpenTelemetry span %s (trace %s). Parent span is %s.", - traceData.getSpanId(), - traceData.getTraceId(), - traceData.getParentSpanId()); - final @NotNull SentryDate startDate = - new SentryLongDate(otelSpan.toSpanData().getStartEpochNanos()); - final @NotNull SpanOptions spanOptions = new SpanOptions(); - spanOptions.setOrigin(TRACE_ORIGN); - final @NotNull ISpan sentryChildSpan = - sentryParentSpan.startChild( - otelSpan.getName(), otelSpan.getName(), startDate, Instrumenter.OTEL, spanOptions); - spanStorage.store(traceData.getSpanId(), sentryChildSpan); - } else { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Creating Sentry transaction for OpenTelemetry span %s (trace %s).", - traceData.getSpanId(), - traceData.getTraceId()); - final @NotNull String transactionName = otelSpan.getName(); - final @NotNull TransactionNameSource transactionNameSource = TransactionNameSource.CUSTOM; - final @Nullable String op = otelSpan.getName(); - final SpanId spanId = new SpanId(traceData.getSpanId()); - - final @NotNull TransactionContext transactionContext = - traceData.getSentryTraceHeader() == null - ? new TransactionContext( - new SentryId(traceData.getTraceId()), spanId, null, null, null) - : TransactionContext.fromPropagationContext( - PropagationContext.fromHeaders( - traceData.getSentryTraceHeader(), - traceData.getBaggage(), - spanId, - scopes.getOptions())); - ; - transactionContext.setName(transactionName); - transactionContext.setTransactionNameSource(transactionNameSource); - transactionContext.setOperation(op); - transactionContext.setInstrumenter(Instrumenter.OTEL); - - TransactionOptions transactionOptions = new TransactionOptions(); - transactionOptions.setStartTimestamp( - new SentryLongDate(otelSpan.toSpanData().getStartEpochNanos())); - transactionOptions.setOrigin(TRACE_ORIGN); - - ISpan sentryTransaction = scopes.startTransaction(transactionContext, transactionOptions); - spanStorage.store(traceData.getSpanId(), sentryTransaction); - } - } - - @Override - public boolean isStartRequired() { - return true; - } - - @Override - public void onEnd(final @NotNull ReadableSpan otelSpan) { - if (!ensurePrerequisites(otelSpan)) { - return; - } - - final @NotNull TraceData traceData = getTraceData(otelSpan, null); - final @Nullable ISpan sentrySpan = spanStorage.removeAndGet(traceData.getSpanId()); - - if (sentrySpan == null) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Unable to find Sentry span for OpenTelemetry span %s (trace %s). This may simply mean it is a Sentry request.", - traceData.getSpanId(), - traceData.getTraceId()); - return; - } - - if (isSentryRequest(otelSpan)) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not forwarding OpenTelemetry span %s to Sentry as this looks like a span for a request to Sentry (trace %s).", - traceData.getSpanId(), - traceData.getTraceId()); - return; - } - - if (sentrySpan instanceof ITransaction) { - final @NotNull ITransaction sentryTransaction = (ITransaction) sentrySpan; - updateTransactionWithOtelData(sentryTransaction, otelSpan); - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Finishing Sentry transaction %s for OpenTelemetry span %s (trace %s).", - sentryTransaction.getEventId(), - traceData.getSpanId(), - traceData.getTraceId()); - } else { - updateSpanWithOtelData(sentrySpan, otelSpan); - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Finishing Sentry span for OpenTelemetry span %s (trace %s). Parent span is %s.", - traceData.getSpanId(), - traceData.getTraceId(), - traceData.getParentSpanId()); - } - - final @NotNull SpanStatus sentryStatus = mapOtelStatus(otelSpan); - final @NotNull SentryDate endTimestamp = - new SentryLongDate(otelSpan.toSpanData().getEndEpochNanos()); - sentrySpan.finish(sentryStatus, endTimestamp); - } - - @Override - public boolean isEndRequired() { - return true; - } - - private boolean ensurePrerequisites(final @NotNull ReadableSpan otelSpan) { - if (!hasSentryBeenInitialized()) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not forwarding OpenTelemetry span to Sentry as Sentry has not yet been initialized."); - return false; - } - - final @NotNull Instrumenter instrumenter = scopes.getOptions().getInstrumenter(); - if (!Instrumenter.OTEL.equals(instrumenter)) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not forwarding OpenTelemetry span to Sentry as instrumenter has been set to %s.", - instrumenter); - return false; - } - - final @NotNull SpanContext otelSpanContext = otelSpan.getSpanContext(); - if (!otelSpanContext.isValid()) { - scopes - .getOptions() - .getLogger() - .log( - SentryLevel.DEBUG, - "Not forwarding OpenTelemetry span to Sentry as the span is invalid."); - return false; - } - - return true; - } - - @SuppressWarnings("deprecation") - private boolean isSentryRequest(final @NotNull ReadableSpan otelSpan) { - final @NotNull SpanKind kind = otelSpan.getKind(); - if (!spanKindsConsideredForSentryRequests.contains(kind)) { - return false; - } - - final @Nullable String httpUrl = otelSpan.getAttribute(UrlAttributes.URL_FULL); - return DsnUtil.urlContainsDsnHost(scopes.getOptions(), httpUrl); - } - - private @NotNull TraceData getTraceData( - final @NotNull ReadableSpan otelSpan, final @Nullable Context parentContext) { - final @NotNull SpanContext otelSpanContext = otelSpan.getSpanContext(); - final @NotNull String otelSpanId = otelSpanContext.getSpanId(); - final @NotNull String otelParentSpanIdMaybeInvalid = - otelSpan.getParentSpanContext().getSpanId(); - final @NotNull String otelTraceId = otelSpanContext.getTraceId(); - final @Nullable String otelParentSpanId = - io.opentelemetry.api.trace.SpanId.isValid(otelParentSpanIdMaybeInvalid) - ? otelParentSpanIdMaybeInvalid - : null; - - @Nullable SentryTraceHeader sentryTraceHeader = null; - @Nullable Baggage baggage = null; - - if (parentContext != null) { - sentryTraceHeader = parentContext.get(SentryOtelKeys.SENTRY_TRACE_KEY); - if (sentryTraceHeader != null) { - baggage = parentContext.get(SentryOtelKeys.SENTRY_BAGGAGE_KEY); - } - } - - return new TraceData(otelTraceId, otelSpanId, otelParentSpanId, sentryTraceHeader, baggage); - } - - private void updateTransactionWithOtelData( - final @NotNull ITransaction sentryTransaction, final @NotNull ReadableSpan otelSpan) { - final @NotNull OtelSpanInfo otelSpanInfo = - spanDescriptionExtractor.extractSpanInfo(otelSpan.toSpanData(), null, scopes.getOptions()); - sentryTransaction.setOperation(otelSpanInfo.getOp()); - String transactionName = otelSpanInfo.getDescription(); - sentryTransaction.setName( - transactionName == null ? DEFAULT_TRANSACTION_NAME : transactionName, - otelSpanInfo.getTransactionNameSource()); - - final @NotNull Map otelContext = toOtelContext(otelSpan); - sentryTransaction.setContext("otel", otelContext); - } - - private @NotNull Map toOtelContext(final @NotNull ReadableSpan otelSpan) { - final @NotNull SpanData spanData = otelSpan.toSpanData(); - final @NotNull Map context = new HashMap<>(); - - context.put("attributes", toMapWithStringKeys(spanData.getAttributes())); - context.put("resource", toMapWithStringKeys(spanData.getResource().getAttributes())); - - return context; - } - - private void updateSpanWithOtelData( - final @NotNull ISpan sentrySpan, final @NotNull ReadableSpan otelSpan) { - final @NotNull SpanData spanData = otelSpan.toSpanData(); - - sentrySpan.setData("otel.kind", otelSpan.getKind()); - - spanData - .getAttributes() - .forEach( - (attributeKey, value) -> { - if (value != null) { - sentrySpan.setData(attributeKey.getKey(), value); - } - }); - - final @NotNull OtelSpanInfo otelSpanInfo = - spanDescriptionExtractor.extractSpanInfo(otelSpan.toSpanData(), null, scopes.getOptions()); - sentrySpan.setOperation(otelSpanInfo.getOp()); - sentrySpan.setDescription(otelSpanInfo.getDescription()); - } - - @SuppressWarnings("deprecation") - private SpanStatus mapOtelStatus(final @NotNull ReadableSpan otelSpan) { - final @NotNull SpanData otelSpanData = otelSpan.toSpanData(); - final @NotNull StatusData otelStatus = otelSpanData.getStatus(); - final @NotNull StatusCode otelStatusCode = otelStatus.getStatusCode(); - - if (StatusCode.OK.equals(otelStatusCode) || StatusCode.UNSET.equals(otelStatusCode)) { - return SpanStatus.OK; - } - - final @Nullable Long httpStatus = - otelSpan.getAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE); - if (httpStatus != null) { - final @Nullable SpanStatus spanStatus = SpanStatus.fromHttpStatusCode(httpStatus.intValue()); - if (spanStatus != null) { - return spanStatus; - } - } - - return SpanStatus.UNKNOWN_ERROR; - } - - private boolean hasSentryBeenInitialized() { - return scopes.isEnabled(); - } - - private @NotNull Map toMapWithStringKeys(final @Nullable Attributes attributes) { - final @NotNull Map mapWithStringKeys = new HashMap<>(); - - if (attributes != null) { - attributes.forEach( - (key, value) -> { - if (key != null) { - mapWithStringKeys.put(key.getKey(), value); - } - }); - } - - return mapWithStringKeys; - } -} diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/TraceData.java b/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/TraceData.java deleted file mode 100644 index 5904db39e77..00000000000 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/TraceData.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.sentry.opentelemetry; - -import io.sentry.Baggage; -import io.sentry.SentryTraceHeader; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -@Deprecated -@ApiStatus.Internal -public final class TraceData { - - private final @NotNull String traceId; - private final @NotNull String spanId; - private final @Nullable String parentSpanId; - private final @Nullable SentryTraceHeader sentryTraceHeader; - private final @Nullable Baggage baggage; - - public TraceData( - @NotNull final String traceId, - @NotNull final String spanId, - @Nullable final String parentSpanId, - @Nullable final SentryTraceHeader sentryTraceHeader, - @Nullable final Baggage baggage) { - this.traceId = traceId; - this.spanId = spanId; - this.parentSpanId = parentSpanId; - this.sentryTraceHeader = sentryTraceHeader; - this.baggage = baggage; - } - - public @NotNull String getTraceId() { - return traceId; - } - - public @NotNull String getSpanId() { - return spanId; - } - - public @Nullable String getParentSpanId() { - return parentSpanId; - } - - public @Nullable SentryTraceHeader getSentryTraceHeader() { - return sentryTraceHeader; - } - - public @Nullable Baggage getBaggage() { - return baggage; - } -} diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/test/kotlin/SentryPropagatorTest.kt b/sentry-opentelemetry/sentry-opentelemetry-core/src/test/kotlin/SentryPropagatorTest.kt deleted file mode 100644 index 29e820acff0..00000000000 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/test/kotlin/SentryPropagatorTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package io.sentry.opentelemetry - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.context.Context -import io.sentry.Sentry -import io.sentry.opentelemetry.SentryOtelKeys.SENTRY_BAGGAGE_KEY -import io.sentry.opentelemetry.SentryOtelKeys.SENTRY_TRACE_KEY -import kotlin.test.AfterTest -import kotlin.test.BeforeTest -import kotlin.test.Test -import kotlin.test.assertFalse -import kotlin.test.assertNull - -class SentryPropagatorTest { - - @BeforeTest - fun setup() { - Sentry.init("https://key@sentry.io/proj") - } - - @AfterTest - fun teardown() { - Sentry.close() - Context.root().makeCurrent() - } - - @Suppress("DEPRECATION") - @Test - fun `ignores incoming headers when strict continuation rejects org id`() { - Sentry.init { options -> - options.dsn = "https://key@o2.ingest.sentry.io/123" - options.isStrictTraceContinuation = true - } - - val propagator = SentryPropagator() - val carrier: Map = - mapOf( - "sentry-trace" to "f9118105af4a2d42b4124532cd1065ff-424cffc8f94feeee-1", - "baggage" to "sentry-trace_id=f9118105af4a2d42b4124532cd1065ff,sentry-org_id=1", - ) - - val newContext = propagator.extract(Context.root(), carrier, MapGetter()) - - assertFalse(Span.fromContext(newContext).spanContext.isValid) - assertNull(newContext.get(SENTRY_TRACE_KEY)) - assertNull(newContext.get(SENTRY_BAGGAGE_KEY)) - } -} diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/src/test/kotlin/SentrySpanProcessorTest.kt b/sentry-opentelemetry/sentry-opentelemetry-core/src/test/kotlin/SentrySpanProcessorTest.kt deleted file mode 100644 index df2cf9596dd..00000000000 --- a/sentry-opentelemetry/sentry-opentelemetry-core/src/test/kotlin/SentrySpanProcessorTest.kt +++ /dev/null @@ -1,525 +0,0 @@ -package io.sentry.opentelemetry - -import io.opentelemetry.api.OpenTelemetry -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.SpanBuilder -import io.opentelemetry.api.trace.SpanContext -import io.opentelemetry.api.trace.SpanId -import io.opentelemetry.api.trace.SpanKind -import io.opentelemetry.api.trace.StatusCode -import io.opentelemetry.api.trace.TraceId -import io.opentelemetry.api.trace.Tracer -import io.opentelemetry.context.Context -import io.opentelemetry.context.propagation.ContextPropagators -import io.opentelemetry.context.propagation.TextMapGetter -import io.opentelemetry.context.propagation.TextMapSetter -import io.opentelemetry.sdk.OpenTelemetrySdk -import io.opentelemetry.sdk.trace.ReadWriteSpan -import io.opentelemetry.sdk.trace.ReadableSpan -import io.opentelemetry.sdk.trace.SdkTracerProvider -import io.opentelemetry.semconv.HttpAttributes -import io.opentelemetry.semconv.UrlAttributes -import io.sentry.Baggage -import io.sentry.BaggageHeader -import io.sentry.Hint -import io.sentry.IScopes -import io.sentry.ISpan -import io.sentry.ITransaction -import io.sentry.Instrumenter -import io.sentry.SentryDate -import io.sentry.SentryEvent -import io.sentry.SentryOptions -import io.sentry.SentryTraceHeader -import io.sentry.SpanOptions -import io.sentry.SpanStatus -import io.sentry.TransactionContext -import io.sentry.TransactionOptions -import io.sentry.protocol.TransactionNameSource -import java.net.http.HttpHeaders -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNotEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull -import kotlin.test.assertTrue -import org.mockito.kotlin.any -import org.mockito.kotlin.anyOrNull -import org.mockito.kotlin.check -import org.mockito.kotlin.eq -import org.mockito.kotlin.mock -import org.mockito.kotlin.never -import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyNoInteractions -import org.mockito.kotlin.verifyNoMoreInteractions -import org.mockito.kotlin.whenever - -class SentrySpanProcessorTest { - - companion object { - val SENTRY_TRACE_HEADER_STRING = "2722d9f6ec019ade60c776169d9a8904-cedf5b7571cb4972-1" - val BAGGAGE_HEADER_STRING = - "sentry-public_key=502f25099c204a2fbf4cb16edc5975d1,sentry-sample_rate=1,sentry-trace_id=2722d9f6ec019ade60c776169d9a8904,sentry-transaction=HTTP%20GET" - } - - private class Fixture { - - val options = - SentryOptions().also { - it.dsn = "https://key@sentry.io/proj" - it.instrumenter = Instrumenter.OTEL - } - val scopes = mock() - val transaction = mock() - val span = mock() - val spanContext = mock() - lateinit var openTelemetry: OpenTelemetry - lateinit var tracer: Tracer - val sentryTrace = SentryTraceHeader(SENTRY_TRACE_HEADER_STRING) - val baggage = Baggage.fromHeader(BAGGAGE_HEADER_STRING) - - fun setup() { - whenever(scopes.isEnabled).thenReturn(true) - whenever(scopes.options).thenReturn(options) - whenever(scopes.startTransaction(any(), any())) - .thenReturn(transaction) - - whenever(spanContext.operation).thenReturn("spanContextOp") - whenever(spanContext.parentSpanId).thenReturn(io.sentry.SpanId("cedf5b7571cb4972")) - - whenever(transaction.spanContext).thenReturn(spanContext) - whenever(span.spanContext).thenReturn(spanContext) - whenever(span.toSentryTrace()).thenReturn(sentryTrace) - whenever(transaction.toSentryTrace()).thenReturn(sentryTrace) - - val baggageHeader = BaggageHeader.fromBaggageAndOutgoingHeader(baggage, null) - whenever(span.toBaggageHeader(any())).thenReturn(baggageHeader) - whenever(transaction.toBaggageHeader(any())).thenReturn(baggageHeader) - - whenever( - transaction.startChild( - any(), - anyOrNull(), - anyOrNull(), - eq(Instrumenter.OTEL), - any(), - ) - ) - .thenReturn(span) - - val sdkTracerProvider = - SdkTracerProvider.builder().addSpanProcessor(SentrySpanProcessor(scopes)).build() - - openTelemetry = - OpenTelemetrySdk.builder() - .setTracerProvider(sdkTracerProvider) - .setPropagators(ContextPropagators.create(SentryPropagator())) - .build() - - tracer = openTelemetry.getTracer("sentry-test") - } - } - - private val fixture = Fixture() - - @Test - fun `requires start`() { - val processor = SentrySpanProcessor() - assertTrue(processor.isStartRequired) - } - - @Test - fun `requires end`() { - val processor = SentrySpanProcessor() - assertTrue(processor.isEndRequired) - } - - @Test - fun `ignores sentry client request`() { - fixture.setup() - givenSpanBuilder(SpanKind.CLIENT) - .setAttribute(UrlAttributes.URL_FULL, "https://key@sentry.io/proj/some-api") - .startSpan() - - thenNoTransactionIsStarted() - } - - @Test - fun `ignores sentry internal request`() { - fixture.setup() - givenSpanBuilder(SpanKind.CLIENT) - .setAttribute(UrlAttributes.URL_FULL, "https://key@sentry.io/proj/some-api") - .startSpan() - - thenNoTransactionIsStarted() - } - - @Test - fun `does nothing on start if Sentry has not been initialized`() { - fixture.setup() - val context = mock() - val span = mock() - - whenever(fixture.scopes.isEnabled).thenReturn(false) - - SentrySpanProcessor(fixture.scopes).onStart(context, span) - - verify(fixture.scopes).isEnabled - verify(fixture.scopes).options - verifyNoMoreInteractions(fixture.scopes) - verifyNoInteractions(context, span) - } - - @Test - fun `does nothing on end if Sentry has not been initialized`() { - fixture.setup() - val span = mock() - - whenever(fixture.scopes.isEnabled).thenReturn(false) - - SentrySpanProcessor(fixture.scopes).onEnd(span) - - verify(fixture.scopes).isEnabled - verify(fixture.scopes).options - verifyNoMoreInteractions(fixture.scopes) - verifyNoInteractions(span) - } - - @Test - fun `does not start transaction for invalid SpanId`() { - fixture.setup() - val mockSpan = mock() - val mockSpanContext = mock() - whenever(mockSpanContext.spanId).thenReturn(SpanId.getInvalid()) - whenever(mockSpan.spanContext).thenReturn(mockSpanContext) - SentrySpanProcessor(fixture.scopes).onStart(Context.current(), mockSpan) - thenNoTransactionIsStarted() - } - - @Test - fun `does not start transaction for invalid TraceId`() { - fixture.setup() - val mockSpan = mock() - val mockSpanContext = mock() - whenever(mockSpanContext.spanId).thenReturn(SpanId.fromBytes("seed".toByteArray())) - whenever(mockSpanContext.traceId).thenReturn(TraceId.getInvalid()) - whenever(mockSpan.spanContext).thenReturn(mockSpanContext) - SentrySpanProcessor(fixture.scopes).onStart(Context.current(), mockSpan) - thenNoTransactionIsStarted() - } - - @Test - fun `creates transaction for first otel span and span for second`() { - fixture.setup() - val otelSpan = givenSpanBuilder().startSpan() - thenTransactionIsStarted(otelSpan, isContinued = false) - - val otelChildSpan = givenSpanBuilder(SpanKind.CLIENT, parentSpan = otelSpan).startSpan() - thenChildSpanIsStarted() - - otelChildSpan.end() - thenChildSpanIsFinished() - - otelSpan.end() - thenTransactionIsFinished() - } - - private fun whenExtractingHeaders(sentryTrace: Boolean = true, baggage: Boolean = true): Context { - val headers = givenHeaders(sentryTrace, baggage) - return fixture.openTelemetry.propagators.textMapPropagator.extract( - Context.current(), - headers, - HeaderGetter(), - ) - } - - @Test - fun `propagator can extract and result is used for transaction and attached on inject`() { - fixture.setup() - val extractedContext = whenExtractingHeaders() - - extractedContext.makeCurrent().use { _ -> - val otelSpan = givenSpanBuilder().startSpan() - thenTraceIdIsUsed(otelSpan) - thenTransactionIsStarted(otelSpan, isContinued = true) - - val otelChildSpan = givenSpanBuilder(SpanKind.CLIENT, parentSpan = otelSpan).startSpan() - thenChildSpanIsStarted() - - val map = mutableMapOf() - fixture.openTelemetry.propagators.textMapPropagator.inject( - Context.current().with(otelSpan), - map, - TestSetter(), - ) - - assertTrue(map.isNotEmpty()) - assertEquals(SENTRY_TRACE_HEADER_STRING, map["sentry-trace"]) - assertEquals(BAGGAGE_HEADER_STRING, map["baggage"]) - - otelChildSpan.end() - thenChildSpanIsFinished() - - otelSpan.end() - thenTransactionIsFinished() - } - } - - @Test - fun `incoming baggage without sentry-trace is ignored`() { - fixture.setup() - val extractedContext = whenExtractingHeaders(sentryTrace = false, baggage = true) - - extractedContext.makeCurrent().use { _ -> - val otelSpan = givenSpanBuilder().startSpan() - thenTraceIdIsNotUsed(otelSpan) - thenTransactionIsStarted(otelSpan, isContinued = false) - - val otelChildSpan = givenSpanBuilder(SpanKind.CLIENT, parentSpan = otelSpan).startSpan() - thenChildSpanIsStarted() - - otelChildSpan.end() - thenChildSpanIsFinished() - - otelSpan.end() - thenTransactionIsFinished() - } - } - - @Test - fun `sentry-trace without baggage continues trace`() { - fixture.setup() - val extractedContext = whenExtractingHeaders(sentryTrace = true, baggage = false) - - extractedContext.makeCurrent().use { _ -> - val otelSpan = givenSpanBuilder().startSpan() - - thenTraceIdIsUsed(otelSpan) - thenTransactionIsStarted(otelSpan, isContinued = true, continuesWithFilledBaggage = false) - - val otelChildSpan = givenSpanBuilder(SpanKind.CLIENT, parentSpan = otelSpan).startSpan() - thenChildSpanIsStarted() - - otelChildSpan.end() - thenChildSpanIsFinished() - - otelSpan.end() - thenTransactionIsFinished() - } - } - - @Test - fun `sets status for errored span`() { - fixture.setup() - val otelSpan = givenSpanBuilder().startSpan() - thenTransactionIsStarted(otelSpan, isContinued = false) - - val otelChildSpan = givenSpanBuilder(SpanKind.CLIENT, parentSpan = otelSpan).startSpan() - thenChildSpanIsStarted() - - otelChildSpan.setStatus(StatusCode.ERROR) - otelChildSpan.setAttribute(UrlAttributes.URL_FULL, "http://github.com/getsentry/sentry-java") - otelChildSpan.setAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 404L) - - otelChildSpan.end() - thenChildSpanIsFinished(SpanStatus.NOT_FOUND) - - otelSpan.end() - thenTransactionIsFinished() - } - - @Test - fun `sets status for errored span if not http`() { - fixture.setup() - val otelSpan = givenSpanBuilder().startSpan() - thenTransactionIsStarted(otelSpan, isContinued = false) - - val otelChildSpan = givenSpanBuilder(SpanKind.CLIENT, parentSpan = otelSpan).startSpan() - thenChildSpanIsStarted() - - otelChildSpan.setStatus(StatusCode.ERROR) - - otelChildSpan.end() - thenChildSpanIsFinished(SpanStatus.UNKNOWN_ERROR) - - otelSpan.end() - thenTransactionIsFinished() - } - - @Test - fun `links error to OTEL transaction`() { - fixture.setup() - val extractedContext = whenExtractingHeaders() - - extractedContext.makeCurrent().use { _ -> - val otelSpan = givenSpanBuilder().startSpan() - thenTransactionIsStarted(otelSpan, isContinued = true) - - otelSpan.makeCurrent().use { _ -> - val processedEvent = - OpenTelemetryLinkErrorEventProcessor(fixture.scopes).process(SentryEvent(), Hint()) - val traceContext = processedEvent!!.contexts.trace!! - - assertEquals("2722d9f6ec019ade60c776169d9a8904", traceContext.traceId.toString()) - assertEquals(otelSpan.spanContext.spanId, traceContext.spanId.toString()) - assertEquals("cedf5b7571cb4972", traceContext.parentSpanId.toString()) - assertEquals("spanContextOp", traceContext.operation) - } - - otelSpan.end() - thenTransactionIsFinished() - } - } - - @Test - fun `does not link error to OTEL transaction if instrumenter does not match`() { - fixture.options.instrumenter = Instrumenter.SENTRY - fixture.setup() - - val processedEvent = - OpenTelemetryLinkErrorEventProcessor(fixture.scopes).process(SentryEvent(), Hint()) - - thenNoTraceContextHasBeenAddedToEvent(processedEvent) - } - - private fun givenSpanBuilder( - spanKind: SpanKind = SpanKind.SERVER, - parentSpan: Span? = null, - ): SpanBuilder { - val spanName = if (parentSpan == null) "testspan" else "childspan" - val spanBuilder = - fixture.tracer - .spanBuilder(spanName) - .setAttribute("some-attribute", "some-value") - .setSpanKind(spanKind) - - parentSpan?.let { spanBuilder.setParent(Context.current().with(parentSpan)) } - - return spanBuilder - } - - private fun givenHeaders(sentryTrace: Boolean = true, baggage: Boolean = true): HttpHeaders? { - val headerMap = - mutableMapOf>().also { - if (sentryTrace) { - it.put("sentry-trace", listOf(SENTRY_TRACE_HEADER_STRING)) - } - if (baggage) { - it.put("baggage", listOf(BAGGAGE_HEADER_STRING)) - } - } - - return HttpHeaders.of(headerMap) { _, _ -> true } - } - - private fun thenTransactionIsStarted( - otelSpan: Span, - isContinued: Boolean = false, - continuesWithFilledBaggage: Boolean = true, - ) { - if (isContinued) { - verify(fixture.scopes) - .startTransaction( - check { - assertEquals("testspan", it.name) - assertEquals(TransactionNameSource.CUSTOM, it.transactionNameSource) - assertEquals("testspan", it.operation) - assertEquals(otelSpan.spanContext.spanId, it.spanId.toString()) - assertEquals("2722d9f6ec019ade60c776169d9a8904", it.traceId.toString()) - assertEquals("cedf5b7571cb4972", it.parentSpanId?.toString()) - assertTrue(it.parentSamplingDecision!!.sampled) - if (continuesWithFilledBaggage) { - assertEquals("2722d9f6ec019ade60c776169d9a8904", it.baggage?.traceId) - assertEquals(1.0, it.baggage?.sampleRate) - assertEquals("HTTP GET", it.baggage?.transaction) - assertEquals("502f25099c204a2fbf4cb16edc5975d1", it.baggage?.publicKey) - assertFalse(it.baggage!!.isMutable) - } else { - assertNotNull(it.baggage) - assertNull(it.baggage?.traceId) - assertNull(it.baggage?.sampleRate) - assertNull(it.baggage?.transaction) - assertNull(it.baggage?.publicKey) - assertTrue(it.baggage!!.isMutable) - } - }, - check { - assertNotNull(it.startTimestamp) - assertFalse(it.isBindToScope) - }, - ) - } else { - verify(fixture.scopes) - .startTransaction( - check { - assertEquals("testspan", it.name) - assertEquals(TransactionNameSource.CUSTOM, it.transactionNameSource) - assertEquals("testspan", it.operation) - assertEquals(otelSpan.spanContext.spanId, it.spanId.toString()) - assertEquals(otelSpan.spanContext.traceId, it.traceId.toString()) - assertNull(it.parentSpanId) - assertNull(it.parentSamplingDecision) - assertNotNull(it.baggage) - }, - check { - assertNotNull(it.startTimestamp) - assertFalse(it.isBindToScope) - }, - ) - } - } - - private fun thenTraceIdIsUsed(otelSpan: Span) { - assertEquals("2722d9f6ec019ade60c776169d9a8904", otelSpan.spanContext.traceId) - } - - private fun thenTraceIdIsNotUsed(otelSpan: Span) { - assertNotEquals("2722d9f6ec019ade60c776169d9a8904", otelSpan.spanContext.traceId) - } - - private fun thenNoTransactionIsStarted() { - verify(fixture.scopes, never()) - .startTransaction(any(), any()) - } - - private fun thenChildSpanIsStarted() { - verify(fixture.transaction) - .startChild( - eq("childspan"), - eq("childspan"), - any(), - eq(Instrumenter.OTEL), - any(), - ) - } - - private fun thenChildSpanIsFinished(status: SpanStatus = SpanStatus.OK) { - verify(fixture.span).finish(eq(status), any()) - } - - private fun thenTransactionIsFinished() { - verify(fixture.transaction).setContext(eq("otel"), any()) - verify(fixture.transaction).finish(eq(SpanStatus.OK), any()) - } - - private fun thenNoTraceContextHasBeenAddedToEvent(event: SentryEvent?) { - assertNotNull(event) - assertNull(event.contexts.trace) - } -} - -class HeaderGetter : TextMapGetter { - override fun keys(headers: HttpHeaders): MutableIterable { - return headers.map().map { it.key }.toMutableList() - } - - override fun get(headers: HttpHeaders?, key: String): String? { - return headers?.firstValue(key)?.orElse(null) - } -} - -class TestSetter : TextMapSetter> { - override fun set(values: MutableMap?, key: String, value: String) { - values?.put(key, value) - } -} diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 2007edf00c9..597c6234136 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -4294,13 +4294,6 @@ public final class io/sentry/SentryReplayOptions$SentryReplayQuality : java/lang public static fun values ()[Lio/sentry/SentryReplayOptions$SentryReplayQuality; } -public final class io/sentry/SentrySpanStorage { - public fun get (Ljava/lang/String;)Lio/sentry/ISpan; - public static fun getInstance ()Lio/sentry/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/SentryStackTraceFactory { public fun (Lio/sentry/SentryOptions;)V public fun getInAppCallStack ()Ljava/util/List; diff --git a/sentry/src/main/java/io/sentry/SentrySpanStorage.java b/sentry/src/main/java/io/sentry/SentrySpanStorage.java deleted file mode 100644 index 56397971e59..00000000000 --- a/sentry/src/main/java/io/sentry/SentrySpanStorage.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.sentry; - -import io.sentry.util.AutoClosableReentrantLock; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Has been moved to `sentry` gradle module to include it in the bootstrap classloader without - * having to introduce yet another module for OpenTelemetry support. - * - * @deprecated please use SentryWeakSpanStorage (from sentry-opentelemetry-bootstrap) instead. - */ -@Deprecated -@ApiStatus.Internal -public final class SentrySpanStorage { - private static volatile @Nullable SentrySpanStorage INSTANCE; - private static final @NotNull AutoClosableReentrantLock staticLock = - new AutoClosableReentrantLock(); - - public static @NotNull SentrySpanStorage getInstance() { - if (INSTANCE == null) { - try (final @NotNull ISentryLifecycleToken ignored = staticLock.acquire()) { - if (INSTANCE == null) { - INSTANCE = new SentrySpanStorage(); - } - } - } - - return INSTANCE; - } - - private final @NotNull Map spans = new ConcurrentHashMap<>(); - - private SentrySpanStorage() {} - - public void store(final @NotNull String spanId, final @NotNull ISpan span) { - spans.put(spanId, span); - } - - public @Nullable ISpan get(final @Nullable String spanId) { - return spans.get(spanId); - } - - public @Nullable ISpan removeAndGet(final @Nullable String spanId) { - return spans.remove(spanId); - } -}