Skip to content

Commit 158d688

Browse files
authored
feat: Allow Hybrid SDK to setTrace (#4137)
1 parent 0584f7e commit 158d688

File tree

10 files changed

+102
-1
lines changed

10 files changed

+102
-1
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
### Features
4+
5+
- The SDK now automatically propagates the trace-context to the native layer. This allows to connect errors on different layers of the application. ([#4137](https://github.com/getsentry/sentry-java/pull/4137))
6+
7+
### Dependencies
8+
9+
- Bump Native SDK from v0.7.20 to v0.8.1 ([#4137](https://github.com/getsentry/sentry-java/pull/4137))
10+
- [changelog](https://github.com/getsentry/sentry-native/blob/master/CHANGELOG.md#0810)
11+
- [diff](https://github.com/getsentry/sentry-native/compare/v0.7.20...0.8.1)
12+
313
## 8.3.0
414

515
### Features

buildSrc/src/main/java/Config.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ object Config {
159159
val apolloKotlin = "com.apollographql.apollo3:apollo-runtime:3.8.2"
160160
val apolloKotlin4 = "com.apollographql.apollo:apollo-runtime:4.1.1"
161161

162-
val sentryNativeNdk = "io.sentry:sentry-native-ndk:0.7.20"
162+
val sentryNativeNdk = "io.sentry:sentry-native-ndk:0.8.1"
163163

164164
object OpenTelemetry {
165165
val otelVersion = "1.44.1"

sentry-android-core/api/sentry-android-core.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public final class io/sentry/android/core/InternalSentrySdk {
221221
public static fun getAppStartMeasurement ()Ljava/util/Map;
222222
public static fun getCurrentScope ()Lio/sentry/IScope;
223223
public static fun serializeScope (Landroid/content/Context;Lio/sentry/android/core/SentryAndroidOptions;Lio/sentry/IScope;)Ljava/util/Map;
224+
public static fun setTrace (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;)V
224225
}
225226

226227
public final class io/sentry/android/core/LoadClass : io/sentry/util/LoadClass {

sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

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

3+
import static io.sentry.Sentry.getCurrentScopes;
34
import static io.sentry.SentryLevel.DEBUG;
45
import static io.sentry.SentryLevel.INFO;
56
import static io.sentry.SentryLevel.WARNING;
@@ -13,6 +14,7 @@
1314
import io.sentry.IScopes;
1415
import io.sentry.ISerializer;
1516
import io.sentry.ObjectWriter;
17+
import io.sentry.PropagationContext;
1618
import io.sentry.ScopeType;
1719
import io.sentry.ScopesAdapter;
1820
import io.sentry.SentryEnvelope;
@@ -30,6 +32,7 @@
3032
import io.sentry.protocol.SentryId;
3133
import io.sentry.protocol.User;
3234
import io.sentry.util.MapObjectWriter;
35+
import io.sentry.util.TracingUtils;
3336
import java.io.ByteArrayInputStream;
3437
import java.io.File;
3538
import java.io.InputStream;
@@ -329,4 +332,22 @@ private static Session updateSession(
329332
});
330333
return sessionRef.get();
331334
}
335+
336+
/**
337+
* Allows a Hybrid SDK to set the trace on the native layer
338+
*
339+
* @param traceId the trace ID
340+
* @param spanId the trace origin's span ID
341+
* @param sampleRate the sample rate used by the origin of the trace
342+
* @param sampleRand the random value used to sample with by the origin of the trace
343+
*/
344+
public static void setTrace(
345+
final @NotNull String traceId,
346+
final @NotNull String spanId,
347+
final @Nullable Double sampleRate,
348+
final @Nullable Double sampleRand) {
349+
TracingUtils.setTrace(
350+
getCurrentScopes(),
351+
PropagationContext.fromExistingTrace(traceId, spanId, sampleRate, sampleRand));
352+
}
332353
}

sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import io.sentry.SentryExceptionFactory
1919
import io.sentry.SentryItemType
2020
import io.sentry.SentryOptions
2121
import io.sentry.Session
22+
import io.sentry.SpanId
2223
import io.sentry.android.core.performance.ActivityLifecycleTimeSpan
2324
import io.sentry.android.core.performance.AppStartMetrics
2425
import io.sentry.exception.ExceptionMechanismException
@@ -505,4 +506,25 @@ class InternalSentrySdkTest {
505506
assertEquals(20.toLong(), actualProcessSpan["start_timestamp_ms"])
506507
assertEquals(100.toLong(), actualProcessSpan["end_timestamp_ms"])
507508
}
509+
510+
@Test
511+
fun `setTrace sets correct propagation context`() {
512+
val fixture = Fixture()
513+
fixture.init(context)
514+
515+
val traceId = "771a43a4192642f0b136d5159a501700"
516+
val spanId = "771a43a4192642f0"
517+
val sampleRate = 0.5
518+
val sampleRand = 0.3
519+
520+
InternalSentrySdk.setTrace(traceId, spanId, sampleRate, sampleRand)
521+
522+
Sentry.configureScope { scope ->
523+
val propagationContext = scope.propagationContext
524+
assertEquals(SentryId(traceId), propagationContext.traceId)
525+
assertEquals(SpanId(spanId), propagationContext.parentSpanId)
526+
assertEquals(sampleRate, propagationContext.baggage.sampleRateDouble)
527+
assertEquals(sampleRand, propagationContext.baggage.sampleRandDouble)
528+
}
529+
}
508530
}

sentry-android-ndk/api/sentry-android-ndk.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public final class io/sentry/android/ndk/NdkScopeObserver : io/sentry/ScopeObser
2020
public fun removeTag (Ljava/lang/String;)V
2121
public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V
2222
public fun setTag (Ljava/lang/String;Ljava/lang/String;)V
23+
public fun setTrace (Lio/sentry/SpanContext;Lio/sentry/IScope;)V
2324
public fun setUser (Lio/sentry/protocol/User;)V
2425
}
2526

sentry-android-ndk/src/main/java/io/sentry/android/ndk/NdkScopeObserver.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
import io.sentry.Breadcrumb;
44
import io.sentry.DateUtils;
5+
import io.sentry.IScope;
56
import io.sentry.ScopeObserverAdapter;
67
import io.sentry.SentryLevel;
78
import io.sentry.SentryOptions;
9+
import io.sentry.SpanContext;
810
import io.sentry.ndk.INativeScope;
911
import io.sentry.ndk.NativeScope;
1012
import io.sentry.protocol.User;
@@ -125,4 +127,22 @@ public void removeExtra(final @NotNull String key) {
125127
.log(SentryLevel.ERROR, e, "Scope sync removeExtra(%s) has an error.", key);
126128
}
127129
}
130+
131+
@Override
132+
public void setTrace(@Nullable SpanContext spanContext, @NotNull IScope scope) {
133+
if (spanContext == null) {
134+
return;
135+
}
136+
137+
try {
138+
options
139+
.getExecutorService()
140+
.submit(
141+
() ->
142+
nativeScope.setTrace(
143+
spanContext.getTraceId().toString(), spanContext.getSpanId().toString()));
144+
} catch (Throwable e) {
145+
options.getLogger().log(SentryLevel.ERROR, e, "Scope sync setTrace failed.");
146+
}
147+
}
128148
}

sentry/api/sentry.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,7 @@ public final class io/sentry/PropagationContext {
19521952
public fun <init> ()V
19531953
public fun <init> (Lio/sentry/PropagationContext;)V
19541954
public fun <init> (Lio/sentry/protocol/SentryId;Lio/sentry/SpanId;Lio/sentry/SpanId;Lio/sentry/Baggage;Ljava/lang/Boolean;)V
1955+
public static fun fromExistingTrace (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Double;Ljava/lang/Double;)Lio/sentry/PropagationContext;
19551956
public static fun fromHeaders (Lio/sentry/ILogger;Ljava/lang/String;Ljava/lang/String;)Lio/sentry/PropagationContext;
19561957
public static fun fromHeaders (Lio/sentry/ILogger;Ljava/lang/String;Ljava/util/List;)Lio/sentry/PropagationContext;
19571958
public static fun fromHeaders (Lio/sentry/SentryTraceHeader;Lio/sentry/Baggage;Lio/sentry/SpanId;)Lio/sentry/PropagationContext;
@@ -6360,6 +6361,7 @@ public final class io/sentry/util/TracingUtils {
63606361
public static fun ensureBaggage (Lio/sentry/Baggage;Ljava/lang/Boolean;Ljava/lang/Double;Ljava/lang/Double;)Lio/sentry/Baggage;
63616362
public static fun isIgnored (Ljava/util/List;Ljava/lang/String;)Z
63626363
public static fun maybeUpdateBaggage (Lio/sentry/IScope;Lio/sentry/SentryOptions;)Lio/sentry/PropagationContext;
6364+
public static fun setTrace (Lio/sentry/IScopes;Lio/sentry/PropagationContext;)V
63636365
public static fun startNewTrace (Lio/sentry/IScopes;)V
63646366
public static fun trace (Lio/sentry/IScopes;Ljava/util/List;Lio/sentry/ISpan;)Lio/sentry/util/TracingUtils$TracingHeaders;
63656367
public static fun traceIfAllowed (Lio/sentry/IScopes;Ljava/lang/String;Ljava/util/List;Lio/sentry/ISpan;)Lio/sentry/util/TracingUtils$TracingHeaders;

sentry/src/main/java/io/sentry/PropagationContext.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ public static PropagationContext fromHeaders(
5151
sentryTraceHeader.isSampled());
5252
}
5353

54+
public static @NotNull PropagationContext fromExistingTrace(
55+
final @NotNull String traceId,
56+
final @NotNull String spanId,
57+
final @Nullable Double decisionSampleRate,
58+
final @Nullable Double decisionSampleRand) {
59+
return new PropagationContext(
60+
new SentryId(traceId),
61+
new SpanId(),
62+
new SpanId(spanId),
63+
TracingUtils.ensureBaggage(null, null, decisionSampleRate, decisionSampleRand),
64+
null);
65+
}
66+
5467
private @NotNull SentryId traceId;
5568
private @NotNull SpanId spanId;
5669
private @Nullable SpanId parentSpanId;

sentry/src/main/java/io/sentry/util/TracingUtils.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ public static void startNewTrace(final @NotNull IScopes scopes) {
2828
});
2929
}
3030

31+
public static void setTrace(
32+
final @NotNull IScopes scopes, final @NotNull PropagationContext propagationContext) {
33+
scopes.configureScope(
34+
scope -> {
35+
scope.withPropagationContext(
36+
oldPropagationContext -> {
37+
scope.setPropagationContext(propagationContext);
38+
});
39+
});
40+
}
41+
3142
public static @Nullable TracingHeaders traceIfAllowed(
3243
final @NotNull IScopes scopes,
3344
final @NotNull String requestUrl,

0 commit comments

Comments
 (0)