Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
305baf5
replace hub with scopes
adinauer Mar 27, 2024
95f5e1b
Add Scopes
adinauer Apr 2, 2024
27f2398
Introduce `IScopes` interface.
adinauer Apr 2, 2024
ce3c14f
Replace `IHub` with `IScopes` in core
adinauer Apr 2, 2024
ce615f4
Replace `IHub` with `IScopes` in android core
adinauer Apr 2, 2024
22ddc00
Replace `IHub` with `IScopes` in android integrations
adinauer Apr 2, 2024
305c217
Replace `IHub` with `IScopes` in apollo integrations
adinauer Apr 2, 2024
da927bc
Replace `IHub` with `IScopes` in okhttp integration
adinauer Apr 2, 2024
8279276
Replace `IHub` with `IScopes` in graphql integration
adinauer Apr 2, 2024
9bfc086
Replace `IHub` with `IScopes` in logging integrations
adinauer Apr 2, 2024
b998e50
Replace `IHub` with `IScopes` in more integrations
adinauer Apr 2, 2024
739827a
Replace `IHub` with `IScopes` in OTel integration
adinauer Apr 2, 2024
69f2d63
Replace `IHub` with `IScopes` in Spring 5 / Spring Boot 2 integrations
adinauer Apr 2, 2024
792d482
Replace `IHub` with `IScopes` in Spring 6 / Spring Boot 3 integrations
adinauer Apr 2, 2024
9bcbce6
Replace `IHub` with `IScopes` in samples
adinauer Apr 2, 2024
3f25a4b
Merge branch 'feat/hsm-13-replacements-in-samples' into feat/hubs-sco…
adinauer Apr 2, 2024
d6fb40a
gitscopes -> github
adinauer Apr 2, 2024
7752bcc
Replace ThreadLocal with ScopesStorage
adinauer Apr 4, 2024
1e329c5
Move client and throwable to span map to scope
adinauer Apr 4, 2024
b0d89ae
Add global scope
adinauer Apr 4, 2024
cdd414a
use global scope in Scopes
adinauer Apr 4, 2024
98da9ff
Implement pushScope popScope and withScope for Scopes
adinauer Apr 4, 2024
2d26033
Add pushIsolationScope; add fork methods to ISCope
adinauer Apr 12, 2024
bbb6700
Use separate scopes for current, isolation and global scope; rename m…
adinauer Apr 12, 2024
c714b21
Allow controlling which scope configureScope uses
adinauer Apr 12, 2024
a474402
Combine scopes
adinauer Apr 12, 2024
ae93e33
Use new API for CRONS integrations
adinauer Apr 12, 2024
b01298b
Add lifecycle helper
adinauer Apr 12, 2024
b64e688
Change spring integrations to use new API
adinauer Apr 12, 2024
d06fc50
Use new API in servlet integrations
adinauer Apr 12, 2024
f0af5c3
Use new API for kotlin coroutines and wrapers for Supplier/Callable
adinauer Apr 12, 2024
2f02001
Discussion TODOs
adinauer Apr 12, 2024
bf4a7bf
Fix breadcrumb ordering
adinauer Apr 15, 2024
62cb91a
Mark TODOS with [HSM]
adinauer Apr 15, 2024
b1630ea
Add getGlobalScope and forkedRootScopes to IScopes
adinauer Apr 16, 2024
136b9ce
Fix EventProcessor ordering on scopes
adinauer Apr 16, 2024
94d54ef
Reuse code in Scopes
adinauer Apr 16, 2024
017599d
No longer replace global scope
adinauer Apr 16, 2024
f4c2b3c
Replace hub occurrences in comments, var names etc.
adinauer Apr 16, 2024
61c9d4a
Implement ScopesTest
adinauer Apr 18, 2024
04f3892
Implement CombinedScopeViewTest
adinauer Apr 18, 2024
840c194
Fix combined contexts
adinauer Apr 19, 2024
ab1c3a6
Use combined scopes for cross platform
adinauer Apr 19, 2024
23506c5
Changes according to reviews of previous PRs
adinauer Apr 23, 2024
c9b6f8b
more
adinauer Apr 23, 2024
696a809
even more
adinauer Apr 23, 2024
847200d
isEnabled checks client instead of having a property on Scopes
adinauer Apr 24, 2024
8e86d3b
Use SentryOptions.empty
adinauer Apr 25, 2024
06db228
Remove Hub
adinauer Apr 25, 2024
37ab4d0
Use OpenTelemetry for Performance and Scopes propagation
adinauer Apr 30, 2024
faef2f8
Promote certain span attributes
adinauer May 2, 2024
c57b2d3
Merge branch '8.x.x' into feat/potel-1-context-forking-and-basics
adinauer May 3, 2024
5b15128
Merge branch '8.x.x' into feat/potel-1-context-forking-and-basics
adinauer May 7, 2024
9d48538
Merge branch 'feat/potel-1-context-forking-and-basics' into feat/pote…
adinauer May 7, 2024
9b900c7
Use OTel in Sentry API
adinauer May 13, 2024
b3919bd
Deduplicate SpanInfo extraction
adinauer May 15, 2024
36ed84a
Forward Sentry API to Sentry through OTel
adinauer May 22, 2024
8f56e3f
Use OTel status for Sentry span API
adinauer May 23, 2024
81982bc
POTel Tracing
adinauer May 28, 2024
fba451c
fix root span detection (remote flag), and scope closing
adinauer May 29, 2024
fc64f13
Merge branch '8.x.x' into feat/potel-7-tracing
adinauer Jun 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
public final class io/sentry/opentelemetry/InternalSemanticAttributes {
public static final field BREADCRUMB_TYPE Lio/opentelemetry/api/common/AttributeKey;
public static final field IS_REMOTE_PARENT Lio/opentelemetry/api/common/AttributeKey;
public static final field OP Lio/opentelemetry/api/common/AttributeKey;
public static final field ORIGIN Lio/opentelemetry/api/common/AttributeKey;
public static final field PARENT_SAMPLED Lio/opentelemetry/api/common/AttributeKey;
public static final field PROFILE_SAMPLED Lio/opentelemetry/api/common/AttributeKey;
public static final field PROFILE_SAMPLE_RATE Lio/opentelemetry/api/common/AttributeKey;
public static final field SAMPLED Lio/opentelemetry/api/common/AttributeKey;
public static final field SAMPLE_RATE Lio/opentelemetry/api/common/AttributeKey;
public static final field SOURCE Lio/opentelemetry/api/common/AttributeKey;
public fun <init> ()V
}

Expand All @@ -17,20 +16,21 @@ public final class io/sentry/opentelemetry/OtelContextScopesStorage : io/sentry/
}

public final class io/sentry/opentelemetry/OtelSpanContext : io/sentry/SpanContext {
public fun <init> (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/opentelemetry/api/trace/Span;)V
public fun <init> (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/OtelSpanWrapper;)V
public fun getStatus ()Lio/sentry/SpanStatus;
public fun setStatus (Lio/sentry/SpanStatus;)V
}

public final class io/sentry/opentelemetry/OtelSpanFactory : io/sentry/ISpanFactory {
public fun <init> ()V
public fun createSpan (Ljava/lang/String;Ljava/lang/String;Lio/sentry/IScopes;Lio/sentry/SpanOptions;Lio/sentry/ISpan;)Lio/sentry/ISpan;
public fun createSpan (Ljava/lang/String;Ljava/lang/String;Lio/sentry/IScopes;Lio/sentry/SpanOptions;Lio/sentry/SpanContext;Lio/sentry/ISpan;)Lio/sentry/ISpan;
public fun createTransaction (Lio/sentry/TransactionContext;Lio/sentry/IScopes;Lio/sentry/TransactionOptions;Lio/sentry/TransactionPerformanceCollector;)Lio/sentry/ITransaction;
public fun retrieveCurrentSpan (Lio/sentry/IScope;)Lio/sentry/ISpan;
public fun retrieveCurrentSpan (Lio/sentry/IScopes;)Lio/sentry/ISpan;
}

public final class io/sentry/opentelemetry/OtelSpanWrapper : io/sentry/ISpan {
public fun <init> (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/IScopes;Lio/sentry/SentryDate;Lio/opentelemetry/api/trace/Span;)V
public fun <init> (Lio/opentelemetry/sdk/trace/ReadWriteSpan;Lio/sentry/IScopes;Lio/sentry/SentryDate;Lio/sentry/TracesSamplingDecision;Lio/sentry/opentelemetry/OtelSpanWrapper;)V
public fun finish ()V
public fun finish (Lio/sentry/SpanStatus;)V
public fun finish (Lio/sentry/SpanStatus;Lio/sentry/SentryDate;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@

// TODO [POTEL] context key vs attribute key
public final class InternalSemanticAttributes {
public static final AttributeKey<String> ORIGIN = AttributeKey.stringKey("sentry.origin");
public static final AttributeKey<String> OP = AttributeKey.stringKey("sentry.op");
public static final AttributeKey<String> SOURCE = AttributeKey.stringKey("sentry.source");
// public static final AttributeKey<String> ORIGIN = AttributeKey.stringKey("sentry.origin");
// public static final AttributeKey<String> OP = AttributeKey.stringKey("sentry.op");
// public static final AttributeKey<String> SOURCE = AttributeKey.stringKey("sentry.source");
public static final AttributeKey<Boolean> SAMPLED = AttributeKey.booleanKey("sentry.sampled");
public static final AttributeKey<Double> SAMPLE_RATE =
AttributeKey.doubleKey("sentry.sample_rate");
public static final AttributeKey<Boolean> PARENT_SAMPLED =
AttributeKey.booleanKey("sentry.parentSampled");
AttributeKey.booleanKey("sentry.parent_sampled");
public static final AttributeKey<Boolean> PROFILE_SAMPLED =
AttributeKey.booleanKey("sentry.profile_sampled");
public static final AttributeKey<Double> PROFILE_SAMPLE_RATE =
AttributeKey.doubleKey("sentry.profile_sample_rate");
public static final AttributeKey<Boolean> IS_REMOTE_PARENT =
AttributeKey.booleanKey("sentry.isParentRemote");
public static final AttributeKey<String> BREADCRUMB_TYPE =
AttributeKey.stringKey("sentry.breadcrumb.type");
AttributeKey.booleanKey("sentry.is_remote_parent");
// public static final AttributeKey<String> BREADCRUMB_TYPE =
// AttributeKey.stringKey("sentry.breadcrumb.type");
// public static final AttributeKey<SentryLevel> BREADCRUMB_TYPE =
// InternalAttributeKeyImpl.create("sentry.breadcrumb.type", SentryLevel.class);
// BREADCRUMB_TYPE("sentry.breadcrumb.type"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.sentry.SpanContext;
import io.sentry.SpanId;
import io.sentry.SpanStatus;
import io.sentry.TracesSamplingDecision;
import io.sentry.protocol.SentryId;
import java.lang.ref.WeakReference;
import org.jetbrains.annotations.NotNull;
Expand All @@ -22,15 +23,19 @@ public final class OtelSpanContext extends SpanContext {
*/
private final @NotNull WeakReference<ReadWriteSpan> span;

public OtelSpanContext(final @NotNull ReadWriteSpan span, final @Nullable Span parentSpan) {
// TODO [POTEL] tracesSamplingDecision
public OtelSpanContext(
final @NotNull ReadWriteSpan span,
final @Nullable TracesSamplingDecision samplingDecision,
final @Nullable OtelSpanWrapper parentSpan) {
super(
new SentryId(span.getSpanContext().getTraceId()),
new SpanId(span.getSpanContext().getSpanId()),
parentSpan == null ? null : new SpanId(parentSpan.getSpanContext().getSpanId()),
parentSpan == null ? null : parentSpan.getSpanContext().getSpanId(),
span.getName(),
null,
null,
samplingDecision != null
? samplingDecision
: (parentSpan == null ? null : parentSpan.getSamplingDecision()),
null,
null);
this.span = new WeakReference<>(span);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.api.trace.TraceState;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.sentry.IScope;
import io.sentry.IScopes;
import io.sentry.ISpan;
import io.sentry.ISpanFactory;
import io.sentry.ITransaction;
import io.sentry.NoOpSpan;
import io.sentry.NoOpTransaction;
import io.sentry.SentryDate;
import io.sentry.SpanContext;
import io.sentry.SpanId;
import io.sentry.SpanOptions;
import io.sentry.TracesSamplingDecision;
import io.sentry.TransactionContext;
import io.sentry.TransactionOptions;
import io.sentry.TransactionPerformanceCollector;
import io.sentry.protocol.SentryId;
import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
Expand All @@ -34,7 +41,13 @@ public final class OtelSpanFactory implements ISpanFactory {
@Nullable TransactionPerformanceCollector transactionPerformanceCollector) {
final @Nullable OtelSpanWrapper span =
createSpanInternal(
context.getName(), context.getDescription(), scopes, transactionOptions, null);
context.getName(),
context.getDescription(),
scopes,
transactionOptions,
null,
context.getSamplingDecision(),
context);
if (span == null) {
return NoOpTransaction.getInstance();
}
Expand All @@ -47,9 +60,13 @@ public final class OtelSpanFactory implements ISpanFactory {
final @Nullable String description,
final @NotNull IScopes scopes,
final @NotNull SpanOptions spanOptions,
final @NotNull SpanContext spanContext,
final @Nullable ISpan parentSpan) {
final @Nullable TracesSamplingDecision samplingDecision =
parentSpan == null ? null : parentSpan.getSamplingDecision();
final @Nullable OtelSpanWrapper span =
createSpanInternal(name, description, scopes, spanOptions, parentSpan);
createSpanInternal(
name, description, scopes, spanOptions, parentSpan, samplingDecision, spanContext);
if (span == null) {
return NoOpSpan.getInstance();
}
Expand All @@ -61,29 +78,72 @@ public final class OtelSpanFactory implements ISpanFactory {
final @Nullable String description,
final @NotNull IScopes scopes,
final @NotNull SpanOptions spanOptions,
final @Nullable ISpan parentSpan) {
final @Nullable ISpan parentSpan,
final @Nullable TracesSamplingDecision samplingDecision,
final @NotNull SpanContext spanContext) {
final @NotNull SpanBuilder spanBuilder = getTracer().spanBuilder(name);
// TODO [POTEL] If performance is disabled, can we use otel.SamplingDecision.RECORD_ONLY to
// still allow otel to be used for tracing
if (parentSpan == null) {
spanBuilder.setNoParent();
final @NotNull SentryId traceId = spanContext.getTraceId();
final @Nullable SpanId parentSpanId = spanContext.getParentSpanId();
if (parentSpanId == null) {
final @NotNull io.opentelemetry.api.trace.SpanContext otelSpanContext =
io.opentelemetry.api.trace.SpanContext.create(
traceId.toString(),
io.opentelemetry.api.trace.SpanId.getInvalid(),
TraceFlags.getSampled(),
TraceState.getDefault());
final @NotNull Span wrappedSpan = Span.wrap(otelSpanContext);
spanBuilder.setParent(Context.root().with(wrappedSpan));
} else {
final @NotNull io.opentelemetry.api.trace.SpanContext otelSpanContext =
io.opentelemetry.api.trace.SpanContext.createFromRemoteParent(
traceId.toString(),
parentSpanId.toString(),
TraceFlags.getSampled(),
TraceState.getDefault());
final @NotNull Span wrappedSpan = Span.wrap(otelSpanContext);
spanBuilder.setParent(Context.root().with(wrappedSpan));
}
} else {
if (parentSpan instanceof OtelSpanWrapper) {
// TODO [POTEL] retrieve context from span
// spanBuilder.setParent()
}
}

// TODO [POTEL] send baggage in (note: won't go through propagators)

final @Nullable SentryDate startTimestampFromOptions = spanOptions.getStartTimestamp();
final @NotNull SentryDate startTimestamp =
startTimestampFromOptions == null
? scopes.getOptions().getDateProvider().now()
: startTimestampFromOptions;
spanBuilder.setStartTimestamp(startTimestamp.nanoTimestamp(), TimeUnit.NANOSECONDS);

if (samplingDecision != null) {
spanBuilder.setAttribute(InternalSemanticAttributes.SAMPLED, samplingDecision.getSampled());
spanBuilder.setAttribute(
InternalSemanticAttributes.SAMPLE_RATE, samplingDecision.getSampleRate());
spanBuilder.setAttribute(
InternalSemanticAttributes.PROFILE_SAMPLED, samplingDecision.getProfileSampled());
spanBuilder.setAttribute(
InternalSemanticAttributes.PROFILE_SAMPLE_RATE, samplingDecision.getProfileSampleRate());
}

final @NotNull Span otelSpan = spanBuilder.startSpan();

final @Nullable OtelSpanWrapper sentrySpan = storage.getSentrySpan(otelSpan.getSpanContext());
if (sentrySpan != null && description != null) {
sentrySpan.setDescription(description);
if (sentrySpan != null) {
if (description != null) {
sentrySpan.setDescription(description);
}
if (samplingDecision != null) {
sentrySpan.getSpanContext().setSamplingDecision(samplingDecision);
}
}

return sentrySpan;
}

Expand All @@ -96,6 +156,15 @@ public final class OtelSpanFactory implements ISpanFactory {
return storage.getSentrySpan(span.getSpanContext());
}

@Override
public @Nullable ISpan retrieveCurrentSpan(IScope scope) {
final @Nullable Span span = Span.fromContextOrNull(Context.current());
if (span == null) {
return null;
}
return storage.getSentrySpan(span.getSpanContext());
}

private @NotNull Tracer getTracer() {
return GlobalOpenTelemetry.getTracer(
"sentry-instrumentation-scope-name", "sentry-instrumentation-scope-version");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import io.sentry.util.LazyEvaluator;
import io.sentry.util.Objects;
import java.lang.ref.WeakReference;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -74,15 +76,18 @@ public final class OtelSpanWrapper implements ISpan {
/** A throwable thrown during the execution of the span. */
private @Nullable Throwable throwable;

private @NotNull Deque<ISentryLifecycleToken> tokensToCleanup = new ArrayDeque<>(1);

public OtelSpanWrapper(
final @NotNull ReadWriteSpan span,
final @NotNull IScopes scopes,
final @NotNull SentryDate startTimestamp,
final @Nullable Span parentSpan) {
final @Nullable TracesSamplingDecision samplingDecision,
final @Nullable OtelSpanWrapper parentSpan) {
this.scopes = Objects.requireNonNull(scopes, "scopes are required");
this.span = new WeakReference<>(span);
this.startTimestamp = startTimestamp;
this.context = new OtelSpanContext(span, parentSpan);
this.context = new OtelSpanContext(span, samplingDecision, parentSpan);
}

@Override
Expand All @@ -100,7 +105,7 @@ public OtelSpanWrapper(
return scopes
.getOptions()
.getSpanFactory()
.createSpan(operation, description, scopes, spanOptions, this);
.createSpan(operation, description, scopes, spanOptions, context, this);
}

@Override
Expand Down Expand Up @@ -131,7 +136,7 @@ public OtelSpanWrapper(
return scopes
.getOptions()
.getSpanFactory()
.createSpan(operation, description, scopes, spanOptions, this);
.createSpan(operation, description, scopes, spanOptions, context, this);
}

@Override
Expand All @@ -143,7 +148,7 @@ public OtelSpanWrapper(
return scopes
.getOptions()
.getSpanFactory()
.createSpan(operation, description, scopes, new SpanOptions(), this);
.createSpan(operation, description, scopes, new SpanOptions(), context, this);
}

@Override
Expand Down Expand Up @@ -185,6 +190,10 @@ public void finish(@Nullable SpanStatus status) {
if (otelSpan != null) {
otelSpan.end();
}

for (ISentryLifecycleToken token : tokensToCleanup) {
token.close();
}
}

@Override
Expand Down Expand Up @@ -425,12 +434,19 @@ public Map<String, MeasurementValue> getMeasurements() {
}

@SuppressWarnings("MustBeClosedChecker")
@ApiStatus.Internal
@Override
public @NotNull ISentryLifecycleToken makeCurrent() {
final @Nullable Span otelSpan = getSpan();
if (otelSpan != null) {
final @NotNull Scope otelScope = otelSpan.makeCurrent();
return new OtelContextSpanStorageToken(otelScope);
// TODO [POTEL] should we keep an ordered list of otel scopes and close them in reverse order
// on finish?
// TODO [POTEL] should we make transaction/span implement ISentryLifecycleToken instead?
final @NotNull OtelContextSpanStorageToken token = new OtelContextSpanStorageToken(otelScope);
// to iterate LIFO when closing
tokensToCleanup.addFirst(token);
return token;
}
return NoOpScopesStorage.NoOpScopesLifecycleToken.getInstance();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ public boolean isNoOp() {
return rootSpan.getEventId();
}

@ApiStatus.Internal
@Override
public @NotNull ISentryLifecycleToken makeCurrent() {
return rootSpan.makeCurrent();
Expand Down
Loading