Skip to content

Commit e3d2723

Browse files
authored
Merge f15dbbb into 5b790bc
2 parents 5b790bc + f15dbbb commit e3d2723

File tree

10 files changed

+94
-2
lines changed

10 files changed

+94
-2
lines changed

sentry-opentelemetry/sentry-opentelemetry-bootstrap/api/sentry-opentelemetry-bootstrap.api

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
public abstract interface class io/sentry/opentelemetry/IOtelSpanWrapper : io/sentry/ISpan {
22
public abstract fun getData ()Ljava/util/Map;
33
public abstract fun getMeasurements ()Ljava/util/Map;
4+
public abstract fun getOpenTelemetrySpan ()Lio/opentelemetry/api/trace/Span;
45
public abstract fun getOpenTelemetrySpanAttributes ()Lio/opentelemetry/api/common/Attributes;
56
public abstract fun getScopes ()Lio/sentry/IScopes;
67
public abstract fun getTags ()Ljava/util/Map;
78
public abstract fun getTraceId ()Lio/sentry/protocol/SentryId;
89
public abstract fun getTransactionName ()Ljava/lang/String;
910
public abstract fun getTransactionNameSource ()Lio/sentry/protocol/TransactionNameSource;
1011
public abstract fun isProfileSampled ()Ljava/lang/Boolean;
12+
public abstract fun isRoot ()Z
1113
public abstract fun setTransactionName (Ljava/lang/String;)V
1214
public abstract fun setTransactionName (Ljava/lang/String;Lio/sentry/protocol/TransactionNameSource;)V
1315
public abstract fun storeInContext (Lio/opentelemetry/context/Context;)Lio/opentelemetry/context/Context;
@@ -52,6 +54,7 @@ public final class io/sentry/opentelemetry/OtelStrongRefSpanWrapper : io/sentry/
5254
public fun getDescription ()Ljava/lang/String;
5355
public fun getFinishDate ()Lio/sentry/SentryDate;
5456
public fun getMeasurements ()Ljava/util/Map;
57+
public fun getOpenTelemetrySpan ()Lio/opentelemetry/api/trace/Span;
5558
public fun getOpenTelemetrySpanAttributes ()Lio/opentelemetry/api/common/Attributes;
5659
public fun getOperation ()Ljava/lang/String;
5760
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
@@ -68,6 +71,7 @@ public final class io/sentry/opentelemetry/OtelStrongRefSpanWrapper : io/sentry/
6871
public fun isFinished ()Z
6972
public fun isNoOp ()Z
7073
public fun isProfileSampled ()Ljava/lang/Boolean;
74+
public fun isRoot ()Z
7175
public fun isSampled ()Ljava/lang/Boolean;
7276
public fun makeCurrent ()Lio/sentry/ISentryLifecycleToken;
7377
public fun setContext (Ljava/lang/String;Ljava/lang/Object;)V
@@ -151,6 +155,7 @@ public final class io/sentry/opentelemetry/SentryContextStorage : io/opentelemet
151155
public fun <init> (Lio/opentelemetry/context/ContextStorage;)V
152156
public fun attach (Lio/opentelemetry/context/Context;)Lio/opentelemetry/context/Scope;
153157
public fun current ()Lio/opentelemetry/context/Context;
158+
public fun root ()Lio/opentelemetry/context/Context;
154159
}
155160

156161
public final class io/sentry/opentelemetry/SentryContextStorageProvider : io/opentelemetry/context/ContextStorageProvider {
@@ -181,6 +186,7 @@ public final class io/sentry/opentelemetry/SentryOtelThreadLocalStorage : io/ope
181186
public final class io/sentry/opentelemetry/SentryWeakSpanStorage {
182187
public fun clear ()V
183188
public static fun getInstance ()Lio/sentry/opentelemetry/SentryWeakSpanStorage;
189+
public fun getLastKnownUnfinishedRootSpan ()Lio/sentry/opentelemetry/IOtelSpanWrapper;
184190
public fun getSentrySpan (Lio/opentelemetry/api/trace/SpanContext;)Lio/sentry/opentelemetry/IOtelSpanWrapper;
185191
public fun storeSentrySpan (Lio/opentelemetry/api/trace/SpanContext;Lio/sentry/opentelemetry/IOtelSpanWrapper;)V
186192
}

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/IOtelSpanWrapper.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.sentry.opentelemetry;
22

33
import io.opentelemetry.api.common.Attributes;
4+
import io.opentelemetry.api.trace.Span;
45
import io.opentelemetry.context.Context;
56
import io.sentry.IScopes;
67
import io.sentry.ISpan;
@@ -52,4 +53,9 @@ public interface IOtelSpanWrapper extends ISpan {
5253
@ApiStatus.Internal
5354
@Nullable
5455
Attributes getOpenTelemetrySpanAttributes();
56+
57+
boolean isRoot();
58+
59+
@Nullable
60+
Span getOpenTelemetrySpan();
5561
}

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelStrongRefSpanWrapper.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,14 @@ public void setContext(@Nullable String key, @Nullable Object context) {
310310
public @Nullable Attributes getOpenTelemetrySpanAttributes() {
311311
return delegate.getOpenTelemetrySpanAttributes();
312312
}
313+
314+
@Override
315+
public boolean isRoot() {
316+
return delegate.isRoot();
317+
}
318+
319+
@Override
320+
public @Nullable Span getOpenTelemetrySpan() {
321+
return delegate.getOpenTelemetrySpan();
322+
}
313323
}

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryContextStorage.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.opentelemetry.context.Context;
44
import io.opentelemetry.context.ContextStorage;
55
import io.opentelemetry.context.Scope;
6+
import io.sentry.Sentry;
67
import org.jetbrains.annotations.ApiStatus;
78
import org.jetbrains.annotations.NotNull;
89

@@ -38,4 +39,15 @@ public Scope attach(Context toAttach) {
3839
public Context current() {
3940
return contextStorage.current();
4041
}
42+
43+
@Override
44+
public Context root() {
45+
final @NotNull Context originalRoot = ContextStorage.super.root();
46+
47+
if (Sentry.isGlobalHubMode()) {
48+
return SentryContextWrapper.wrap(originalRoot);
49+
}
50+
51+
return originalRoot;
52+
}
4153
}

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryContextWrapper.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,27 @@ private SentryContextWrapper(final @NotNull Context delegate) {
2020
this.delegate = delegate;
2121
}
2222

23+
@SuppressWarnings("unchecked")
2324
@Override
24-
public <V> V get(final @NotNull ContextKey<V> contextKey) {
25-
return delegate.get(contextKey);
25+
public <V> @Nullable V get(final @NotNull ContextKey<V> contextKey) {
26+
V result = delegate.get(contextKey);
27+
if (Sentry.isGlobalHubMode()) {
28+
if (result == null
29+
|| (result instanceof Span && !((Span) result).getSpanContext().isValid())) {
30+
if (isOpentelemetrySpan(contextKey)) {
31+
IOtelSpanWrapper sentrySpan =
32+
SentryWeakSpanStorage.getInstance().getLastKnownUnfinishedRootSpan();
33+
if (sentrySpan != null) {
34+
try {
35+
return (V) sentrySpan.getOpenTelemetrySpan();
36+
} catch (Throwable t) {
37+
return result;
38+
}
39+
}
40+
}
41+
}
42+
}
43+
return result;
2644
}
2745

2846
@Override

sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryWeakSpanStorage.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.opentelemetry.context.internal.shaded.WeakConcurrentMap;
55
import io.sentry.ISentryLifecycleToken;
66
import io.sentry.util.AutoClosableReentrantLock;
7+
import java.lang.ref.WeakReference;
78
import org.jetbrains.annotations.ApiStatus;
89
import org.jetbrains.annotations.NotNull;
910
import org.jetbrains.annotations.Nullable;
@@ -34,6 +35,8 @@ public final class SentryWeakSpanStorage {
3435
// weak keys, spawns a thread to clean up values that have been garbage collected
3536
private final @NotNull WeakConcurrentMap<SpanContext, IOtelSpanWrapper> sentrySpans =
3637
new WeakConcurrentMap<>(true);
38+
private volatile @NotNull WeakReference<IOtelSpanWrapper> lastKnownRootSpan =
39+
new WeakReference<>(null);
3740

3841
private SentryWeakSpanStorage() {}
3942

@@ -44,6 +47,17 @@ private SentryWeakSpanStorage() {}
4447
public void storeSentrySpan(
4548
final @NotNull SpanContext otelSpan, final @NotNull IOtelSpanWrapper sentrySpan) {
4649
this.sentrySpans.put(otelSpan, sentrySpan);
50+
if (sentrySpan.isRoot()) {
51+
lastKnownRootSpan = new WeakReference<>(sentrySpan);
52+
}
53+
}
54+
55+
public @Nullable IOtelSpanWrapper getLastKnownUnfinishedRootSpan() {
56+
final @Nullable IOtelSpanWrapper span = lastKnownRootSpan.get();
57+
if (span != null && !span.isFinished()) {
58+
return span;
59+
}
60+
return null;
4761
}
4862

4963
@TestOnly

sentry-opentelemetry/sentry-opentelemetry-core/api/sentry-opentelemetry-core.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public final class io/sentry/opentelemetry/OtelSpanWrapper : io/sentry/opentelem
6161
public fun getDescription ()Ljava/lang/String;
6262
public fun getFinishDate ()Lio/sentry/SentryDate;
6363
public fun getMeasurements ()Ljava/util/Map;
64+
public fun getOpenTelemetrySpan ()Lio/opentelemetry/api/trace/Span;
6465
public fun getOpenTelemetrySpanAttributes ()Lio/opentelemetry/api/common/Attributes;
6566
public fun getOperation ()Ljava/lang/String;
6667
public fun getSamplingDecision ()Lio/sentry/TracesSamplingDecision;
@@ -77,6 +78,7 @@ public final class io/sentry/opentelemetry/OtelSpanWrapper : io/sentry/opentelem
7778
public fun isFinished ()Z
7879
public fun isNoOp ()Z
7980
public fun isProfileSampled ()Ljava/lang/Boolean;
81+
public fun isRoot ()Z
8082
public fun isSampled ()Ljava/lang/Boolean;
8183
public fun makeCurrent ()Lio/sentry/ISentryLifecycleToken;
8284
public fun setContext (Ljava/lang/String;Ljava/lang/Object;)V

sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OtelSpanWrapper.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,25 @@ public Map<String, MeasurementValue> getMeasurements() {
515515
}
516516
}
517517

518+
@Override
519+
public boolean isRoot() {
520+
if (context.getParentSpanId() == null) {
521+
return true;
522+
}
523+
524+
final @Nullable ReadWriteSpan readWriteSpan = span.get();
525+
if (readWriteSpan != null) {
526+
return readWriteSpan.getParentSpanContext().isRemote();
527+
}
528+
529+
return false;
530+
}
531+
532+
@Override
533+
public @Nullable Span getOpenTelemetrySpan() {
534+
return span.get();
535+
}
536+
518537
@SuppressWarnings("MustBeClosedChecker")
519538
@ApiStatus.Internal
520539
@Override

sentry/api/sentry.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,7 @@ public final class io/sentry/Sentry {
25292529
public static fun init (Ljava/lang/String;)V
25302530
public static fun isCrashedLastRun ()Ljava/lang/Boolean;
25312531
public static fun isEnabled ()Z
2532+
public static fun isGlobalHubMode ()Z
25322533
public static fun isHealthy ()Z
25332534
public static fun popScope ()V
25342535
public static fun pushIsolationScope ()Lio/sentry/ISentryLifecycleToken;

sentry/src/main/java/io/sentry/Sentry.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,4 +1225,8 @@ public interface OptionsConfiguration<T extends SentryOptions> {
12251225
public static @NotNull SentryId captureCheckIn(final @NotNull CheckIn checkIn) {
12261226
return getCurrentScopes().captureCheckIn(checkIn);
12271227
}
1228+
1229+
public static boolean isGlobalHubMode() {
1230+
return globalHubMode;
1231+
}
12281232
}

0 commit comments

Comments
 (0)