For 27768: add FirstAppOpenForDay growth data

This commit is contained in:
MatthewTighe 2022-11-09 09:52:39 -08:00 committed by mergify[bot]
parent 6b89c28604
commit 5947344dd2
10 changed files with 65 additions and 7 deletions

View File

@ -377,8 +377,6 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
if (settings().isMarketingTelemetryEnabled) {
components.analytics.metrics.start(MetricServiceType.Marketing)
}
components.appStore.dispatch(AppAction.MetricsInitializedAction)
}
protected open fun setupLeakCanary() {

View File

@ -78,6 +78,7 @@ import org.mozilla.fenix.addons.AddonPermissionsDetailsFragmentDirections
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.browser.browsingmode.DefaultBrowsingModeManager
import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.metrics.BreadcrumbsRecorder
import org.mozilla.fenix.databinding.ActivityHomeBinding
import org.mozilla.fenix.exceptions.trackingprotection.TrackingProtectionExceptionsFragmentDirections
@ -370,6 +371,11 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
Events.defaultBrowserChanged.record(NoExtras())
}
// We attempt to send metrics onResume so that the start of new user sessions is not
// missed. Previously, this was done in FenixApplication::onCreate, but it was decided
// that we should not rely on the application being killed between user sessions.
components.appStore.dispatch(AppAction.ResumedMetricsAction)
DefaultBrowserNotificationWorker.setDefaultBrowserNotificationIfNeeded(applicationContext)
}
}

View File

@ -193,7 +193,7 @@ sealed class AppAction : Action {
}
/**
* Indicates that the app's metrics have been initialized and startup data can be sent.
* Indicates that the app has been resumed and metrics that relate to that should be sent.
*/
object MetricsInitializedAction : AppAction()
object ResumedMetricsAction : AppAction()
}

View File

@ -220,7 +220,7 @@ internal object AppStoreReducer {
val wallpaperState = state.wallpaperState.copy(availableWallpapers = wallpapers)
state.copy(wallpaperState = wallpaperState)
}
is AppAction.MetricsInitializedAction -> state
is AppAction.ResumedMetricsAction -> state
}
}

View File

@ -21,5 +21,10 @@ sealed class Event {
* Event recording whether Firefox has been set as the default browser.
*/
object SetAsDefault : GrowthData("xgpcgt")
/**
* Event recording the first time Firefox has been resumed in a 24 hour period.
*/
object FirstAppOpenForDay : GrowthData("41hl22")
}
}

View File

@ -21,8 +21,9 @@ class MetricsMiddleware(
}
private fun handleAction(action: AppAction) = when (action) {
is AppAction.MetricsInitializedAction -> {
is AppAction.ResumedMetricsAction -> {
metrics.track(Event.GrowthData.SetAsDefault)
metrics.track(Event.GrowthData.FirstAppOpenForDay)
}
else -> Unit
}

View File

@ -43,15 +43,26 @@ internal class DefaultMetricsStorage(
Event.GrowthData.SetAsDefault -> {
!settings.setAsDefaultGrowthSent && checkDefaultBrowser()
}
Event.GrowthData.FirstAppOpenForDay -> {
settings.resumeGrowthLastSent.hasBeenMoreThanDaySince()
}
}
}
override suspend fun updateSentState(event: Event) = withContext(dispatcher) {
when (event) {
Event.GrowthData.SetAsDefault -> settings.setAsDefaultGrowthSent = true
Event.GrowthData.SetAsDefault -> {
settings.setAsDefaultGrowthSent = true
}
Event.GrowthData.FirstAppOpenForDay -> {
settings.resumeGrowthLastSent = System.currentTimeMillis()
}
}
}
private fun Long.hasBeenMoreThanDaySince(): Boolean =
System.currentTimeMillis() - this > dayMillis
companion object {
private const val dayMillis: Long = 1000 * 60 * 60 * 24
private const val windowStartMillis: Long = dayMillis * 2

View File

@ -1418,4 +1418,9 @@ class Settings(private val appContext: Context) : PreferencesHolder {
key = appContext.getPreferenceKey(R.string.pref_key_growth_set_as_default),
default = false,
)
var resumeGrowthLastSent by longPreference(
key = appContext.getPreferenceKey(R.string.pref_key_growth_resume_last_sent),
default = 0,
)
}

View File

@ -310,4 +310,5 @@
<!-- Growth Data -->
<string name="pref_key_growth_set_as_default" translatable="false">pref_key_growth_set_as_default</string>
<string name="pref_key_growth_resume_last_sent" translatable="false">pref_key_growth_last_resumed</string>
</resources>

View File

@ -85,4 +85,35 @@ class DefaultMetricsStorageTest {
assertTrue(updateSlot.captured)
}
@Test
fun `GIVEN that it has been less than 24 hours since last resumed sent WHEN checked for sending THEN will not be sent`() = runTest(dispatcher) {
val currentTime = System.currentTimeMillis()
every { settings.resumeGrowthLastSent } returns currentTime
val result = storage.shouldTrack(Event.GrowthData.FirstAppOpenForDay)
assertFalse(result)
}
@Test
fun `GIVEN that it has been more than 24 hours since last resumed sent WHEN checked for sending THEN will be sent`() = runTest(dispatcher) {
val currentTime = System.currentTimeMillis()
every { settings.resumeGrowthLastSent } returns currentTime - 1000 * 60 * 60 * 24 * 2
val result = storage.shouldTrack(Event.GrowthData.FirstAppOpenForDay)
assertTrue(result)
}
@Test
fun `WHEN last resumed state updated THEN settings updated accordingly`() = runTest(dispatcher) {
val updateSlot = slot<Long>()
every { settings.resumeGrowthLastSent } returns 0
every { settings.resumeGrowthLastSent = capture(updateSlot) } returns Unit
storage.updateSentState(Event.GrowthData.FirstAppOpenForDay)
assertTrue(updateSlot.captured > 0)
}
}