Skip to content

Commit 14c28f4

Browse files
authored
Merge 02fd16f into b5b093e
2 parents b5b093e + 02fd16f commit 14c28f4

File tree

6 files changed

+80
-34
lines changed

6 files changed

+80
-34
lines changed

sentry/src/main/java/io/sentry/ExperimentalOptions.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
* <p>Beware that experimental options can change at any time.
1010
*/
1111
public final class ExperimentalOptions {
12-
private @NotNull SentryReplayOptions sessionReplay = new SentryReplayOptions();
12+
private @NotNull SentryReplayOptions sessionReplay;
13+
14+
public ExperimentalOptions(final boolean empty) {
15+
this.sessionReplay = new SentryReplayOptions(empty);
16+
}
1317

1418
@NotNull
1519
public SentryReplayOptions getSessionReplay() {

sentry/src/main/java/io/sentry/SentryOptions.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
import io.sentry.transport.ITransportGate;
2020
import io.sentry.transport.NoOpEnvelopeCache;
2121
import io.sentry.transport.NoOpTransportGate;
22+
import io.sentry.util.Objects;
2223
import io.sentry.util.Platform;
2324
import io.sentry.util.SampleRateUtils;
2425
import io.sentry.util.StringUtils;
2526
import io.sentry.util.thread.IMainThreadChecker;
2627
import io.sentry.util.thread.NoOpMainThreadChecker;
2728
import java.io.File;
28-
import java.net.Proxy;
2929
import java.util.ArrayList;
3030
import java.util.Collections;
3131
import java.util.HashMap;
@@ -119,10 +119,14 @@ public class SentryOptions {
119119
private @NotNull SentryLevel diagnosticLevel = DEFAULT_DIAGNOSTIC_LEVEL;
120120

121121
/** Envelope reader interface */
122-
private @NotNull IEnvelopeReader envelopeReader = new EnvelopeReader(new JsonSerializer(this));
122+
private volatile @Nullable IEnvelopeReader envelopeReader;
123+
124+
private final @NotNull Object envelopeReaderLock = new Object();
123125

124126
/** Serializer interface to serialize/deserialize json events */
125-
private @NotNull ISerializer serializer = new JsonSerializer(this);
127+
private volatile @Nullable ISerializer serializer;
128+
129+
private final @NotNull Object serializerLock = new Object();
126130

127131
/** Max depth when serializing object graphs with reflection. * */
128132
private int maxDepth = 100;
@@ -415,8 +419,9 @@ public class SentryOptions {
415419
private boolean traceOptionsRequests = true;
416420

417421
/** Date provider to retrieve the current date from. */
418-
@ApiStatus.Internal
419-
private @NotNull SentryDateProvider dateProvider = new SentryAutoDateProvider();
422+
@ApiStatus.Internal private volatile @Nullable SentryDateProvider dateProvider;
423+
424+
private final @NotNull Object dateProviderLock = new Object();
420425

421426
private final @NotNull List<IPerformanceCollector> performanceCollectors = new ArrayList<>();
422427

@@ -479,7 +484,7 @@ public class SentryOptions {
479484

480485
@ApiStatus.Experimental private @Nullable Cron cron = null;
481486

482-
private final @NotNull ExperimentalOptions experimental = new ExperimentalOptions();
487+
private final @NotNull ExperimentalOptions experimental;
483488

484489
private @NotNull ReplayController replayController = NoOpReplayController.getInstance();
485490

@@ -605,7 +610,14 @@ public void setDiagnosticLevel(@Nullable final SentryLevel diagnosticLevel) {
605610
* @return the serializer
606611
*/
607612
public @NotNull ISerializer getSerializer() {
608-
return serializer;
613+
if (serializer == null) {
614+
synchronized (serializerLock) {
615+
if (serializer == null) {
616+
serializer = new JsonSerializer(this);
617+
}
618+
}
619+
}
620+
return Objects.requireNonNull(serializer, "Serializer was null");
609621
}
610622

611623
/**
@@ -636,7 +648,14 @@ public void setMaxDepth(int maxDepth) {
636648
}
637649

638650
public @NotNull IEnvelopeReader getEnvelopeReader() {
639-
return envelopeReader;
651+
if (envelopeReader == null) {
652+
synchronized (envelopeReaderLock) {
653+
if (envelopeReader == null) {
654+
envelopeReader = new EnvelopeReader(getSerializer());
655+
}
656+
}
657+
}
658+
return Objects.requireNonNull(envelopeReader, "EnvelopeReader was null");
640659
}
641660

642661
public void setEnvelopeReader(final @Nullable IEnvelopeReader envelopeReader) {
@@ -2212,7 +2231,14 @@ public void setIgnoredCheckIns(final @Nullable List<String> ignoredCheckIns) {
22122231
/** Returns the current {@link SentryDateProvider} that is used to retrieve the current date. */
22132232
@ApiStatus.Internal
22142233
public @NotNull SentryDateProvider getDateProvider() {
2215-
return dateProvider;
2234+
if (dateProvider == null) {
2235+
synchronized (dateProviderLock) {
2236+
if (dateProvider == null) {
2237+
dateProvider = new SentryAutoDateProvider();
2238+
}
2239+
}
2240+
}
2241+
return Objects.requireNonNull(dateProvider, "DateProvider is not set");
22162242
}
22172243

22182244
/**
@@ -2540,6 +2566,7 @@ public SentryOptions() {
25402566
* @param empty if options should be empty.
25412567
*/
25422568
private SentryOptions(final boolean empty) {
2569+
experimental = new ExperimentalOptions(empty);
25432570
if (!empty) {
25442571
// SentryExecutorService should be initialized before any
25452572
// SendCachedEventFireAndForgetIntegration

sentry/src/main/java/io/sentry/SentryReplayOptions.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,16 @@ public enum SentryReplayQuality {
9696
/** The maximum duration of a full session replay, defaults to 1h. */
9797
private long sessionDuration = 60 * 60 * 1000L;
9898

99-
public SentryReplayOptions() {
100-
setRedactAllText(true);
101-
setRedactAllImages(true);
99+
public SentryReplayOptions(final boolean empty) {
100+
if (!empty) {
101+
setRedactAllText(true);
102+
setRedactAllImages(true);
103+
}
102104
}
103105

104106
public SentryReplayOptions(
105107
final @Nullable Double sessionSampleRate, final @Nullable Double onErrorSampleRate) {
106-
this();
108+
this(false);
107109
this.sessionSampleRate = sessionSampleRate;
108110
this.onErrorSampleRate = onErrorSampleRate;
109111
}

sentry/src/main/java/io/sentry/clientreport/AtomicClientReportStorage.java

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package io.sentry.clientreport;
22

33
import io.sentry.DataCategory;
4+
import io.sentry.util.LazyEvaluator;
45
import java.util.ArrayList;
56
import java.util.Collections;
67
import java.util.List;
78
import java.util.Map;
9+
import java.util.Set;
810
import java.util.concurrent.ConcurrentHashMap;
911
import java.util.concurrent.atomic.AtomicLong;
1012
import org.jetbrains.annotations.ApiStatus;
@@ -14,25 +16,28 @@
1416
@ApiStatus.Internal
1517
final class AtomicClientReportStorage implements IClientReportStorage {
1618

17-
private final @NotNull Map<ClientReportKey, AtomicLong> lostEventCounts;
19+
private final @NotNull LazyEvaluator<Map<ClientReportKey, AtomicLong>> lostEventCounts =
20+
new LazyEvaluator<>(
21+
() -> {
22+
final Map<ClientReportKey, AtomicLong> modifyableEventCountsForInit =
23+
new ConcurrentHashMap<>();
1824

19-
public AtomicClientReportStorage() {
20-
final Map<ClientReportKey, AtomicLong> modifyableEventCountsForInit = new ConcurrentHashMap<>();
25+
for (final DiscardReason discardReason : DiscardReason.values()) {
26+
for (final DataCategory category : DataCategory.values()) {
27+
modifyableEventCountsForInit.put(
28+
new ClientReportKey(discardReason.getReason(), category.getCategory()),
29+
new AtomicLong(0));
30+
}
31+
}
2132

22-
for (final DiscardReason discardReason : DiscardReason.values()) {
23-
for (final DataCategory category : DataCategory.values()) {
24-
modifyableEventCountsForInit.put(
25-
new ClientReportKey(discardReason.getReason(), category.getCategory()),
26-
new AtomicLong(0));
27-
}
28-
}
33+
return Collections.unmodifiableMap(modifyableEventCountsForInit);
34+
});
2935

30-
lostEventCounts = Collections.unmodifiableMap(modifyableEventCountsForInit);
31-
}
36+
public AtomicClientReportStorage() {}
3237

3338
@Override
3439
public void addCount(ClientReportKey key, Long count) {
35-
final @Nullable AtomicLong quantity = lostEventCounts.get(key);
40+
final @Nullable AtomicLong quantity = lostEventCounts.getValue().get(key);
3641

3742
if (quantity != null) {
3843
quantity.addAndGet(count);
@@ -43,7 +48,8 @@ public void addCount(ClientReportKey key, Long count) {
4348
public List<DiscardedEvent> resetCountsAndGet() {
4449
final List<DiscardedEvent> discardedEvents = new ArrayList<>();
4550

46-
for (final Map.Entry<ClientReportKey, AtomicLong> entry : lostEventCounts.entrySet()) {
51+
Set<Map.Entry<ClientReportKey, AtomicLong>> entrySet = lostEventCounts.getValue().entrySet();
52+
for (final Map.Entry<ClientReportKey, AtomicLong> entry : entrySet) {
4753
final Long quantity = entry.getValue().getAndSet(0);
4854
if (quantity > 0) {
4955
discardedEvents.add(

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
*/
1111
@ApiStatus.Internal
1212
public final class LazyEvaluator<T> {
13-
private @Nullable T value = null;
13+
14+
private volatile @Nullable T value = null;
1415
private final @NotNull Evaluator<T> evaluator;
1516

1617
/**
@@ -28,10 +29,16 @@ public LazyEvaluator(final @NotNull Evaluator<T> evaluator) {
2829
*
2930
* @return The result of the evaluator function.
3031
*/
31-
public synchronized @NotNull T getValue() {
32+
public @NotNull T getValue() {
3233
if (value == null) {
33-
value = evaluator.evaluate();
34+
synchronized (this) {
35+
if (value == null) {
36+
value = evaluator.evaluate();
37+
}
38+
}
3439
}
40+
41+
//noinspection DataFlowIssue
3542
return value;
3643
}
3744

sentry/src/test/java/io/sentry/SentryReplayOptionsTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class SentryReplayOptionsTest {
77

88
@Test
99
fun `uses medium quality as default`() {
10-
val replayOptions = SentryReplayOptions()
10+
val replayOptions = SentryReplayOptions(true)
1111

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

1717
@Test
1818
fun `low quality`() {
19-
val replayOptions = SentryReplayOptions().apply { quality = SentryReplayOptions.SentryReplayQuality.LOW }
19+
val replayOptions = SentryReplayOptions(true).apply { quality = SentryReplayOptions.SentryReplayQuality.LOW }
2020

2121
assertEquals(50_000, replayOptions.quality.bitRate)
2222
assertEquals(0.8f, replayOptions.quality.sizeScale)
2323
}
2424

2525
@Test
2626
fun `high quality`() {
27-
val replayOptions = SentryReplayOptions().apply { quality = SentryReplayOptions.SentryReplayQuality.HIGH }
27+
val replayOptions = SentryReplayOptions(true).apply { quality = SentryReplayOptions.SentryReplayQuality.HIGH }
2828

2929
assertEquals(100_000, replayOptions.quality.bitRate)
3030
assertEquals(1.0f, replayOptions.quality.sizeScale)

0 commit comments

Comments
 (0)