From 2090b11c975c7dd659360c0a8fc44e1dfb3d4f33 Mon Sep 17 00:00:00 2001 From: mcarare Date: Thu, 7 May 2020 14:59:24 +0300 Subject: [PATCH] For #10434: Handle cases when proc/$pid/stat is not accessible. --- app/metrics.yaml | 16 ++++++++++++++++ .../perf/StartupFrameworkStartMeasurement.kt | 14 ++++++++++++-- app/src/main/java/org/mozilla/fenix/perf/Stat.kt | 3 +++ docs/metrics.md | 1 + 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/metrics.yaml b/app/metrics.yaml index 168ba0cee..d79d4953c 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -2253,6 +2253,22 @@ startup.timeline: - perf-android-fe@mozilla.com - mcomella@mozilla.com expires: "2020-07-15" + framework_start_read_error: + send_in_pings: + - startup-timeline + type: boolean + description: | + An error when attempting to read stats from /proc pseudo-filesystem - + privacy managers can block access to reading these files - + the application will catch a file reading exception. + bugs: + - https://github.com/mozilla-mobile/fenix/issues/10434 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/10481 + notification_emails: + - perf-android-fe@mozilla.com + - mcomella@mozilla.com + expires: "2020-07-15" clock_ticks_per_second: send_in_pings: - startup-timeline diff --git a/app/src/main/java/org/mozilla/fenix/perf/StartupFrameworkStartMeasurement.kt b/app/src/main/java/org/mozilla/fenix/perf/StartupFrameworkStartMeasurement.kt index 5a3fe8923..dbc4d2c24 100644 --- a/app/src/main/java/org/mozilla/fenix/perf/StartupFrameworkStartMeasurement.kt +++ b/app/src/main/java/org/mozilla/fenix/perf/StartupFrameworkStartMeasurement.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.perf import android.os.Process import android.os.SystemClock +import java.io.FileNotFoundException import kotlin.math.roundToLong import org.mozilla.fenix.GleanMetrics.StartupTimeline as Telemetry @@ -53,14 +54,23 @@ internal class StartupFrameworkStartMeasurement( if (applicationInitNanos < 0) { telemetry.frameworkStartError.set(true) } else { - telemetry.frameworkStart.setRawNanos(getFrameworkStartNanos()) + try { + telemetry.frameworkStart.setRawNanos(getFrameworkStartNanos()) + } catch (e: FileNotFoundException) { + // Privacy managers can add hooks that block access to reading system /proc files. + // We want to catch these exception and report an error on accessing the file + // rather than an implementation error. + telemetry.frameworkStartReadError.set(true) + } // frameworkStart is derived from the number of clock ticks per second. To ensure this // value does not throw off our result, we capture it too. telemetry.clockTicksPerSecond.add(stat.clockTicksPerSecond.toInt()) } } - + /** + * @throws [java.io.FileNotFoundException] + */ private fun getFrameworkStartNanos(): Long { // Get our timestamps in ticks: we expect ticks to be less granular than nanoseconds so, // to ensure our measurement uses the correct number of significant figures, we convert diff --git a/app/src/main/java/org/mozilla/fenix/perf/Stat.kt b/app/src/main/java/org/mozilla/fenix/perf/Stat.kt index a2ff22b53..ec816aedb 100644 --- a/app/src/main/java/org/mozilla/fenix/perf/Stat.kt +++ b/app/src/main/java/org/mozilla/fenix/perf/Stat.kt @@ -24,6 +24,9 @@ private const val FIELD_POS_STARTTIME = 21 // starttime naming matches field in */ open class Stat { + /** + * @throws [java.io.FileNotFoundException] + */ @VisibleForTesting(otherwise = PRIVATE) open fun getStatText(pid: Int): String = File("/proc/$pid/stat").readText() diff --git a/docs/metrics.md b/docs/metrics.md index 1bbfc0fb3..2e0956633 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -275,6 +275,7 @@ The following metrics are added to the ping: | startup.timeline.clock_ticks_per_second |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |The number of clock tick time units that occur in one second on this particular device. This value is expected to be used in conjunction with the `framework_start` metric. |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-07-15 | | startup.timeline.framework_start |[timespan](https://mozilla.github.io/glean/book/user/metrics/timespan.html) |The duration the Android framework takes to start before letting us run code in `*Application.init`. This is calculated from `appInitTimestamp - processStartTimestamp`. `processStartTimestamp` is derived from the clock tick time unit, which is expected to be less granular than nanoseconds. Therefore, we convert and round our timestamps to clock ticks before computing the difference and convert back to nanoseconds to report. For debugging purposes, `clock_ticks_per_second`, which may vary between devices, is also reported as a metric |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-07-15 | | startup.timeline.framework_start_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |An error when attempting to record `framework_start` - the application init timestamp returned a negative value - which is likely indicative of a bug in the implementation. |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-07-15 | +| startup.timeline.framework_start_read_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |An error when attempting to read stats from /proc pseudo-filesystem - privacy managers can block access to reading these files - the application will catch a file reading exception. |[1](https://github.com/mozilla-mobile/fenix/pull/10481)||2020-07-15 |