Use the client activity API in the Kotlin language Bindings

This additionally moves the logic from the GleanLifecycleObserver
to the Glean.kt file. The logic was spread between the two
files, making it harder than needed to understand what happened
when changing the state.
This additionally fixes the tests.
This commit is contained in:
Alessio Placitelli 2021-01-25 15:13:59 +01:00
Родитель 73f43c54fc
Коммит d200c48d4a
6 изменённых файлов: 45 добавлений и 41 удалений

Просмотреть файл

@ -48,19 +48,19 @@ This ping includes the [client id](https://mozilla.github.io/glean/book/user/pin
**Reasons this ping may be sent:**
- `background`: The ping was submitted before going to background.
- `dirty_startup`: The ping was submitted at startup, because the application process was
killed before the Glean SDK had the chance to generate this ping, when
going to background, in the last session.
*Note*: this ping will not contain the `glean.baseline.duration` metric.
- `foreground`: The ping was submitted when the application went to foreground, which
- `active`: The ping was submitted when the application became active again, which
includes when the application starts.
*Note*: this ping will not contain the `glean.baseline.duration` metric.
- `dirty_startup`: The ping was submitted at startup, because the application process was
killed before the Glean SDK had the chance to generate this ping, before
becoming inactive, in the last session.
*Note*: this ping will not contain the `glean.baseline.duration` metric.
- `inactive`: The ping was submitted before becoming inactive.
The following metrics are added to the ping:

Просмотреть файл

@ -18,6 +18,7 @@ import com.sun.jna.StringArray
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import mozilla.telemetry.glean.GleanMetrics.GleanBaseline
import mozilla.telemetry.glean.config.Configuration
import mozilla.telemetry.glean.config.FfiConfiguration
import mozilla.telemetry.glean.utils.getLocaleTag
@ -562,16 +563,42 @@ open class GleanInternalAPI internal constructor () {
* Handle the foreground event and send the appropriate pings.
*/
internal fun handleForegroundEvent() {
Pings.baseline.submit(Pings.baselineReasonCodes.foreground)
GleanValidation.foregroundCount.add(1)
// Note that this is sending the length of the last foreground session
// because it belongs to the baseline ping and that ping is sent every
// time the app goes to background.
@Suppress("EXPERIMENTAL_API_USAGE")
Dispatchers.API.launch {
LibGleanFFI.INSTANCE.glean_handle_client_active()
// The above call may generate pings, so we need to trigger
// the uploader. It's fine to trigger it if no ping was generated:
// it will bail out.
PingUploadWorker.enqueueWorker(applicationContext)
}
// Start the timespan for the new activity period.
GleanBaseline.duration.start()
}
/**
* Handle the background event and send the appropriate pings.
*/
internal fun handleBackgroundEvent() {
Pings.baseline.submit(Pings.baselineReasonCodes.background)
Pings.events.submit(Pings.eventsReasonCodes.background)
// We're going to background, so store how much time we spent
// on foreground.
GleanBaseline.duration.stop()
@Suppress("EXPERIMENTAL_API_USAGE")
Dispatchers.API.launch {
LibGleanFFI.INSTANCE.glean_handle_client_inactive()
// The above call may generate pings, so we need to trigger
// the uploader. It's fine to trigger it if no ping was generated:
// it will bail out.
PingUploadWorker.enqueueWorker(applicationContext)
}
}
/**

Просмотреть файл

@ -97,6 +97,10 @@ internal interface LibGleanFFI : Library {
fun glean_is_dirty_flag_set(): Byte
fun glean_handle_client_active()
fun glean_handle_client_inactive()
fun glean_test_clear_all_stores()
fun glean_is_first_run(): Byte

Просмотреть файл

@ -7,11 +7,7 @@ package mozilla.telemetry.glean.scheduler
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import mozilla.telemetry.glean.Dispatchers
import mozilla.telemetry.glean.Glean
import mozilla.telemetry.glean.GleanMetrics.GleanBaseline
import mozilla.telemetry.glean.rust.LibGleanFFI
import mozilla.telemetry.glean.rust.toByte
/**
* Connects process lifecycle events from Android to Glean's handleEvent
@ -24,22 +20,9 @@ internal class GleanLifecycleObserver : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
when (event) {
Lifecycle.Event.ON_STOP -> {
// We're going to background, so store how much time we spent
// on foreground.
GleanBaseline.duration.stop()
Glean.handleBackgroundEvent()
// Clear the "dirty flag" as the last thing when going to background.
// If the application is not being force-closed, we should still be
// alive and allowed to change this. If we're being force-closed and
// don't get to this point, next time Glean runs it will be detected.
@Suppress("EXPERIMENTAL_API_USAGE")
Dispatchers.API.launch {
LibGleanFFI.INSTANCE.glean_set_dirty_flag(false.toByte())
}
}
Lifecycle.Event.ON_START -> {
// Updates the baseline.duration metric when entering the foreground.
// We use ON_START here because we don't want to incorrectly count metrics in
// ON_RESUME as pause/resume can happen when interacting with things like the
// navigation shade which could lead to incorrectly recording the start of a
@ -47,17 +30,7 @@ internal class GleanLifecycleObserver : LifecycleEventObserver {
//
// https://developer.android.com/reference/android/app/Activity.html#onStart()
// Note that this is sending the length of the last foreground session
// because it belongs to the baseline ping and that ping is sent every
// time the app goes to background.
Glean.handleForegroundEvent()
GleanBaseline.duration.start()
// Set the "dirty flag" to `true`.
@Suppress("EXPERIMENTAL_API_USAGE")
Dispatchers.API.launch {
LibGleanFFI.INSTANCE.glean_set_dirty_flag(true.toByte())
}
}
else -> {
// For other lifecycle events, do nothing

Просмотреть файл

@ -74,6 +74,6 @@ public class GleanFromJavaTest {
// submit() can be called without parameters.
Pings.INSTANCE.baseline().submit();
// submit() can be called with a `reason`.
Pings.INSTANCE.baseline().submit(Pings.baselineReasonCodes.background);
Pings.INSTANCE.baseline().submit(Pings.baselineReasonCodes.inactive);
}
}

Просмотреть файл

@ -232,7 +232,7 @@ class GleanTest {
// - seq: 2, reason: foreground, duration: null
if (seq == 1) {
val baselineMetricsObject = json.getJSONObject("metrics")
assertEquals("background", json.getJSONObject("ping_info").getString("reason"))
assertEquals("inactive", json.getJSONObject("ping_info").getString("reason"))
val baselineTimespanMetrics = baselineMetricsObject.getJSONObject("timespan")
assertEquals(1, baselineTimespanMetrics.length())
assertNotNull(baselineTimespanMetrics.get("glean.baseline.duration"))