Skip to content

Commit 0686640

Browse files
authored
Fix timestamp intervals of PerformanceCollectionData in profiles (#2648)
* fixed timestamps of PerformanceCollectionData in profiles * updated ui test to cover all measurements cases
1 parent 18efe20 commit 0686640

File tree

4 files changed

+41
-27
lines changed

4 files changed

+41
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
### Fixes
1212

13+
- Fix timestamp intervals of PerformanceCollectionData in profiles ([#2648](https://github.com/getsentry/sentry-java/pull/2648))
1314
- Fix timestamps of PerformanceCollectionData in profiles ([#2632](https://github.com/getsentry/sentry-java/pull/2632))
1415
- Fix missing propagateMinConstraints flag for SentryTraced ([#2637](https://github.com/getsentry/sentry-java/pull/2637))
1516

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,9 @@ private void putPerformanceCollectionDataInMeasurements(
433433
// terms of System.currentTimeMillis() and measurements timestamps require the nanoseconds since
434434
// the beginning, expressed with SystemClock.elapsedRealtimeNanos()
435435
long timestampDiff =
436-
SystemClock.elapsedRealtimeNanos() - transactionStartNanos - System.currentTimeMillis();
436+
SystemClock.elapsedRealtimeNanos()
437+
- transactionStartNanos
438+
- TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis());
437439
if (performanceCollectionData != null) {
438440
final @NotNull ArrayDeque<ProfileMeasurementValue> memoryUsageMeasurements =
439441
new ArrayDeque<>(performanceCollectionData.size());
@@ -447,17 +449,19 @@ private void putPerformanceCollectionDataInMeasurements(
447449
if (cpuData != null) {
448450
cpuUsageMeasurements.add(
449451
new ProfileMeasurementValue(
450-
cpuData.getTimestampMillis() + timestampDiff, cpuData.getCpuUsagePercentage()));
452+
TimeUnit.MILLISECONDS.toNanos(cpuData.getTimestampMillis()) + timestampDiff,
453+
cpuData.getCpuUsagePercentage()));
451454
}
452455
if (memoryData != null && memoryData.getUsedHeapMemory() > -1) {
453456
memoryUsageMeasurements.add(
454457
new ProfileMeasurementValue(
455-
memoryData.getTimestampMillis() + timestampDiff, memoryData.getUsedHeapMemory()));
458+
TimeUnit.MILLISECONDS.toNanos(memoryData.getTimestampMillis()) + timestampDiff,
459+
memoryData.getUsedHeapMemory()));
456460
}
457461
if (memoryData != null && memoryData.getUsedNativeMemory() > -1) {
458462
nativeMemoryUsageMeasurements.add(
459463
new ProfileMeasurementValue(
460-
memoryData.getTimestampMillis() + timestampDiff,
464+
TimeUnit.MILLISECONDS.toNanos(memoryData.getTimestampMillis()) + timestampDiff,
461465
memoryData.getUsedNativeMemory()));
462466
}
463467
}

sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/EnvelopeTests.kt

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ class EnvelopeTests : BaseUiTest() {
8888
val slowFrames = profilingTraceData.measurementsMap[ProfileMeasurement.ID_SLOW_FRAME_RENDERS]
8989
val frozenFrames = profilingTraceData.measurementsMap[ProfileMeasurement.ID_FROZEN_FRAME_RENDERS]
9090
val frameRates = profilingTraceData.measurementsMap[ProfileMeasurement.ID_SCREEN_FRAME_RATES]!!
91-
val memoryStats = profilingTraceData.measurementsMap[ProfileMeasurement.ID_MEMORY_FOOTPRINT]!!
92-
val memoryNativeStats = profilingTraceData.measurementsMap[ProfileMeasurement.ID_MEMORY_NATIVE_FOOTPRINT]!!
93-
val cpuStats = profilingTraceData.measurementsMap[ProfileMeasurement.ID_CPU_USAGE]!!
91+
val memoryStats = profilingTraceData.measurementsMap[ProfileMeasurement.ID_MEMORY_FOOTPRINT]
92+
val memoryNativeStats = profilingTraceData.measurementsMap[ProfileMeasurement.ID_MEMORY_NATIVE_FOOTPRINT]
93+
val cpuStats = profilingTraceData.measurementsMap[ProfileMeasurement.ID_CPU_USAGE]
9494
// Slow and frozen frames can be null (in case there were none)
9595
if (slowFrames != null) {
9696
assertEquals(ProfileMeasurement.UNIT_NANOSECONDS, slowFrames.unit)
@@ -101,28 +101,35 @@ class EnvelopeTests : BaseUiTest() {
101101
// There could be no slow/frozen frames, but we expect at least one frame rate
102102
assertEquals(ProfileMeasurement.UNIT_HZ, frameRates.unit)
103103
assertTrue(frameRates.values.isNotEmpty())
104-
assertEquals(ProfileMeasurement.UNIT_BYTES, memoryStats.unit)
105-
assertTrue(memoryStats.values.isNotEmpty())
106-
assertEquals(ProfileMeasurement.UNIT_BYTES, memoryNativeStats.unit)
107-
assertTrue(memoryNativeStats.values.isNotEmpty())
108-
assertEquals(ProfileMeasurement.UNIT_PERCENT, cpuStats.unit)
109-
assertTrue(cpuStats.values.isNotEmpty())
104+
memoryStats?.let {
105+
assertEquals(ProfileMeasurement.UNIT_BYTES, it.unit)
106+
assertEquals(true, it.values.isNotEmpty())
107+
}
108+
memoryNativeStats?.let {
109+
assertEquals(ProfileMeasurement.UNIT_BYTES, it.unit)
110+
assertEquals(true, it.values.isNotEmpty())
111+
}
112+
cpuStats?.let {
113+
assertEquals(ProfileMeasurement.UNIT_PERCENT, it.unit)
114+
assertEquals(true, it.values.isNotEmpty())
115+
}
110116

111117
// We allow measurements to be added since the start up to the end of the profile, with a small tolerance due to threading
112-
val maxTimestampAllowed = profilingTraceData.durationNs.toLong() + TimeUnit.SECONDS.toNanos(1)
113-
114-
assertTrue((slowFrames?.values?.maxOf { it.relativeStartNs.toLong() } ?: 0) < maxTimestampAllowed)
115-
assertTrue((slowFrames?.values?.minOf { it.relativeStartNs.toLong() } ?: 0) >= 0)
116-
assertTrue((frozenFrames?.values?.maxOf { it.relativeStartNs.toLong() } ?: 0) < maxTimestampAllowed)
117-
assertTrue((frozenFrames?.values?.minOf { it.relativeStartNs.toLong() } ?: 0) >= 0)
118-
assertTrue(frameRates.values.maxOf { it.relativeStartNs.toLong() } < maxTimestampAllowed)
119-
assertTrue(frameRates.values.minOf { it.relativeStartNs.toLong() } > 0)
120-
assertTrue(memoryStats.values.maxOf { it.relativeStartNs.toLong() } < maxTimestampAllowed)
121-
assertTrue(memoryStats.values.minOf { it.relativeStartNs.toLong() } > 0)
122-
assertTrue(memoryNativeStats.values.maxOf { it.relativeStartNs.toLong() } < maxTimestampAllowed)
123-
assertTrue(memoryNativeStats.values.minOf { it.relativeStartNs.toLong() } > 0)
124-
assertTrue(cpuStats.values.maxOf { it.relativeStartNs.toLong() } < maxTimestampAllowed)
125-
assertTrue(cpuStats.values.minOf { it.relativeStartNs.toLong() } > 0)
118+
val maxTimestampAllowed = profilingTraceData.durationNs.toLong() + TimeUnit.SECONDS.toNanos(2)
119+
val allMeasurements = profilingTraceData.measurementsMap.values
120+
121+
allMeasurements.filter { it.values.isNotEmpty() }.forEach { measurement ->
122+
val values = measurement.values.sortedBy { it.relativeStartNs.toLong() }
123+
// There should be no measurement before the profile starts
124+
assertTrue(values.first().relativeStartNs.toLong() > 0)
125+
// There should be no measurement after the profile ends
126+
assertTrue(values.last().relativeStartNs.toLong() < maxTimestampAllowed)
127+
128+
// Timestamps of measurements should differ at least 10 milliseconds from each other
129+
(1 until values.size).forEach { i ->
130+
assertTrue(values[i].relativeStartNs.toLong() > values[i - 1].relativeStartNs.toLong() + TimeUnit.MILLISECONDS.toNanos(10))
131+
}
132+
}
126133

127134
// We should find the transaction id that started the profiling in the list of transactions
128135
val transactionData = profilingTraceData.transactions

sentry-samples/sentry-samples-android/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
<!-- Just some random permissions to showcase the permission context sent to Sentry -->
1313
<uses-permission android:name="android.permission.CAMERA"/>
1414
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
15+
<!-- Needed by leakcanary.NotificationEventListener -->
16+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
1517

1618
<!-- if your minSdkVersion < 16, this would make usable on minSdkVersion >= 14-->
1719
<uses-sdk

0 commit comments

Comments
 (0)