Skip to content

Commit

Permalink
[SR] Allow overriding SdkVersion only for replay events (#4014)
Browse files Browse the repository at this point in the history
  • Loading branch information
romtsn authored Dec 30, 2024
1 parent 45a4343 commit 75ebe50
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Fix warm start detection ([#3937](https://github.com/getsentry/sentry-java/pull/3937))

### Internal

- Session Replay: Allow overriding `SdkVersion` for replay events ([#4014](https://github.com/getsentry/sentry-java/pull/4014))

## 7.19.1

### Fixes
Expand Down
8 changes: 5 additions & 3 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ public abstract interface class io/sentry/EventProcessor {
}

public final class io/sentry/ExperimentalOptions {
public fun <init> (Z)V
public fun <init> (ZLio/sentry/protocol/SdkVersion;)V
public fun getSessionReplay ()Lio/sentry/SentryReplayOptions;
public fun setSessionReplay (Lio/sentry/SentryReplayOptions;)V
}
Expand Down Expand Up @@ -2724,8 +2724,8 @@ public final class io/sentry/SentryReplayOptions {
public static final field TEXT_VIEW_CLASS_NAME Ljava/lang/String;
public static final field VIDEO_VIEW_CLASS_NAME Ljava/lang/String;
public static final field WEB_VIEW_CLASS_NAME Ljava/lang/String;
public fun <init> (Ljava/lang/Double;Ljava/lang/Double;)V
public fun <init> (Z)V
public fun <init> (Ljava/lang/Double;Ljava/lang/Double;Lio/sentry/protocol/SdkVersion;)V
public fun <init> (ZLio/sentry/protocol/SdkVersion;)V
public fun addMaskViewClass (Ljava/lang/String;)V
public fun addUnmaskViewClass (Ljava/lang/String;)V
public fun getErrorReplayDuration ()J
Expand All @@ -2734,6 +2734,7 @@ public final class io/sentry/SentryReplayOptions {
public fun getMaskViewContainerClass ()Ljava/lang/String;
public fun getOnErrorSampleRate ()Ljava/lang/Double;
public fun getQuality ()Lio/sentry/SentryReplayOptions$SentryReplayQuality;
public fun getSdkVersion ()Lio/sentry/protocol/SdkVersion;
public fun getSessionDuration ()J
public fun getSessionSampleRate ()Ljava/lang/Double;
public fun getSessionSegmentDuration ()J
Expand All @@ -2747,6 +2748,7 @@ public final class io/sentry/SentryReplayOptions {
public fun setMaskViewContainerClass (Ljava/lang/String;)V
public fun setOnErrorSampleRate (Ljava/lang/Double;)V
public fun setQuality (Lio/sentry/SentryReplayOptions$SentryReplayQuality;)V
public fun setSdkVersion (Lio/sentry/protocol/SdkVersion;)V
public fun setSessionSampleRate (Ljava/lang/Double;)V
public fun setTrackOrientationChange (Z)V
public fun setUnmaskViewContainerClass (Ljava/lang/String;)V
Expand Down
6 changes: 4 additions & 2 deletions sentry/src/main/java/io/sentry/ExperimentalOptions.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.sentry;

import io.sentry.protocol.SdkVersion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Experimental options for new features, these options are going to be promoted to SentryOptions
Expand All @@ -11,8 +13,8 @@
public final class ExperimentalOptions {
private @NotNull SentryReplayOptions sessionReplay;

public ExperimentalOptions(final boolean empty) {
this.sessionReplay = new SentryReplayOptions(empty);
public ExperimentalOptions(final boolean empty, final @Nullable SdkVersion sdkVersion) {
this.sessionReplay = new SentryReplayOptions(empty, sdkVersion);
}

@NotNull
Expand Down
7 changes: 7 additions & 0 deletions sentry/src/main/java/io/sentry/MainEventProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.sentry.hints.Cached;
import io.sentry.protocol.DebugImage;
import io.sentry.protocol.DebugMeta;
import io.sentry.protocol.SdkVersion;
import io.sentry.protocol.SentryException;
import io.sentry.protocol.SentryTransaction;
import io.sentry.protocol.User;
Expand Down Expand Up @@ -159,6 +160,12 @@ private void processNonCachedEvent(final @NotNull SentryBaseEvent event) {

if (shouldApplyScopeData(event, hint)) {
processNonCachedEvent(event);
final @Nullable SdkVersion replaySdkVersion =
options.getExperimental().getSessionReplay().getSdkVersion();
if (replaySdkVersion != null) {
// we override the SdkVersion only for replay events as those may come from Hybrid SDKs
event.setSdk(replaySdkVersion);
}
}
return event;
}
Expand Down
5 changes: 4 additions & 1 deletion sentry/src/main/java/io/sentry/SentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,11 @@ public void captureUserFeedback(final @NotNull UserFeedback userFeedback) {
envelopeItems.add(replayItem);
final SentryId sentryId = event.getEventId();

// SdkVersion from ReplayOptions defaults to SdkVersion from SentryOptions and can be
// overwritten by the hybrid SDKs
final SentryEnvelopeHeader envelopeHeader =
new SentryEnvelopeHeader(sentryId, options.getSdkVersion(), traceContext);
new SentryEnvelopeHeader(
sentryId, options.getExperimental().getSessionReplay().getSdkVersion(), traceContext);

return new SentryEnvelope(envelopeHeader, envelopeItems);
}
Expand Down
12 changes: 10 additions & 2 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,13 @@ public void setSslSocketFactory(final @Nullable SSLSocketFactory sslSocketFactor
*/
@ApiStatus.Internal
public void setSdkVersion(final @Nullable SdkVersion sdkVersion) {
final @Nullable SdkVersion replaySdkVersion = experimental.getSessionReplay().getSdkVersion();
if (this.sdkVersion != null
&& replaySdkVersion != null
&& this.sdkVersion.equals(replaySdkVersion)) {
// if sdkVersion = sessionReplay.sdkVersion we override it, as it means no one else set it
experimental.getSessionReplay().setSdkVersion(sdkVersion);
}
this.sdkVersion = sdkVersion;
}

Expand Down Expand Up @@ -2626,7 +2633,8 @@ public SentryOptions() {
* @param empty if options should be empty.
*/
private SentryOptions(final boolean empty) {
experimental = new ExperimentalOptions(empty);
final @NotNull SdkVersion sdkVersion = createSdkVersion();
experimental = new ExperimentalOptions(empty, sdkVersion);
if (!empty) {
// SentryExecutorService should be initialized before any
// SendCachedEventFireAndForgetIntegration
Expand All @@ -2647,7 +2655,7 @@ private SentryOptions(final boolean empty) {
}

setSentryClientName(BuildConfig.SENTRY_JAVA_SDK_NAME + "/" + BuildConfig.VERSION_NAME);
setSdkVersion(createSdkVersion());
setSdkVersion(sdkVersion);
addPackageInfo();
}
}
Expand Down
27 changes: 24 additions & 3 deletions sentry/src/main/java/io/sentry/SentryReplayOptions.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.sentry;

import io.sentry.protocol.SdkVersion;
import io.sentry.util.SampleRateUtils;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
Expand Down Expand Up @@ -114,7 +115,13 @@ public enum SentryReplayQuality {
*/
private boolean trackOrientationChange = true;

public SentryReplayOptions(final boolean empty) {
/**
* SdkVersion object that contains the Sentry Client Name and its version. This object is only
* applied to {@link SentryReplayEvent}s.
*/
private @Nullable SdkVersion sdkVersion;

public SentryReplayOptions(final boolean empty, final @Nullable SdkVersion sdkVersion) {
if (!empty) {
setMaskAllText(true);
setMaskAllImages(true);
Expand All @@ -123,14 +130,18 @@ public SentryReplayOptions(final boolean empty) {
maskViewClasses.add(ANDROIDX_MEDIA_VIEW_CLASS_NAME);
maskViewClasses.add(EXOPLAYER_CLASS_NAME);
maskViewClasses.add(EXOPLAYER_STYLED_CLASS_NAME);
this.sdkVersion = sdkVersion;
}
}

public SentryReplayOptions(
final @Nullable Double sessionSampleRate, final @Nullable Double onErrorSampleRate) {
this(false);
final @Nullable Double sessionSampleRate,
final @Nullable Double onErrorSampleRate,
final @Nullable SdkVersion sdkVersion) {
this(false, sdkVersion);
this.sessionSampleRate = sessionSampleRate;
this.onErrorSampleRate = onErrorSampleRate;
this.sdkVersion = sdkVersion;
}

@Nullable
Expand Down Expand Up @@ -282,4 +293,14 @@ public boolean isTrackOrientationChange() {
public void setTrackOrientationChange(final boolean trackOrientationChange) {
this.trackOrientationChange = trackOrientationChange;
}

@ApiStatus.Internal
public @Nullable SdkVersion getSdkVersion() {
return sdkVersion;
}

@ApiStatus.Internal
public void setSdkVersion(final @Nullable SdkVersion sdkVersion) {
this.sdkVersion = sdkVersion;
}
}
14 changes: 13 additions & 1 deletion sentry/src/test/java/io/sentry/MainEventProcessorTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import kotlin.test.assertTrue

class MainEventProcessorTest {
class Fixture {
private val sentryOptions: SentryOptions = SentryOptions().apply {
val sentryOptions: SentryOptions = SentryOptions().apply {
dsn = dsnString
release = "release"
dist = "dist"
Expand Down Expand Up @@ -619,6 +619,18 @@ class MainEventProcessorTest {
assertEquals("value1", replayEvent.tags!!["tag1"])
}

@Test
fun `uses SdkVersion from replay options for replay events`() {
val sut = fixture.getSut(tags = mapOf("tag1" to "value1"))

fixture.sentryOptions.experimental.sessionReplay.sdkVersion = SdkVersion("dart", "3.2.1")
var replayEvent = SentryReplayEvent()
replayEvent = sut.process(replayEvent, Hint())

assertEquals("3.2.1", replayEvent.sdk!!.version)
assertEquals("dart", replayEvent.sdk!!.name)
}

private fun generateCrashedEvent(crashedThread: Thread = Thread.currentThread()) =
SentryEvent().apply {
val mockThrowable = mock<Throwable>()
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/test/java/io/sentry/SentryReplayOptionsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class SentryReplayOptionsTest {

@Test
fun `uses medium quality as default`() {
val replayOptions = SentryReplayOptions(true)
val replayOptions = SentryReplayOptions(true, null)

assertEquals(SentryReplayOptions.SentryReplayQuality.MEDIUM, replayOptions.quality)
assertEquals(75_000, replayOptions.quality.bitRate)
Expand All @@ -16,15 +16,15 @@ class SentryReplayOptionsTest {

@Test
fun `low quality`() {
val replayOptions = SentryReplayOptions(true).apply { quality = SentryReplayOptions.SentryReplayQuality.LOW }
val replayOptions = SentryReplayOptions(true, null).apply { quality = SentryReplayOptions.SentryReplayQuality.LOW }

assertEquals(50_000, replayOptions.quality.bitRate)
assertEquals(0.8f, replayOptions.quality.sizeScale)
}

@Test
fun `high quality`() {
val replayOptions = SentryReplayOptions(true).apply { quality = SentryReplayOptions.SentryReplayQuality.HIGH }
val replayOptions = SentryReplayOptions(true, null).apply { quality = SentryReplayOptions.SentryReplayQuality.HIGH }

assertEquals(100_000, replayOptions.quality.bitRate)
assertEquals(1.0f, replayOptions.quality.sizeScale)
Expand Down

0 comments on commit 75ebe50

Please sign in to comment.