Improved all axpect of tracing / forcing arrays

Improved ui and tree export
This commit is contained in:
Martino Ferrari
2026-05-21 06:20:22 +02:00
parent 58abf98eea
commit bceab8607c
7 changed files with 1281 additions and 328 deletions
+5 -87
View File
@@ -347,9 +347,11 @@ func (m *MarteClient) handleJSONResponse(tag, data string) {
return
case "TREE":
// Parse server-side and stream pre-digested flat-node batches to the
// browser so it never has to JSON.parse a multi-MB string.
go m.sendTreeBatches(data)
// Per-node response — forward to browser as-is.
broadcast(m.hub, map[string]any{
"type": "tree_node",
"data": data,
})
return
}
broadcast(m.hub, map[string]any{
@@ -359,90 +361,6 @@ func (m *MarteClient) handleJSONResponse(tag, data string) {
})
}
// ---------------------------------------------------------------------------
// TREE streaming
// ---------------------------------------------------------------------------
// TreeNode mirrors the DebugService TREE JSON structure.
type TreeNode struct {
Name string `json:"Name"`
Class string `json:"Class"`
IsTraceable bool `json:"IsTraceable"`
IsForcable bool `json:"IsForcable"`
Elements uint32 `json:"Elements"`
Children []*TreeNode `json:"Children"`
}
// FlatNode is a pre-digested, compact representation sent to the browser.
type FlatNode struct {
Path string `json:"p"`
Name string `json:"n"`
Class string `json:"c"`
Parent string `json:"par"`
Tr bool `json:"tr,omitempty"`
Fo bool `json:"fo,omitempty"`
El uint32 `json:"el,omitempty"`
HasCh bool `json:"ch,omitempty"`
}
func flattenTree(node *TreeNode, parentPath string, out *[]FlatNode) {
path := node.Name
if parentPath != "" {
path = parentPath + "." + node.Name
}
hasCh := len(node.Children) > 0
*out = append(*out, FlatNode{
Path: path,
Name: node.Name,
Class: node.Class,
Parent: parentPath,
Tr: node.IsTraceable,
Fo: node.IsForcable,
El: node.Elements,
HasCh: hasCh,
})
for _, c := range node.Children {
flattenTree(c, path, out)
}
}
// sendTreeBatches parses the raw TREE JSON and streams compact FlatNode
// batches to all browsers. Each browser processes one batch per animation
// frame, keeping the UI responsive during large tree loads.
func (m *MarteClient) sendTreeBatches(raw string) {
var root TreeNode
if err := json.Unmarshal([]byte(raw), &root); err != nil {
log.Printf("[TREE] parse error: %v — falling back to raw JSON", err)
broadcast(m.hub, map[string]any{"type": "response", "tag": "TREE", "data": raw})
return
}
var nodes []FlatNode
if root.Name == "Root" && len(root.Children) > 0 {
for _, c := range root.Children {
flattenTree(c, "", &nodes)
}
} else {
flattenTree(&root, "", &nodes)
}
total := len(nodes)
log.Printf("[TREE] streaming %d flat nodes to browser", total)
broadcast(m.hub, map[string]any{"type": "tree_clear", "total": total})
const batchSize = 50
for i := 0; i < total; i += batchSize {
end := i + batchSize
if end > total {
end = total
}
broadcast(m.hub, map[string]any{
"type": "tree_batch",
"nodes": nodes[i:end],
"done": end == total,
})
}
}
func (m *MarteClient) handleTextLine(line string) {
if strings.HasPrefix(line, "OK SERVICE_INFO") {