1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
package flamegraph
import (
"encoding/json"
"fmt"
"io"
"iter"
"os"
"strings"
)
type jsonNode struct {
Name string `json:"name"`
Value uint64 `json:"value"`
Total uint64 `json:"total"`
Children []jsonNode `json:"children,omitempty"`
}
type jsonFlamegraph struct {
Fields []string `json:"fields"`
CountField string `json:"countField"`
Root jsonNode `json:"root"`
}
func (n NativeSVG) WriteJSONFromFile(iorDataFile string) (outFile string, err error) {
outFile = fmt.Sprintf("%s.%s-by-%s.json",
strings.TrimSuffix(iorDataFile, ".ior.zst"),
strings.Join(n.fields, ":"),
n.countField,
)
defer func() {
if err != nil {
_ = os.Remove(outFile)
}
}()
iod, err := newIorDataFromFile(iorDataFile)
if err != nil {
return outFile, fmt.Errorf("read ior data: %w", err)
}
fd, err := os.Create(outFile)
if err != nil {
return outFile, fmt.Errorf("create output %s: %w", outFile, err)
}
defer fd.Close()
if err := n.WriteJSONFromIter(iod.iter(), fd); err != nil {
return outFile, err
}
return outFile, nil
}
func (n NativeSVG) WriteJSONFromIter(records iter.Seq[IterRecord], w io.Writer) error {
tr, err := n.buildTrieFromIter(records)
if err != nil {
return err
}
payload := jsonFlamegraph{
Fields: append([]string(nil), n.fields...),
CountField: n.countField,
Root: jsonNodeFromTrieNode(tr.root, "root"),
}
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
return enc.Encode(payload)
}
func jsonNodeFromTrieNode(node *trieNode, name string) jsonNode {
out := jsonNode{
Name: name,
Value: node.value,
Total: node.total,
}
if len(node.children) == 0 {
return out
}
out.Children = make([]jsonNode, 0, len(node.children))
for _, child := range node.children {
out.Children = append(out.Children, jsonNodeFromTrieNode(child, child.name))
}
return out
}
|