Skip to content

Commit

Permalink
Rename file and tweak method names
Browse files Browse the repository at this point in the history
  • Loading branch information
bidetofevil committed Nov 8, 2024
1 parent 716e5b7 commit 7f8d105
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ sealed class EmbType(type: String, subtype: String?) : TelemetryType {

object ThermalState : Performance("thermal_state")

object ActivityOpen : Performance("activity_open")
object UiLoad : Performance("ui_load")
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class EmbraceSpanBuilder(
}

private fun updateKeySpan() {
if (fixedAttributes.contains(EmbType.Performance.Default) || fixedAttributes.contains(EmbType.Performance.ActivityOpen)) {
if (fixedAttributes.contains(EmbType.Performance.Default) || fixedAttributes.contains(EmbType.Performance.UiLoad)) {
if (getParentSpan() == null) {
fixedAttributes.add(KeySpan)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ internal class EmbraceSpanBuilderTest {
}

@Test
fun `perf and activity_open spans are key spans if parent is null`() {
fun `perf and ui_load spans are key spans if parent is null`() {
val perfSpanBuilder = EmbraceSpanBuilder(
tracer = tracer,
name = "test",
Expand All @@ -171,7 +171,7 @@ internal class EmbraceSpanBuilderTest {
val activityOpenSpanBuilder = EmbraceSpanBuilder(
tracer = tracer,
name = "test",
telemetryType = EmbType.Performance.ActivityOpen,
telemetryType = EmbType.Performance.UiLoad,
internal = false,
private = false,
parentSpan = null,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
package io.embrace.android.embracesdk.internal.capture.activity

/**
* The relevant stages in the lifecycle of Activities pertaining to observing the performance of their loading
* Relevant events in during the lifecycle of UI loading. Listeners to these events should gather the data and log
* the appropriate loading traces and spans given the associated Activity.
*/
interface OpenEvents {
interface UiLoadEvents {

/**
* When a previously in-progress Activity Open trace should be abandoned, and that the component managing
* the trace recording should prepare itself to start tracing the opening of a new Activity instance.
* When we no longer wish to observe the loading of the given Activity instance. This may be called during its load
* or after it has loaded. Calls to this for a given Activity instance is idempotent
*/
fun resetTrace(instanceId: Int, activityName: String, timestampMs: Long)
fun abandon(instanceId: Int, activityName: String, timestampMs: Long)

/**
* When the app is no longer in a state where it is trying to open up a new Activity
*/
fun hibernate(instanceId: Int, activityName: String, timestampMs: Long)
fun reset(instanceId: Int)

/**
* When the given Activity is entering the CREATE stage of its lifecycle.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicReference

/**
* Observes Activity lifecycle and rendering events to create traces that model the workflow for showing an Activity on screen after
* app startup has completed. This creates traces for both types of Activity opening specified in [OpenType].
* Observes [UiLoadEvents] to create traces that model the workflow for displaying UI on screen.
* This will record traces for all [UiLoadType] but will ignore any UI load that is part of the app startup workflow.
*
* Depending on the version of Android and the state of the app, the start, end, and intermediate stages of the workflow will use
* timestamps from different events, which affects the precision of the measurement.
* timestamps from different events, which affects the precision of the measurements as well as the child spans contained in the trace.
*
* The start for [OpenType.COLD]:
* The start for [UiLoadType.COLD]:
*
* - On Android 10+, when [ActivityLifecycleCallbacks.onActivityPostPaused] is fired, denoting that the previous activity has completed
* its [ActivityLifecycleCallbacks.onActivityPaused] callbacks and a new Activity is ready to be created.
Expand All @@ -26,7 +26,7 @@ import java.util.concurrent.atomic.AtomicReference
* process of exiting. This will possibly result in some cleanup work of exiting the previous activity being included in the duration
* of the next trace that is logged.
*
* The start for [OpenType.HOT]
* The start for [UiLoadType.HOT]
*
* - On Android 10+, when [ActivityLifecycleCallbacks.onActivityPreStarted] is fired, denoting that an existing Activity instance is ready
* to be started
Expand All @@ -35,45 +35,45 @@ import java.util.concurrent.atomic.AtomicReference
* process of starting. This will possibly result in some of the work to start the activity already having happened depending on the
* other callbacks that have been registered.
*
* The end for both [OpenType.COLD] and [OpenType.HOT]:
* The end for both [UiLoadType.COLD] and [UiLoadType.HOT]:
*
* - Android 10+, when the Activity's first UI frame finishes rendering and is delivered to the screen
*
* - Android 9 and lower, when [ActivityLifecycleCallbacks.onActivityResumed] is fired.
*/
class OpenTraceEmitter(
class UiLoadTraceEmitter(
private val spanService: SpanService,
private val versionChecker: VersionChecker,
) : OpenEvents {
) : UiLoadEvents {

private val activeTraces: MutableMap<Int, ActivityOpenTrace> = ConcurrentHashMap()
private val traceZygoteHolder: AtomicReference<OpenTraceZygote> = AtomicReference(INITIAL)
private val activeTraces: MutableMap<Int, UiLoadTrace> = ConcurrentHashMap()
private val traceZygoteHolder: AtomicReference<UiLoadTraceZygote> = AtomicReference(INITIAL)
private var currentTracedInstanceId: Int? = null

override fun resetTrace(instanceId: Int, activityName: String, timestampMs: Long) {
override fun abandon(instanceId: Int, activityName: String, timestampMs: Long) {
currentTracedInstanceId?.let { currentlyTracedInstanceId ->
if (instanceId != currentlyTracedInstanceId) {
endTrace(instanceId = currentlyTracedInstanceId, timestampMs = timestampMs, errorCode = ErrorCode.USER_ABANDON)

Check warning on line 56 in embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/activity/UiLoadTraceEmitter.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/activity/UiLoadTraceEmitter.kt#L56

Added line #L56 was not covered by tests
}
}

Check warning on line 58 in embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/activity/UiLoadTraceEmitter.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/activity/UiLoadTraceEmitter.kt#L58

Added line #L58 was not covered by tests
traceZygoteHolder.set(
OpenTraceZygote(
UiLoadTraceZygote(
lastActivityName = activityName,
lastActivityInstanceId = instanceId,
lastActivityPausedTimeMs = timestampMs
)
)
}

override fun hibernate(instanceId: Int, activityName: String, timestampMs: Long) {
override fun reset(instanceId: Int) {
if (traceZygoteHolder.get().lastActivityInstanceId == instanceId) {
traceZygoteHolder.set(BACKGROUNDED)
}
}

override fun create(instanceId: Int, activityName: String, timestampMs: Long) {
startTrace(
openType = OpenType.COLD,
uiLoadType = UiLoadType.COLD,
instanceId = instanceId,
activityName = activityName,
timestampMs = timestampMs
Expand All @@ -95,7 +95,7 @@ class OpenTraceEmitter(

override fun start(instanceId: Int, activityName: String, timestampMs: Long) {
startTrace(
openType = OpenType.HOT,
uiLoadType = UiLoadType.HOT,
instanceId = instanceId,
activityName = activityName,
timestampMs = timestampMs
Expand Down Expand Up @@ -160,7 +160,7 @@ class OpenTraceEmitter(
}

private fun startTrace(
openType: OpenType,
uiLoadType: UiLoadType,
instanceId: Int,
activityName: String,
timestampMs: Long
Expand All @@ -178,14 +178,14 @@ class OpenTraceEmitter(
}

spanService.startSpan(
name = traceName(activityName, openType),
type = EmbType.Performance.ActivityOpen,
name = traceName(activityName, uiLoadType),
type = EmbType.Performance.UiLoad,
startTimeMs = startTimeMs,
)?.let { root ->
if (zygote.lastActivityInstanceId != -1) {
root.addSystemAttribute("last_activity", zygote.lastActivityName)
}
activeTraces[instanceId] = ActivityOpenTrace(root = root, activityName = activityName)
activeTraces[instanceId] = UiLoadTrace(root = root, activityName = activityName)
}
}
}
Expand Down Expand Up @@ -228,8 +228,8 @@ class OpenTraceEmitter(

private fun traceName(
activityName: String,
openType: OpenType
): String = "$activityName-${openType.typeName}-open"
uiLoadType: UiLoadType
): String = "$activityName-${uiLoadType.typeName}-open"

enum class LifecycleEvent(private val typeName: String) {
CREATE("create"),
Expand All @@ -240,13 +240,13 @@ class OpenTraceEmitter(
fun spanName(activityName: String): String = "$activityName-$typeName"
}

private data class ActivityOpenTrace(
private data class UiLoadTrace(
val activityName: String,
val root: PersistableEmbraceSpan,
val children: Map<LifecycleEvent, PersistableEmbraceSpan> = ConcurrentHashMap(),
)

private data class OpenTraceZygote(
private data class UiLoadTraceZygote(
val lastActivityName: String,
val lastActivityInstanceId: Int,
val lastActivityPausedTimeMs: Long,
Expand All @@ -256,19 +256,19 @@ class OpenTraceEmitter(
const val INVALID_INSTANCE: Int = -1
const val INVALID_TIME: Long = -1L

val INITIAL = OpenTraceZygote(
val INITIAL = UiLoadTraceZygote(
lastActivityName = "NEW_APP_LAUNCH",
lastActivityInstanceId = INVALID_INSTANCE,
lastActivityPausedTimeMs = INVALID_TIME
)

val READY = OpenTraceZygote(
val READY = UiLoadTraceZygote(
lastActivityName = "READY",
lastActivityInstanceId = INVALID_INSTANCE,
lastActivityPausedTimeMs = INVALID_TIME
)

val BACKGROUNDED = OpenTraceZygote(
val BACKGROUNDED = UiLoadTraceZygote(
lastActivityName = "BACKGROUNDED",
lastActivityInstanceId = INVALID_INSTANCE,
lastActivityPausedTimeMs = INVALID_TIME
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.embrace.android.embracesdk.internal.capture.activity

/**
* The type of UI load being traced
*/
enum class UiLoadType(val typeName: String) {
/**
* Load where the Activity instance has to be created
*/
COLD("cold"),

/**
* Load where the instance has already been created and just needs to be started and resumed (e.g. foregrounding)
*/
HOT("hot")
}
Loading

0 comments on commit 7f8d105

Please sign in to comment.