You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/perf/StartupTypeTelemetry.kt

97 lines
3.6 KiB
Kotlin

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.perf
import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting.NONE
import androidx.annotation.VisibleForTesting.PRIVATE
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import mozilla.components.support.base.log.logger.Logger
import org.mozilla.fenix.GleanMetrics.PerfStartup
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.perf.StartupPathProvider.StartupPath
import org.mozilla.fenix.perf.StartupStateProvider.StartupState
private val activityClass = HomeActivity::class.java
private val logger = Logger("StartupTypeTelemetry")
/**
* Records telemetry for the number of start ups. See the
* [Fenix perf glossary](https://wiki.mozilla.org/index.php?title=Performance/Fenix/Glossary)
* for specific definitions.
*
* This should be a member variable of [HomeActivity] because its data is tied to the lifecycle of an
* Activity. Call [attachOnHomeActivityOnCreate] for this class to work correctly.
*
* N.B.: this class is lightly hardcoded to HomeActivity.
*/
class StartupTypeTelemetry(
private val startupStateProvider: StartupStateProvider,
private val startupPathProvider: StartupPathProvider
) {
fun attachOnHomeActivityOnCreate(lifecycle: Lifecycle) {
lifecycle.addObserver(StartupTypeLifecycleObserver())
}
private fun getTelemetryLabel(startupState: StartupState, startupPath: StartupPath): String {
// We don't use the enum name directly to avoid unintentional changes when refactoring.
val stateLabel = when (startupState) {
StartupState.COLD -> "cold"
StartupState.WARM -> "warm"
StartupState.HOT -> "hot"
StartupState.UNKNOWN -> "unknown"
}
val pathLabel = when (startupPath) {
StartupPath.MAIN -> "main"
StartupPath.VIEW -> "view"
// To avoid combinatorial explosion in label names, we bucket NOT_SET into UNKNOWN.
StartupPath.NOT_SET,
StartupPath.UNKNOWN -> "unknown"
}
return "${stateLabel}_$pathLabel"
}
@VisibleForTesting(otherwise = NONE)
fun getTestCallbacks() = StartupTypeLifecycleObserver()
@VisibleForTesting(otherwise = PRIVATE)
fun record() {
val startupState = startupStateProvider.getStartupStateForStartedActivity(activityClass)
val startupPath = startupPathProvider.startupPathForActivity
val label = getTelemetryLabel(startupState, startupPath)
PerfStartup.startupType[label].add(1)
logger.info("Recorded start up: $label")
}
@VisibleForTesting(otherwise = PRIVATE)
inner class StartupTypeLifecycleObserver : DefaultLifecycleObserver {
private var shouldRecordStart = false
override fun onStart(owner: LifecycleOwner) {
shouldRecordStart = true
}
override fun onResume(owner: LifecycleOwner) {
// We must record in onResume because the StartupStateProvider can only be called for
// STARTED activities and we can't guarantee our onStart is called before its.
//
// We only record if start was called for this resume to avoid recording
// for onPause -> onResume states.
if (shouldRecordStart) {
record()
shouldRecordStart = false
}
}
}
}