Skip to content

Commit 213d6c2

Browse files
committed
RUM-8947: post-review fixes
1 parent 1ddbaed commit 213d6c2

File tree

13 files changed

+110
-44
lines changed

13 files changed

+110
-44
lines changed

features/dd-sdk-android-rum/api/apiSurface

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ data class com.datadog.android.rum.RumConfiguration
8686
fun setSessionListener(RumSessionListener): Builder
8787
fun setInitialResourceIdentifier(com.datadog.android.rum.metric.networksettled.InitialResourceIdentifier): Builder
8888
fun setLastInteractionIdentifier(com.datadog.android.rum.metric.interactiontonextview.LastInteractionIdentifier?): Builder
89+
fun setSlowFrameListenerConfiguration(com.datadog.android.rum.configuration.SlowFrameListenerConfiguration?): Builder
8990
fun build(): RumConfiguration
9091
enum com.datadog.android.rum.RumErrorSource
9192
- NETWORK
@@ -164,6 +165,10 @@ class com.datadog.android.rum._RumInternalProxy
164165
companion object
165166
fun setTelemetryConfigurationEventMapper(RumConfiguration.Builder, com.datadog.android.event.EventMapper<com.datadog.android.telemetry.model.TelemetryConfigurationEvent>): RumConfiguration.Builder
166167
fun setAdditionalConfiguration(RumConfiguration.Builder, Map<String, Any>): RumConfiguration.Builder
168+
data class com.datadog.android.rum.configuration.SlowFrameListenerConfiguration
169+
constructor(Int = DEFAULT_SLOW_FRAME_RECORDS_MAX_AMOUNT, Long = DEFAULT_FROZEN_FRAME_THRESHOLD_NS, Long = DEFAULT_CONTINUOUS_SLOW_FRAME_THRESHOLD_NS, Long = DEFAULT_FREEZE_DURATION_NS, Long = DEFAULT_VIEW_LIFETIME_THRESHOLD_NS)
170+
companion object
171+
val DEFAULT: SlowFrameListenerConfiguration
167172
enum com.datadog.android.rum.configuration.VitalsUpdateFrequency
168173
constructor(Long)
169174
- FREQUENT

features/dd-sdk-android-rum/api/dd-sdk-android-rum.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ public final class com/datadog/android/rum/configuration/SlowFrameListenerConfig
259259
}
260260

261261
public final class com/datadog/android/rum/configuration/SlowFrameListenerConfiguration$Companion {
262+
public final fun getDEFAULT ()Lcom/datadog/android/rum/configuration/SlowFrameListenerConfiguration;
262263
}
263264

264265
public final class com/datadog/android/rum/configuration/VitalsUpdateFrequency : java/lang/Enum {

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/RumConfiguration.kt

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,15 +285,29 @@ data class RumConfiguration internal constructor(
285285
}
286286

287287
/**
288-
* Sets the configuration for the slow frames listener, which is used to compute the slow frames array,
289-
* slow frames ratio, and freeze ratio.
288+
* The SlowFramesListener provides statistical data to help identify performance issues related to UI rendering:
290289
*
291-
* Setting this property to null will disable the slow frames listener and stop the corresponding ratio computation.
290+
* - slowFrames: A list of records containing the timestamp and duration of frames where users experience
291+
* jank frames within the given view.
292292
*
293-
* @param slowFrameListenerConfiguration The configuration to be used with the slow frames listener.
293+
* - slowFrameRate: The rate of slow frames encountered during the view's lifetime.
294+
*
295+
* - freezeRate: The rate of freeze occurrences during the view's lifetime.
296+
*
297+
*
298+
*
299+
* This configuration sets the parameters for the SlowFramesListener, which are used to calculate the slow frames array,
300+
* slow frame ratio, and freeze ratio. For additional details, refer to [SlowFrameListenerConfiguration].
301+
*
302+
* Assigning a null value to this property will disable the SlowFramesListener and stop the computation of the
303+
* associated rates.
304+
*
305+
* @param slowFrameListenerConfiguration The configuration to be applied to the SlowFramesListener.
294306
*/
295307
@ExperimentalRumApi
296-
fun setSlowFrameListenerConfiguration(slowFrameListenerConfiguration: SlowFrameListenerConfiguration): Builder {
308+
fun setSlowFrameListenerConfiguration(
309+
slowFrameListenerConfiguration: SlowFrameListenerConfiguration?
310+
): Builder {
297311
rumConfig = rumConfig.copy(slowFrameListenerConfiguration = slowFrameListenerConfiguration)
298312
return this
299313
}

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/configuration/SlowFrameListenerConfiguration.kt

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,58 @@
66
package com.datadog.android.rum.configuration
77

88
/**
9-
* Configuration class for the slow frames listener, used to define thresholds for detecting
10-
* slow frames, frozen frames, and ANRs (Application Not Responding) in the context of performance monitoring.
11-
*
12-
* @param maxSlowFramesAmount The maximum number of slow frame records to track. Default is 1000.
13-
* @param frozenFrameThresholdNs The threshold (in nanoseconds) used to determine whether a frame is considered frozen.
14-
* Default is 700 000 000 ns (700ms).
15-
* @param continuousSlowFrameThresholdNs The threshold (in nanoseconds) for considering a frame as continuously slow.
16-
* Default is 16 666 666 ns (approximately 1/60 fps).
17-
* @param anrDuration The duration (in nanoseconds) to consider as an ANR (Application Not Responding).
18-
* Default is 5 000 000 000 ns (5 seconds).
19-
* @param minViewLifetimeThresholdNs The minimum view lifetime threshold (in nanoseconds) before it is considered for monitoring.
20-
* Default is 100 000 000 ns (100ms).
9+
* The SlowFramesListener provides various statistics to assist in identifying UI performance issues:
10+
*
11+
* - slowFrames: A list of records containing the timestamp and duration of frames where users experience
12+
* jank frames within the given view.
13+
*
14+
* - slowFrameRate: The rate of slow frames encountered during the view's lifetime.
15+
*
16+
* - freezeRate: The rate of freeze occurrences during the view's lifetime.
17+
*
18+
* This class defines thresholds for frame duration to classify frames based on their duration type.
19+
*
20+
* @param maxSlowFramesAmount The maximum number of slow frame records to track for each view.
21+
* The default value is 1000.
22+
*
23+
* @param maxSlowFrameThresholdNs The threshold (in nanoseconds) used to classify a frame as slow.
24+
* Frames with durations exceeding this threshold will not be considered slow and will not affect the
25+
* [com.datadog.android.rum.model.ViewEvent.ViewEventView.slowFramesRate].
26+
* The default value is 700,000,000 ns (700 ms).
27+
*
28+
* @param continuousSlowFrameThresholdNs The threshold (in nanoseconds) used to classify a frame as continuously slow.
29+
* If two consecutive slow frames are recorded and the delay between them is less than this threshold, the previous frame
30+
* record will be updated rather than adding a new one.
31+
* The default value is 16,666,666 ns (approximately 1/60 fps).
32+
*
33+
* @param freezeDurationThreshold The duration (in nanoseconds) used to classify a frame as a freeze frame.
34+
* The cumulative duration of such freezes contributes to the calculation of the
35+
* [com.datadog.android.rum.model.ViewEvent.ViewEventView.freezeRate].
36+
* The default value is 5,000,000,000 ns (5 seconds).
37+
*
38+
* @param minViewLifetimeThresholdNs The minimum lifetime (in nanoseconds) a view must have before it is considered
39+
* for monitoring. The default value is 100,000,000 ns (100 ms).
2140
*/
41+
2242
data class SlowFrameListenerConfiguration(
2343
internal val maxSlowFramesAmount: Int = DEFAULT_SLOW_FRAME_RECORDS_MAX_AMOUNT,
24-
internal val frozenFrameThresholdNs: Long = DEFAULT_FROZEN_FRAME_THRESHOLD_NS,
44+
internal val maxSlowFrameThresholdNs: Long = DEFAULT_FROZEN_FRAME_THRESHOLD_NS,
2545
internal val continuousSlowFrameThresholdNs: Long = DEFAULT_CONTINUOUS_SLOW_FRAME_THRESHOLD_NS,
26-
internal val anrDuration: Long = DEFAULT_ANR_DURATION_NS,
46+
internal val freezeDurationThreshold: Long = DEFAULT_FREEZE_DURATION_NS,
2747
internal val minViewLifetimeThresholdNs: Long = DEFAULT_VIEW_LIFETIME_THRESHOLD_NS
2848
) {
2949

3050
companion object {
51+
/**
52+
* A default configuration of the SlowFrameListenerConfiguration class with all parameters set to their default values.
53+
*/
54+
val DEFAULT: SlowFrameListenerConfiguration = SlowFrameListenerConfiguration()
55+
3156
// Taking into account each Hitch takes 64B in the payload, we can have 64KB max per view event
3257
private const val DEFAULT_SLOW_FRAME_RECORDS_MAX_AMOUNT: Int = 1000
3358
private const val DEFAULT_CONTINUOUS_SLOW_FRAME_THRESHOLD_NS: Long = 16_666_666L // 1/60 fps in nanoseconds
3459
private const val DEFAULT_FROZEN_FRAME_THRESHOLD_NS: Long = 700_000_000 // 700ms
35-
private const val DEFAULT_ANR_DURATION_NS: Long = 5_000_000_000L // 5s
60+
private const val DEFAULT_FREEZE_DURATION_NS: Long = 5_000_000_000L // 5s
3661
private const val DEFAULT_VIEW_LIFETIME_THRESHOLD_NS: Long = 100_000_000L // 100ms
3762
}
3863
}

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScope.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ internal open class RumViewScope(
915915
}
916916

917917
val uiSlownessReport = slowFramesListener.resolveReport(viewId)
918-
val freezeRate = uiSlownessReport.anrDurationRate(stoppedNanos)
918+
val freezeRate = uiSlownessReport.freezeFramesRate(stoppedNanos)
919919
val slowFramesRate = uiSlownessReport.slowFramesRate(stoppedNanos)
920920
val slowFrames = uiSlownessReport.slowFramesRecords.map {
921921
ViewEvent.SlowFrame(

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/domain/state/ViewUIPerformanceReport.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ internal data class ViewUIPerformanceReport(
4141
else -> 0.0
4242
}
4343

44-
fun anrDurationRate(viewEndedTimeStamp: Long): Double = when {
44+
fun freezeFramesRate(viewEndedTimeStamp: Long): Double = when {
4545
viewEndedTimeStamp - viewStartedTimeStamp <= minViewLifetimeThresholdNs -> 0.0
4646
else -> max(
4747
0.0,

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/metric/slowframes/SlowFramesListener.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ internal class DefaultSlowFramesListener(
7070
// Updating frames statistics
7171
report.totalFramesDurationNs += frameDurationNs
7272

73-
if (frameDurationNs > configuration.frozenFrameThresholdNs || !volatileFrameData.isJank) {
73+
if (frameDurationNs > configuration.maxSlowFrameThresholdNs || !volatileFrameData.isJank) {
7474
// Frame duration is too big to be considered as a slow frame or not jank
7575
return
7676
}
@@ -95,7 +95,7 @@ internal class DefaultSlowFramesListener(
9595
// It's a continuous slow frame – increasing duration
9696
previousSlowFrameRecord.durationNs = min(
9797
previousSlowFrameRecord.durationNs + frameDurationNs,
98-
configuration.frozenFrameThresholdNs - 1
98+
configuration.maxSlowFrameThresholdNs - 1
9999
)
100100
}
101101
}
@@ -104,7 +104,7 @@ internal class DefaultSlowFramesListener(
104104
@WorkerThread
105105
override fun onAddLongTask(durationNs: Long) {
106106
val view = currentViewId
107-
if (durationNs >= configuration.anrDuration && view != null) {
107+
if (durationNs >= configuration.freezeDurationThreshold && view != null) {
108108
val report = getViewPerformanceReport(view)
109109
synchronized(report) { report.anrDurationNs += durationNs }
110110
}

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/RumConfigurationBuilderTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,15 +568,15 @@ internal class RumConfigurationBuilderTest {
568568
@Test
569569
fun `M use a custom slowFramesListenerConfiguration W setSlowFrameListenerConfiguration()`() {
570570
// Given
571-
val customLastInteractionIdentifier = mock<SlowFrameListenerConfiguration>()
571+
val slowFrameListenerConfiguration = mock<SlowFrameListenerConfiguration>()
572572

573573
// When
574574
val rumConfiguration = testedBuilder
575-
.setSlowFrameListenerConfiguration(customLastInteractionIdentifier)
575+
.setSlowFrameListenerConfiguration(slowFrameListenerConfiguration)
576576
.build()
577577

578578
// Then
579579
assertThat(rumConfiguration.featureConfiguration.slowFrameListenerConfiguration)
580-
.isSameAs(customLastInteractionIdentifier)
580+
.isSameAs(slowFrameListenerConfiguration)
581581
}
582582
}

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/internal/RumFeatureTest.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.datadog.android.rum.GlobalRumMonitor
2525
import com.datadog.android.rum.RumErrorSource
2626
import com.datadog.android.rum.assertj.RumFeatureAssert
2727
import com.datadog.android.rum.configuration.VitalsUpdateFrequency
28+
import com.datadog.android.rum.internal.RumFeature.Companion.SLOW_FRAME_MONITORING_DISABLED_MESSAGE
2829
import com.datadog.android.rum.internal.RumFeature.Companion.SLOW_FRAME_MONITORING_ENABLED_MESSAGE
2930
import com.datadog.android.rum.internal.domain.RumDataWriter
3031
import com.datadog.android.rum.internal.domain.event.RumEventMapper
@@ -168,6 +169,26 @@ internal class RumFeatureTest {
168169
assertThat(testedFeature.sampleRate).isEqualTo(fakeConfiguration.sampleRate)
169170
}
170171

172+
@Test
173+
fun `M log slow frames disabled message W initialize {slowFrameListenerConfiguration is null}()`() {
174+
// Given
175+
val configurationWithSlowFramesDisabled = fakeConfiguration.copy(
176+
slowFrameListenerConfiguration = null
177+
)
178+
179+
testedFeature = RumFeature(
180+
mockSdkCore,
181+
fakeApplicationId.toString(),
182+
configurationWithSlowFramesDisabled,
183+
lateCrashReporterFactory = { mockLateCrashReporter }
184+
)
185+
// When
186+
testedFeature.onInitialize(appContext.mockInstance)
187+
188+
// Then
189+
verifySlowFramesListenerLogMessage(SLOW_FRAME_MONITORING_DISABLED_MESSAGE)
190+
}
191+
171192
@Test
172193
fun `M set sample rate to 100 W initialize() {developer mode enabled}`() {
173194
// Given

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScopeTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ internal class RumViewScopeTest {
315315
duration = aLong(min = 0, max = MAX_DURATION_VALUE_NS)
316316
)
317317
}
318-
whenever(mockViewUIPerformanceReport.anrDurationRate(any())) doReturn fakeFreezeRate
318+
whenever(mockViewUIPerformanceReport.freezeFramesRate(any())) doReturn fakeFreezeRate
319319
whenever(mockViewUIPerformanceReport.slowFramesRate(any())) doReturn fakeSlownessRate
320320
whenever(mockViewUIPerformanceReport.slowFramesRecords) doReturn fakeSlowRecords
321321
.map {

0 commit comments

Comments
 (0)