Add message when traversal has error

Summary: By sending a message to the desktop we can report to log view and inform the user what happened

Reviewed By: lblasa

Differential Revision: D50369853

fbshipit-source-id: b4852d736232477261bfdf6f94c9395ce29cceaf
This commit is contained in:
Luke De Feo
2023-10-19 03:33:42 -07:00
committed by Facebook GitHub Bot
parent da903b8bc5
commit ee7f12ef85
7 changed files with 62 additions and 25 deletions

View File

@@ -13,10 +13,12 @@ import com.facebook.flipper.plugins.uidebugger.common.BitmapPool
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
import com.facebook.flipper.plugins.uidebugger.model.FrameworkEvent
import com.facebook.flipper.plugins.uidebugger.model.FrameworkEventMetadata
import com.facebook.flipper.plugins.uidebugger.model.TraversalError
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverManager
import com.facebook.flipper.plugins.uidebugger.scheduler.SharedThrottle
import com.facebook.flipper.plugins.uidebugger.traversal.PartialLayoutTraversal
import kotlinx.serialization.json.Json
interface ConnectionListener {
fun onConnect()
@@ -34,8 +36,7 @@ class UIDContext(
private val pendingFrameworkEvents: MutableList<FrameworkEvent>
) {
val layoutTraversal: PartialLayoutTraversal =
PartialLayoutTraversal(descriptorRegister, observerFactory)
val layoutTraversal: PartialLayoutTraversal = PartialLayoutTraversal(this)
val treeObserverManager = TreeObserverManager(this)
val sharedThrottle: SharedThrottle = SharedThrottle()
@@ -45,6 +46,11 @@ class UIDContext(
synchronized(pendingFrameworkEvents) { pendingFrameworkEvents.add(frameworkEvent) }
}
fun onError(traversalError: TraversalError) {
connectionRef.connection?.send(
TraversalError.name, Json.encodeToString(TraversalError.serializer(), traversalError))
}
fun extractPendingFrameworkEvents(): List<FrameworkEvent> {
synchronized(pendingFrameworkEvents) {
val copy = pendingFrameworkEvents.toList()

View File

@@ -10,21 +10,21 @@ package com.facebook.flipper.plugins.uidebugger.model
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
@kotlinx.serialization.Serializable
data class InitEvent(val rootId: Id, val frameworkEventMetadata: List<FrameworkEventMetadata>) {
class InitEvent(val rootId: Id, val frameworkEventMetadata: List<FrameworkEventMetadata>) {
companion object {
const val name = "init"
}
}
@kotlinx.serialization.Serializable
data class MetadataUpdateEvent(val attributeMetadata: Map<MetadataId, Metadata> = emptyMap()) {
class MetadataUpdateEvent(val attributeMetadata: Map<MetadataId, Metadata> = emptyMap()) {
companion object {
const val name = "metadataUpdate"
}
}
@kotlinx.serialization.Serializable
data class FrameScanEvent(
class FrameScanEvent(
val frameTime: Long,
val nodes: List<Node>,
val snapshot: Snapshot?,
@@ -35,11 +35,23 @@ data class FrameScanEvent(
}
}
@kotlinx.serialization.Serializable data class Snapshot(val nodeId: Id, val data: String)
@kotlinx.serialization.Serializable
class TraversalError(
val nodeName: String,
val errorType: String,
val errorMessage: String,
val stack: String
) {
companion object {
const val name = "traversalError"
}
}
@kotlinx.serialization.Serializable class Snapshot(val nodeId: Id, val data: String)
/** Separate optional performance statistics event */
@kotlinx.serialization.Serializable
data class PerfStatsEvent(
class PerfStatsEvent(
val txId: Long,
val observerType: String,
val nodesCount: Int,

View File

@@ -10,13 +10,13 @@ package com.facebook.flipper.plugins.uidebugger.model
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
@kotlinx.serialization.Serializable
data class FrameworkEventMetadata(
class FrameworkEventMetadata(
val type: String,
val documentation: String,
)
@kotlinx.serialization.Serializable
data class FrameworkEvent(
class FrameworkEvent(
val treeId: Id,
val nodeId: Id,
val type: String,

View File

@@ -17,7 +17,7 @@ typealias MetadataId = Int
* identity, attributes, layout, documentation, or a custom type.
*/
@kotlinx.serialization.Serializable
data class Metadata(
class Metadata(
val id: MetadataId,
val type: String,
val namespace: String,

View File

@@ -22,7 +22,7 @@ data class Bounds(val x: Int, val y: Int, val width: Int, val height: Int) {
}
@kotlinx.serialization.Serializable
data class SpaceBox(val top: Int, val right: Int, val bottom: Int, val left: Int) {
class SpaceBox(val top: Int, val right: Int, val bottom: Int, val left: Int) {
companion object {
fun fromRect(rect: Rect): SpaceBox {
return SpaceBox(rect.top, rect.right, rect.bottom, rect.left)
@@ -31,7 +31,7 @@ data class SpaceBox(val top: Int, val right: Int, val bottom: Int, val left: Int
}
@kotlinx.serialization.Serializable
data class Color(val r: Int, val g: Int, val b: Int, val a: Int) {
class Color(val r: Int, val g: Int, val b: Int, val a: Int) {
companion object {
fun fromColor(color: Int): Color {
val alpha: Int = (color shr 24) and 0xFF / 255
@@ -48,20 +48,20 @@ data class Color(val r: Int, val g: Int, val b: Int, val a: Int) {
}
@kotlinx.serialization.Serializable
data class Coordinate(
class Coordinate(
@Serializable(with = NumberSerializer::class) val x: Number,
@Serializable(with = NumberSerializer::class) val y: Number
) {}
@kotlinx.serialization.Serializable
data class Coordinate3D(
class Coordinate3D(
@Serializable(with = NumberSerializer::class) val x: Number,
@Serializable(with = NumberSerializer::class) val y: Number,
@Serializable(with = NumberSerializer::class) val z: Number
) {}
@kotlinx.serialization.Serializable
data class Size(
class Size(
@Serializable(with = NumberSerializer::class) val width: Number,
@Serializable(with = NumberSerializer::class) val height: Number
) {}

View File

@@ -25,6 +25,7 @@ import com.facebook.flipper.plugins.uidebugger.model.MetadataUpdateEvent
import com.facebook.flipper.plugins.uidebugger.model.Node
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
import com.facebook.flipper.plugins.uidebugger.model.Snapshot
import com.facebook.flipper.plugins.uidebugger.model.TraversalError
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
import java.io.ByteArrayOutputStream
import java.util.concurrent.atomic.AtomicInteger
@@ -107,7 +108,19 @@ class TreeObserverManager(val context: UIDContext) {
val workerThreadStartTimestamp = System.currentTimeMillis()
val nodes = batchedUpdate.updates.flatMap { it.deferredNodes.map { it.value() } }
val nodes =
try {
batchedUpdate.updates.flatMap { it.deferredNodes.map { it.value() } }
} catch (exception: Exception) {
context.onError(
TraversalError(
"DeferredProcessing",
exception.javaClass.simpleName,
exception.message ?: "",
exception.stackTraceToString()))
return
}
val frameworkEvents = context.extractPendingFrameworkEvents()
val snapshotUpdate = batchedUpdate.updates.find { it.snapshot != null }
val deferredComputationEndTimestamp = System.currentTimeMillis()

View File

@@ -9,11 +9,11 @@ package com.facebook.flipper.plugins.uidebugger.traversal
import android.util.Log
import com.facebook.flipper.plugins.uidebugger.LogTag
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
import com.facebook.flipper.plugins.uidebugger.core.UIDContext
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
import com.facebook.flipper.plugins.uidebugger.model.Node
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
import com.facebook.flipper.plugins.uidebugger.model.TraversalError
import com.facebook.flipper.plugins.uidebugger.util.Immediate
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
@@ -24,12 +24,11 @@ import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
* - The second item are any observable roots discovered.
*/
class PartialLayoutTraversal(
private val descriptorRegister: DescriptorRegister,
private val treeObserverFactory: TreeObserverFactory,
private val context: UIDContext,
) {
@Suppress("unchecked_cast")
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
private fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
fun traverse(root: Any, parentId: Id?): Pair<List<MaybeDeferred<Node>>, List<Pair<Any, Id?>>> {
@@ -47,12 +46,13 @@ class PartialLayoutTraversal(
try {
// If we encounter a node that has it own observer, don't traverse
if (node != root && treeObserverFactory.hasObserverFor(node)) {
if (node != root && context.observerFactory.hasObserverFor(node)) {
observableRoots.add((node to parentId))
continue
}
val descriptor = descriptorRegister.descriptorForClassUnsafe(node::class.java).asAny()
val descriptor =
context.descriptorRegister.descriptorForClassUnsafe(node::class.java).asAny()
val curId = descriptor.getId(node)
if (shallow.contains(node)) {
@@ -82,13 +82,13 @@ class PartialLayoutTraversal(
var activeChildId: Id? = null
if (activeChild != null) {
val activeChildDescriptor =
descriptorRegister.descriptorForClassUnsafe(activeChild.javaClass)
context.descriptorRegister.descriptorForClassUnsafe(activeChild.javaClass)
activeChildId = activeChildDescriptor.getId(activeChild)
}
val childrenIds = mutableListOf<Id>()
children.forEach { child ->
val childDescriptor = descriptorRegister.descriptorForClassUnsafe(child.javaClass)
val childDescriptor = context.descriptorRegister.descriptorForClassUnsafe(child.javaClass)
childrenIds.add(childDescriptor.getId(child))
stack.add(Pair(child, curId))
// If there is an active child then don't traverse it
@@ -117,6 +117,12 @@ class PartialLayoutTraversal(
})
} catch (exception: Exception) {
Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
context.onError(
TraversalError(
node.javaClass.simpleName,
exception.javaClass.simpleName,
exception.message ?: "",
exception.stackTraceToString()))
}
}