Skip to content

Commit

Permalink
Merge pull request #1105 from DataDog/louiszawadzki/rumm-2687/report-…
Browse files Browse the repository at this point in the history
…harmonic-mean-of-js-refresh-rate

RUMM-2687 Invert frame time to get js refresh rate
  • Loading branch information
louiszawadzki authored Oct 26, 2022
2 parents 8f67c98 + 79c3f51 commit 0239ec1
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 15 deletions.
2 changes: 1 addition & 1 deletion dd-sdk-android/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ interface com.datadog.android.rum.RumMonitor
enum com.datadog.android.rum.RumPerformanceMetric
- FLUTTER_BUILD_TIME
- FLUTTER_RASTER_TIME
- JS_REFRESH_RATE
- JS_FRAME_TIME
interface com.datadog.android.rum.RumResourceAttributesProvider
fun onProvideAttributes(okhttp3.Request, okhttp3.Response?, Throwable?): Map<String, Any?>
enum com.datadog.android.rum.RumResourceKind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ enum class RumPerformanceMetric {
/** The amount of time Flutter spent rasterizing the view. */
FLUTTER_RASTER_TIME,

/** The JavaScript refresh rate of a React Native view. */
JS_REFRESH_RATE
/** The JavaScript frame time of a React Native view in nanoseconds. */
JS_FRAME_TIME
}
Original file line number Diff line number Diff line change
Expand Up @@ -626,8 +626,8 @@ internal open class RumViewScope(
?.let { it.toPerformanceMetric() },
flutterRasterTime = performanceMetrics[RumPerformanceMetric.FLUTTER_RASTER_TIME]
?.let { it.toPerformanceMetric() },
jsRefreshRate = performanceMetrics[RumPerformanceMetric.JS_REFRESH_RATE]
?.let { it.toPerformanceMetric() }
jsRefreshRate = performanceMetrics[RumPerformanceMetric.JS_FRAME_TIME]
?.let { it.toInversePerformanceMetric() }
),
usr = ViewEvent.Usr(
id = user.id,
Expand Down Expand Up @@ -918,3 +918,26 @@ private fun VitalInfo.toPerformanceMetric(): ViewEvent.FlutterBuildTime {
average = meanValue
)
}

@Suppress("CommentOverPrivateFunction")
/**
* This function is used to inverse frame times metrics into frame rates.
*
* As we take the inverse, the min of the inverse is the inverse of the max and
* vice-versa.
* For instance, if the the min frame time is 20ms (50 fps) and the max is 500ms (2 fps),
* the max frame rate is 50 fps (1/minValue) and the min is 2 fps (1/maxValue).
*
* As the frame times are reported in nanoseconds, we need to add a multiplier.
*/
private fun VitalInfo.toInversePerformanceMetric(): ViewEvent.FlutterBuildTime {
return ViewEvent.FlutterBuildTime(
min = invertValue(maxValue) * TimeUnit.SECONDS.toNanos(1),
max = invertValue(minValue) * TimeUnit.SECONDS.toNanos(1),
average = invertValue(meanValue) * TimeUnit.SECONDS.toNanos(1)
)
}

private fun invertValue(value: Double): Double {
return if (value == 0.0) 0.0 else 1.0 / value
}
Original file line number Diff line number Diff line change
Expand Up @@ -6096,12 +6096,13 @@ internal class RumViewScopeTest {
forge: Forge
) {
// GIVEN
val value = forge.aDouble()
val value = forge.aPositiveDouble(true)
val frameRate = TimeUnit.SECONDS.toNanos(1) / value

// WHEN
testedScope.handleEvent(
RumRawEvent.UpdatePerformanceMetric(
metric = RumPerformanceMetric.JS_REFRESH_RATE,
metric = RumPerformanceMetric.JS_FRAME_TIME,
value = value
),
mockWriter
Expand All @@ -6118,7 +6119,7 @@ internal class RumViewScopeTest {
.apply {
hasFlutterBuildTime(null)
hasFlutterRasterTime(null)
hasJsRefreshRate(ViewEvent.FlutterBuildTime(value, value, value, null))
hasJsRefreshRate(ViewEvent.FlutterBuildTime(frameRate, frameRate, frameRate, null))
}
}
verifyNoMoreInteractions(mockWriter)
Expand All @@ -6132,7 +6133,7 @@ internal class RumViewScopeTest {
// GIVEN
val flutterBuildTimes = DoubleArray(5) { forge.aDouble() }
val flutterRasterTimes = DoubleArray(5) { forge.aDouble() }
val jsRefreshRates = DoubleArray(5) { forge.aDouble() }
val jsFrameTimes = DoubleArray(5) { forge.aPositiveDouble(true) }

// WHEN
for (i in 0..4) {
Expand All @@ -6152,8 +6153,8 @@ internal class RumViewScopeTest {
)
testedScope.handleEvent(
RumRawEvent.UpdatePerformanceMetric(
metric = RumPerformanceMetric.JS_REFRESH_RATE,
value = jsRefreshRates[i]
metric = RumPerformanceMetric.JS_FRAME_TIME,
value = jsFrameTimes[i]
),
mockWriter
)
Expand All @@ -6166,7 +6167,7 @@ internal class RumViewScopeTest {
// THEN
val flutterBuildTimeStats = Arrays.stream(flutterBuildTimes).summaryStatistics()
val flutterRasterTimeStats = Arrays.stream(flutterRasterTimes).summaryStatistics()
val jsRefreshRateStats = Arrays.stream(jsRefreshRates).summaryStatistics()
val jsFrameTimeStats = Arrays.stream(jsFrameTimes).summaryStatistics()
argumentCaptor<ViewEvent> {
verify(mockWriter).write(capture())
assertThat(lastValue)
Expand All @@ -6187,9 +6188,9 @@ internal class RumViewScopeTest {
)
hasJsRefreshRate(
ViewEvent.FlutterBuildTime(
min = jsRefreshRateStats.min,
max = jsRefreshRateStats.max,
average = jsRefreshRateStats.average
min = TimeUnit.SECONDS.toNanos(1) / jsFrameTimeStats.max,
max = TimeUnit.SECONDS.toNanos(1) / jsFrameTimeStats.min,
average = TimeUnit.SECONDS.toNanos(1) / jsFrameTimeStats.average
)
)
}
Expand Down

0 comments on commit 0239ec1

Please sign in to comment.