diff options
author | AoJ Architecture Team <aoj-architecture-team@google.com> | 2023-11-23 11:39:24 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-11-23 11:42:18 -0800 |
commit | 24300ba7e496a810b756283332ef53640b67f919 (patch) | |
tree | c800a177ee8c3d028d957dc40f0a25e0c54ed800 | |
parent | 21e9a95cb5eb49ad3da7f1c0152467737697447f (diff) | |
download | android_onboarding-24300ba7e496a810b756283332ef53640b67f919.tar.gz |
Copybara ❤️: Add capability to log all transitions to logcat. This can be used to get high level visibility into how much of the flow is covered by contracts.
CL: cl/584924583
PiperOrigin-RevId: 584924583
Change-Id: I66842b5caf0c12d7cb93b39522147bbb849b9f2d
10 files changed, 110 insertions, 55 deletions
diff --git a/src/com/android/onboarding/flags/DefaultOnboardingFlagsProvider.kt b/src/com/android/onboarding/flags/DefaultOnboardingFlagsProvider.kt index 6ca251c..5539233 100644 --- a/src/com/android/onboarding/flags/DefaultOnboardingFlagsProvider.kt +++ b/src/com/android/onboarding/flags/DefaultOnboardingFlagsProvider.kt @@ -18,6 +18,13 @@ class DefaultOnboardingFlagsProvider : OnboardingFlagsProvider { override val isDebug: Boolean get() = SystemProperties.getBoolean("$SYSTEM_PROPERTY_NAMESPACE.$FEATURE_DEBUG_ENABLED", false) + override val shouldVisualiseNodeTransitionsInLogcat: Boolean + get() = + SystemProperties.getBoolean( + "$SYSTEM_PROPERTY_NAMESPACE.$FEATURE_VISUALISE_TRANSITIONS", + false + ) || isDebug + companion object { // The key length has to be less that 31 characters (<18 if excluding namespace) const val SYSTEM_PROPERTY_NAMESPACE = "aoj.feature" @@ -25,5 +32,6 @@ class DefaultOnboardingFlagsProvider : OnboardingFlagsProvider { private const val FEATURE_NODE_LOGGING_ENABLED = "node_logging" private const val FEATURE_DEBUG_ENABLED = "debug" private const val FEATURE_UI_LOGGING_ENABLED = "ui_logging" + private const val FEATURE_VISUALISE_TRANSITIONS = "vis_transitions" } } diff --git a/src/com/android/onboarding/flags/OnboardingFlagsProvider.kt b/src/com/android/onboarding/flags/OnboardingFlagsProvider.kt index 7472fc6..ffe6486 100644 --- a/src/com/android/onboarding/flags/OnboardingFlagsProvider.kt +++ b/src/com/android/onboarding/flags/OnboardingFlagsProvider.kt @@ -28,4 +28,7 @@ interface OnboardingFlagsProvider { * other flag values. */ val isDebug: Boolean + + /** Returns true if node transitions should be visualised in logcat. */ + val shouldVisualiseNodeTransitionsInLogcat: Boolean } diff --git a/src/com/android/onboarding/flags/testing/FakeOnboardingFlagsProvider.kt b/src/com/android/onboarding/flags/testing/FakeOnboardingFlagsProvider.kt index 11bfd18..5bfbde4 100644 --- a/src/com/android/onboarding/flags/testing/FakeOnboardingFlagsProvider.kt +++ b/src/com/android/onboarding/flags/testing/FakeOnboardingFlagsProvider.kt @@ -8,6 +8,7 @@ class FakeOnboardingFlagsProvider( override var isNodeLoggingEnabled: Boolean = false, override var isUiLoggingEnabled: Boolean = false, override var isDebug: Boolean = false, + override val shouldVisualiseNodeTransitionsInLogcat: Boolean = false, ) : OnboardingFlagsProvider { @Deprecated(message = "Replaced with overrides", replaceWith = ReplaceWith("isContractEnabled")) var isOnboardingContractEnabledFlag: Boolean by ::isContractEnabled diff --git a/src/com/android/onboarding/nodes/Android.bp b/src/com/android/onboarding/nodes/Android.bp index e63de84..f0b1099 100644 --- a/src/com/android/onboarding/nodes/Android.bp +++ b/src/com/android/onboarding/nodes/Android.bp @@ -13,7 +13,8 @@ android_library { "androidx.activity_activity-ktx", "guava", "android_onboarding.nodes_proto_lite", - "android_onboarding.contracts.annotations" + "android_onboarding.contracts.annotations", + "android_onboarding.flags", ] } @@ -28,7 +29,7 @@ java_library_host { static_libs: [ "guava", "android_onboarding.nodes_proto_full", - "android_onboarding.contracts.annotations_host" + "android_onboarding.contracts.annotations_host", ] } diff --git a/src/com/android/onboarding/nodes/AndroidOnboardingGraphLog.kt b/src/com/android/onboarding/nodes/AndroidOnboardingGraphLog.kt index eb01bf4..c6a1961 100644 --- a/src/com/android/onboarding/nodes/AndroidOnboardingGraphLog.kt +++ b/src/com/android/onboarding/nodes/AndroidOnboardingGraphLog.kt @@ -1,11 +1,27 @@ package com.android.onboarding.nodes +import com.android.onboarding.flags.DefaultOnboardingFlagsProvider + /** A Singleton [OnboardingGraphLog] which automatically logs all events to logcat. */ object AndroidOnboardingGraphLog : OnboardingGraphLog { - private val logcatObserver = OnboardingGraphLogcatObserver() + const val LOG_TAG = "ZZZOnboardingGraph" + private val onboardingFlags = DefaultOnboardingFlagsProvider() + private val logcatObserver = LogcatObserver(LOG_TAG) { it.serializeToString() } private val defaultOnboardingGraphLog = - DefaultOnboardingGraphLog().also { it.addObserver(logcatObserver) } + DefaultOnboardingGraphLog().also { + it.addObserver(logcatObserver) + + if (onboardingFlags.shouldVisualiseNodeTransitionsInLogcat) { + it.addObserver( + OnboardingGraphNodeTransitionObserver( + LogcatObserver(logTag = "OnboardingGraph") { node -> + "${node.nodeName}(${node.nodeId})" + } + ) + ) + } + } override fun addObserver(observer: OnboardingGraphLog.Observer) { defaultOnboardingGraphLog.addObserver(observer) diff --git a/src/com/android/onboarding/nodes/DefaultOnboardingGraphLog.kt b/src/com/android/onboarding/nodes/DefaultOnboardingGraphLog.kt index 7c6b717..048798f 100644 --- a/src/com/android/onboarding/nodes/DefaultOnboardingGraphLog.kt +++ b/src/com/android/onboarding/nodes/DefaultOnboardingGraphLog.kt @@ -1,8 +1,5 @@ package com.android.onboarding.nodes -import java.util.Collections -import java.util.WeakHashMap - class DefaultOnboardingGraphLog : OnboardingGraphLog { private val observers = mutableSetOf<OnboardingGraphLog.Observer>() diff --git a/src/com/android/onboarding/nodes/LogcatObserver.kt b/src/com/android/onboarding/nodes/LogcatObserver.kt new file mode 100644 index 0000000..cf80141 --- /dev/null +++ b/src/com/android/onboarding/nodes/LogcatObserver.kt @@ -0,0 +1,19 @@ +package com.android.onboarding.nodes + +import android.util.Log + +/** An [OnboardingGraphLog.Observer] which logs human readable events to logcat. */ +class LogcatObserver( + private val logTag: String = LOG_TAG, + private val toString: (e: OnboardingGraphLog.OnboardingEvent) -> String = + OnboardingGraphLog.OnboardingEvent::toString +) : OnboardingGraphLog.Observer { + + override fun onEvent(event: OnboardingGraphLog.OnboardingEvent) { + Log.i(logTag, toString(event)) + } + + companion object { + const val LOG_TAG = "RawLogcatGraph" + } +} diff --git a/src/com/android/onboarding/nodes/OnboardingGraphLog.kt b/src/com/android/onboarding/nodes/OnboardingGraphLog.kt index c34966d..0c8ff52 100644 --- a/src/com/android/onboarding/nodes/OnboardingGraphLog.kt +++ b/src/com/android/onboarding/nodes/OnboardingGraphLog.kt @@ -40,7 +40,7 @@ interface OnboardingGraphLog { // LINT.IfChange /** Possible Events. */ - sealed class OnboardingEvent { + sealed class OnboardingEvent(open val nodeId: Long, open val nodeName: String?) { /** Writes this event to a string which can be parsed by [OnboardingGraphLog#deserialize]. */ fun serializeToString(): String { @@ -59,11 +59,11 @@ interface OnboardingGraphLog { data class ActivityNodeExecutedDirectly private constructor( val sourceNodeId: Long, - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val argument: Any? = null, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( sourceNodeId: Long, @@ -106,11 +106,11 @@ interface OnboardingGraphLog { data class ActivityNodeExecutedForResult private constructor( val sourceNodeId: Long, - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val argument: Any? = null, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( sourceNodeId: Long, @@ -151,11 +151,11 @@ interface OnboardingGraphLog { */ data class ActivityNodeValidating private constructor( - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val intent: IntentData? = null, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( nodeId: Long, @@ -193,12 +193,12 @@ interface OnboardingGraphLog { */ data class ActivityNodeFailedValidation private constructor( - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val exception: Exception = IllegalArgumentException("Failed validation"), val intent: IntentData? = null, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( nodeId: Long, @@ -238,11 +238,11 @@ interface OnboardingGraphLog { */ data class ActivityNodeExtractArgument private constructor( - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val intent: IntentData, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( nodeId: Long, @@ -287,11 +287,11 @@ interface OnboardingGraphLog { */ data class ActivityNodeArgumentExtracted private constructor( - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val argument: Any?, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( nodeId: Long, @@ -330,11 +330,11 @@ interface OnboardingGraphLog { */ data class ActivityNodeSetResult private constructor( - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val result: Any?, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( nodeId: Long, @@ -372,10 +372,10 @@ interface OnboardingGraphLog { * because of [reason]. */ data class ActivityNodeFail( - val nodeId: Long, + override val nodeId: Long, val reason: String?, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName = null) { override fun serialize(): OnboardingProtos.LogProto { return OnboardingProtos.LogProto.newBuilder() @@ -408,11 +408,11 @@ interface OnboardingGraphLog { */ data class ActivityNodeResultReceived private constructor( - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val result: Any?, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( nodeId: Long, @@ -452,11 +452,11 @@ interface OnboardingGraphLog { data class ActivityNodeStartExecuteSynchronously private constructor( val sourceNodeId: Long, - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val argument: Any?, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( sourceNodeId: Long, @@ -495,11 +495,11 @@ interface OnboardingGraphLog { /** At [timestamp], the synchronously executing node with id [nodeId] got result [result]. */ data class ActivityNodeExecutedSynchronously private constructor( - val nodeId: Long, - val nodeName: String, + override val nodeId: Long, + override val nodeName: String, val result: Any?, val timestamp: Instant = Instant.now() - ) : OnboardingEvent() { + ) : OnboardingEvent(nodeId, nodeName) { constructor( nodeId: Long, diff --git a/src/com/android/onboarding/nodes/OnboardingGraphLogcatObserver.kt b/src/com/android/onboarding/nodes/OnboardingGraphLogcatObserver.kt deleted file mode 100644 index 4bab5d8..0000000 --- a/src/com/android/onboarding/nodes/OnboardingGraphLogcatObserver.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.android.onboarding.nodes - -import android.util.Log - -/** An [OnboardingGraphLog.Observer] which serializes all logs into logcat. */ -class OnboardingGraphLogcatObserver : OnboardingGraphLog.Observer { - - override fun onEvent(event: OnboardingGraphLog.OnboardingEvent) { - Log.i(LOG_TAG, event.serializeToString()) - } - - companion object { - const val LOG_TAG = "ZZZOnboardingGraph" - } -} diff --git a/src/com/android/onboarding/nodes/OnboardingGraphNodeTransitionObserver.kt b/src/com/android/onboarding/nodes/OnboardingGraphNodeTransitionObserver.kt new file mode 100644 index 0000000..6e21d69 --- /dev/null +++ b/src/com/android/onboarding/nodes/OnboardingGraphNodeTransitionObserver.kt @@ -0,0 +1,25 @@ +package com.android.onboarding.nodes + +/** + * An [OnboardingGraphLog.Observer] which logs a single entry each time we "transition" from one + * node to another. + * + * This will only make sense when the flow is serial and there are no nodes executing in parallel. + * Once parallel nodes is common this should be removed. + * + * This is only for use exploring how much of the Onboarding flow is covered by nodes. It should not + * be depended upon for any other purpose. + */ +class OnboardingGraphNodeTransitionObserver(private val observer: OnboardingGraphLog.Observer) : + OnboardingGraphLog.Observer { + + private var currentNodeId: Long? = null + + override fun onEvent(event: OnboardingGraphLog.OnboardingEvent) { + if (event.nodeId != currentNodeId) { + currentNodeId = event.nodeId + + observer.onEvent(event) + } + } +} |