forked from zyedidia/perforator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmetrics.go
141 lines (120 loc) · 3.03 KB
/
metrics.go
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package perforator
import (
"fmt"
"sort"
"time"
)
// A Result represents a single event, marked by Label, and the counter value
// returned by the perf monitor.
type Result struct {
Label string
Value uint64
}
// Metrics stores a set of results and the time elapsed while they were
// profiling.
type Metrics struct {
Results []Result
Elapsed time.Duration
}
// NamedMetrics associates a metrics structure with a name. This is useful for
// associated metrics structures with regions.
type NamedMetrics struct {
Metrics
Name string
}
// WriteTo pretty-prints the metrics and writes the result to a MetricsWriter.
func (m NamedMetrics) WriteTo(table MetricsWriter) {
table.SetHeader([]string{"Event", fmt.Sprintf("Count (%s)", m.Name)})
for _, r := range m.Results {
table.Append([]string{
r.Label,
fmt.Sprintf("%d", r.Value),
})
}
table.Append([]string{
"time-elapsed",
fmt.Sprintf("%s", m.Elapsed),
})
table.Render()
}
// TotalMetrics is a list of metrics and the region they are associated with.
type TotalMetrics []NamedMetrics
func (t TotalMetrics) WriteTo(table MetricsWriter) {
header := []string{"region"}
for _, m := range t {
for _, result := range m.Results {
header = append(header, result.Label)
}
break
}
header = append(header, "time-elapsed")
table.SetHeader(header)
type kv struct {
Key string
Value Metrics
}
var ss []kv
for _, v := range t {
ss = append(ss, kv{v.Name, v.Metrics})
}
for _, kv := range ss {
row := []string{kv.Key}
m := kv.Value
for _, result := range m.Results {
row = append(row, fmt.Sprintf("%d", result.Value))
}
row = append(row, fmt.Sprintf("%s", m.Elapsed))
table.Append(row)
}
table.Render()
}
// WriteToSorted pretty-prints the metrics and writes the result to a MetricsWriter.
// The sortKey and reverse parameters configure the table arrangement: which
// entry to sort by and whether the sort should be in reverse order.
func (t TotalMetrics) WriteToSorted(table MetricsWriter, sortKey string, reverse bool) {
var sortIdx int
header := []string{"region"}
for _, m := range t {
for i, result := range m.Results {
if result.Label == sortKey {
sortIdx = i
}
header = append(header, result.Label)
}
break
}
header = append(header, "time-elapsed")
table.SetHeader(header)
type kv struct {
Key string
Value Metrics
}
var ss []kv
for _, v := range t {
ss = append(ss, kv{v.Name, v.Metrics})
}
sort.Slice(ss, func(i, j int) bool {
if sortKey == "time-elapsed" {
vali := ss[i].Value.Elapsed
valj := ss[j].Value.Elapsed
if reverse {
return vali < valj
}
return valj < vali
}
if reverse {
return ss[i].Value.Results[sortIdx].Value < ss[j].Value.Results[sortIdx].Value
}
return ss[i].Value.Results[sortIdx].Value > ss[j].Value.Results[sortIdx].Value
})
for _, kv := range ss {
row := []string{kv.Key}
m := kv.Value
for _, result := range m.Results {
row = append(row, fmt.Sprintf("%d", result.Value))
}
row = append(row, fmt.Sprintf("%s", m.Elapsed))
table.Append(row)
}
table.Render()
}