Skip to content

Commit 34431f8

Browse files
authored
Create timer in TransactionPerformanceCollector lazily (#2478)
1 parent 734e4a5 commit 34431f8

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

CHANGELOG.md

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

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Create timer in `TransactionPerformanceCollector` lazily ([#2478](https://github.com/getsentry/sentry-java/pull/2478))
8+
39
## 6.12.0
410

511
### Features

sentry/src/main/java/io/sentry/TransactionPerformanceCollector.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public final class TransactionPerformanceCollector {
1818
private static final long TRANSACTION_COLLECTION_INTERVAL_MILLIS = 100;
1919
private static final long TRANSACTION_COLLECTION_TIMEOUT_MILLIS = 30000;
2020
private final @NotNull Object timerLock = new Object();
21-
private volatile @NotNull Timer timer = new Timer();
21+
private volatile @Nullable Timer timer = null;
2222
private final @NotNull Map<String, ArrayList<MemoryCollectionData>> memoryMap =
2323
new ConcurrentHashMap<>();
2424
private @Nullable IMemoryCollector memoryCollector = null;
@@ -60,6 +60,9 @@ public void start(final @NotNull ITransaction transaction) {
6060
}
6161
if (!isStarted.getAndSet(true)) {
6262
synchronized (timerLock) {
63+
if (timer == null) {
64+
timer = new Timer(true);
65+
}
6366
timer.scheduleAtFixedRate(
6467
new TimerTask() {
6568
@Override
@@ -87,8 +90,10 @@ public void run() {
8790
synchronized (timerLock) {
8891
List<MemoryCollectionData> memoryData = memoryMap.remove(transaction.getEventId().toString());
8992
if (memoryMap.isEmpty() && isStarted.getAndSet(false)) {
90-
timer.cancel();
91-
timer = new Timer();
93+
if (timer != null) {
94+
timer.cancel();
95+
timer = null;
96+
}
9297
}
9398
return memoryData;
9499
}

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class TransactionPerformanceCollectorTest {
3232
lateinit var transaction2: ITransaction
3333
val hub: IHub = mock()
3434
val options = SentryOptions()
35-
lateinit var mockTimer: Timer
35+
var mockTimer: Timer? = null
3636
var lastScheduledRunnable: Runnable? = null
3737

3838
val mockExecutorService = object : ISentryExecutorService {
@@ -56,7 +56,7 @@ class TransactionPerformanceCollectorTest {
5656
transaction1 = SentryTracer(TransactionContext("", ""), hub)
5757
transaction2 = SentryTracer(TransactionContext("", ""), hub)
5858
val collector = TransactionPerformanceCollector(options)
59-
val timer: Timer = collector.getProperty("timer")
59+
val timer: Timer? = collector.getProperty("timer") ?: Timer(true)
6060
mockTimer = spy(timer)
6161
collector.injectForField("timer", mockTimer)
6262
return collector
@@ -77,31 +77,31 @@ class TransactionPerformanceCollectorTest {
7777
val collector = fixture.getSut(NoOpMemoryCollector.getInstance())
7878
assertIs<NoOpMemoryCollector>(fixture.options.memoryCollector)
7979
collector.start(fixture.transaction1)
80-
verify(fixture.mockTimer, never()).scheduleAtFixedRate(any(), any<Long>(), any())
80+
verify(fixture.mockTimer, never())!!.scheduleAtFixedRate(any(), any<Long>(), any())
8181
}
8282

8383
@Test
8484
fun `when start, timer is scheduled every 100 milliseconds`() {
8585
val collector = fixture.getSut()
8686
collector.start(fixture.transaction1)
87-
verify(fixture.mockTimer).scheduleAtFixedRate(any(), any<Long>(), eq(100))
87+
verify(fixture.mockTimer)!!.scheduleAtFixedRate(any(), any<Long>(), eq(100))
8888
}
8989

9090
@Test
9191
fun `when stop, timer is stopped`() {
9292
val collector = fixture.getSut()
9393
collector.start(fixture.transaction1)
9494
collector.stop(fixture.transaction1)
95-
verify(fixture.mockTimer).scheduleAtFixedRate(any(), any<Long>(), eq(100))
96-
verify(fixture.mockTimer).cancel()
95+
verify(fixture.mockTimer)!!.scheduleAtFixedRate(any(), any<Long>(), eq(100))
96+
verify(fixture.mockTimer)!!.cancel()
9797
}
9898

9999
@Test
100100
fun `stopping a not collected transaction return null`() {
101101
val collector = fixture.getSut()
102102
val data = collector.stop(fixture.transaction1)
103-
verify(fixture.mockTimer, never()).scheduleAtFixedRate(any(), any<Long>(), eq(100))
104-
verify(fixture.mockTimer, never()).cancel()
103+
verify(fixture.mockTimer, never())!!.scheduleAtFixedRate(any(), any<Long>(), eq(100))
104+
verify(fixture.mockTimer, never())!!.cancel()
105105
assertNull(data)
106106
}
107107

@@ -115,11 +115,11 @@ class TransactionPerformanceCollectorTest {
115115

116116
val data1 = collector.stop(fixture.transaction1)
117117
// There is still a transaction running: the timer shouldn't stop now
118-
verify(fixture.mockTimer, never()).cancel()
118+
verify(fixture.mockTimer, never())!!.cancel()
119119

120120
val data2 = collector.stop(fixture.transaction2)
121121
// There are no more transactions running: the time should stop now
122-
verify(fixture.mockTimer).cancel()
122+
verify(fixture.mockTimer)!!.cancel()
123123

124124
// The data returned by the collector is not empty
125125
assertFalse(data1!!.isEmpty())
@@ -132,11 +132,11 @@ class TransactionPerformanceCollectorTest {
132132
collector.start(fixture.transaction1)
133133
// Let's sleep to make the collector get values
134134
Thread.sleep(200)
135-
verify(fixture.mockTimer, never()).cancel()
135+
verify(fixture.mockTimer, never())!!.cancel()
136136

137137
// Let the timeout job stop the collector
138138
fixture.lastScheduledRunnable?.run()
139-
verify(fixture.mockTimer).cancel()
139+
verify(fixture.mockTimer)!!.cancel()
140140

141141
// Data is returned even after the collector times out
142142
val data1 = collector.stop(fixture.transaction1)

0 commit comments

Comments
 (0)