Skip to content

Commit d1647d3

Browse files
authored
Merge 8276f08 into 5183da9
2 parents 5183da9 + 8276f08 commit d1647d3

File tree

6 files changed

+86
-8
lines changed

6 files changed

+86
-8
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import io.sentry.protocol.User;
5656
import io.sentry.util.HintUtils;
5757
import io.sentry.util.Random;
58+
import io.sentry.util.SentryRandom;
5859
import java.io.File;
5960
import java.util.ArrayList;
6061
import java.util.Arrays;
@@ -180,7 +181,7 @@ private boolean sampleReplay(final @NotNull SentryEvent event) {
180181

181182
try {
182183
// we have to sample here with the old sample rate, because it may change between app launches
183-
final @NotNull Random random = this.random != null ? this.random : new Random();
184+
final @NotNull Random random = this.random != null ? this.random : SentryRandom.current();
184185
final double replayErrorSampleRateDouble = Double.parseDouble(replayErrorSampleRate);
185186
if (replayErrorSampleRateDouble < random.nextDouble()) {
186187
options

sentry/api/sentry.api

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5829,6 +5829,11 @@ public final class io/sentry/util/SampleRateUtils {
58295829
public static fun isValidTracesSampleRate (Ljava/lang/Double;Z)Z
58305830
}
58315831

5832+
public final class io/sentry/util/SentryRandom {
5833+
public fun <init> ()V
5834+
public static fun current ()Lio/sentry/util/Random;
5835+
}
5836+
58325837
public final class io/sentry/util/StringUtils {
58335838
public static fun byteCountToString (J)Ljava/lang/String;
58345839
public static fun calculateStringHash (Ljava/lang/String;Lio/sentry/ILogger;)Ljava/lang/String;

sentry/src/main/java/io/sentry/SentryClient.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.sentry.util.HintUtils;
1919
import io.sentry.util.Objects;
2020
import io.sentry.util.Random;
21+
import io.sentry.util.SentryRandom;
2122
import io.sentry.util.TracingUtils;
2223
import java.io.Closeable;
2324
import java.io.IOException;
@@ -40,7 +41,6 @@ public final class SentryClient implements ISentryClient, IMetricsClient {
4041

4142
private final @NotNull SentryOptions options;
4243
private final @NotNull ITransport transport;
43-
private final @Nullable Random random;
4444
private final @NotNull SortBreadcrumbsByDate sortBreadcrumbsByDate = new SortBreadcrumbsByDate();
4545
private final @NotNull IMetricsAggregator metricsAggregator;
4646

@@ -66,8 +66,6 @@ public boolean isEnabled() {
6666
options.isEnableMetrics()
6767
? new MetricsAggregator(options, this)
6868
: NoopMetricsAggregator.getInstance();
69-
70-
this.random = options.getSampleRate() == null ? null : new Random();
7169
}
7270

7371
private boolean shouldApplyScopeData(
@@ -1183,6 +1181,7 @@ public boolean isHealthy() {
11831181
}
11841182

11851183
private boolean sample() {
1184+
final @Nullable Random random = options.getSampleRate() == null ? null : SentryRandom.current();
11861185
// https://docs.sentry.io/development/sdk-dev/features/#event-sampling
11871186
if (options.getSampleRate() != null && random != null) {
11881187
final double sampling = options.getSampleRate();

sentry/src/main/java/io/sentry/TracesSampler.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.sentry.util.Objects;
44
import io.sentry.util.Random;
5+
import io.sentry.util.SentryRandom;
56
import org.jetbrains.annotations.NotNull;
67
import org.jetbrains.annotations.Nullable;
78
import org.jetbrains.annotations.TestOnly;
@@ -10,14 +11,14 @@ final class TracesSampler {
1011
private static final @NotNull Double DEFAULT_TRACES_SAMPLE_RATE = 1.0;
1112

1213
private final @NotNull SentryOptions options;
13-
private final @NotNull Random random;
14+
private final @Nullable Random random;
1415

1516
public TracesSampler(final @NotNull SentryOptions options) {
16-
this(Objects.requireNonNull(options, "options are required"), new Random());
17+
this(Objects.requireNonNull(options, "options are required"), null);
1718
}
1819

1920
@TestOnly
20-
TracesSampler(final @NotNull SentryOptions options, final @NotNull Random random) {
21+
TracesSampler(final @NotNull SentryOptions options, final @Nullable Random random) {
2122
this.options = options;
2223
this.random = random;
2324
}
@@ -90,6 +91,13 @@ TracesSamplingDecision sample(final @NotNull SamplingContext samplingContext) {
9091
}
9192

9293
private boolean sample(final @NotNull Double aDouble) {
93-
return !(aDouble < random.nextDouble());
94+
return !(aDouble < getRandom().nextDouble());
95+
}
96+
97+
private Random getRandom() {
98+
if (random == null) {
99+
return SentryRandom.current();
100+
}
101+
return random;
94102
}
95103
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.sentry.util;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
public final class SentryRandom {
6+
7+
private static final SentryRandomThreadLocal instance = new SentryRandomThreadLocal();
8+
9+
public static @NotNull Random current() {
10+
return instance.get();
11+
}
12+
13+
private static class SentryRandomThreadLocal extends ThreadLocal<Random> {
14+
15+
@Override
16+
protected Random initialValue() {
17+
return new Random();
18+
}
19+
}
20+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.sentry.util
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertEquals
5+
import kotlin.test.assertNotEquals
6+
7+
class SentryRandomTest {
8+
9+
@Test
10+
fun `thread local creates a new instance per thread but keeps re-using it for the same thread`() {
11+
val mainThreadRandom1 = SentryRandom.current()
12+
val mainThreadRandom2 = SentryRandom.current()
13+
assertEquals(mainThreadRandom1.toString(), mainThreadRandom2.toString())
14+
15+
var thread1Random1: Random? = null
16+
var thread1Random2: Random? = null
17+
18+
val thread1 = Thread() {
19+
thread1Random1 = SentryRandom.current()
20+
thread1Random2 = SentryRandom.current()
21+
}
22+
23+
var thread2Random1: Random? = null
24+
var thread2Random2: Random? = null
25+
26+
val thread2 = Thread() {
27+
thread2Random1 = SentryRandom.current()
28+
thread2Random2 = SentryRandom.current()
29+
}
30+
31+
thread1.start()
32+
thread2.start()
33+
thread1.join()
34+
thread2.join()
35+
36+
assertEquals(thread1Random1.toString(), thread1Random2.toString())
37+
assertNotEquals(mainThreadRandom1.toString(), thread1Random1.toString())
38+
39+
assertEquals(thread2Random1.toString(), thread2Random2.toString())
40+
assertNotEquals(mainThreadRandom1.toString(), thread2Random1.toString())
41+
42+
val mainThreadRandom3 = SentryRandom.current()
43+
assertEquals(mainThreadRandom1.toString(), mainThreadRandom3.toString())
44+
}
45+
}

0 commit comments

Comments
 (0)