-
Notifications
You must be signed in to change notification settings - Fork 0
/
tagroot.go
133 lines (121 loc) · 3.39 KB
/
tagroot.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
package driver
import (
"strings"
"github.com/bir3/gocompiler/src/xvendor/github.com/google/pprof/internal/measurement"
"github.com/bir3/gocompiler/src/xvendor/github.com/google/pprof/profile"
)
// addLabelNodes adds pseudo stack frames "label:value" to each Sample with
// labels matching the supplied keys.
//
// rootKeys adds frames at the root of the callgraph (first key becomes new root).
// leafKeys adds frames at the leaf of the callgraph (last key becomes new leaf).
//
// Returns whether there were matches found for the label keys.
func addLabelNodes(p *profile.Profile, rootKeys, leafKeys []string, outputUnit string) (rootm, leafm bool) {
// Find where to insert the new locations and functions at the end of
// their ID spaces.
var maxLocID uint64
var maxFunctionID uint64
for _, loc := range p.Location {
if loc.ID > maxLocID {
maxLocID = loc.ID
}
}
for _, f := range p.Function {
if f.ID > maxFunctionID {
maxFunctionID = f.ID
}
}
nextLocID := maxLocID + 1
nextFuncID := maxFunctionID + 1
// Intern the new locations and functions we are generating.
type locKey struct {
functionName, fileName string
}
locs := map[locKey]*profile.Location{}
internLoc := func(locKey locKey) *profile.Location {
loc, found := locs[locKey]
if found {
return loc
}
function := &profile.Function{
ID: nextFuncID,
Name: locKey.functionName,
Filename: locKey.fileName,
}
nextFuncID++
p.Function = append(p.Function, function)
loc = &profile.Location{
ID: nextLocID,
Line: []profile.Line{
{
Function: function,
},
},
}
nextLocID++
p.Location = append(p.Location, loc)
locs[locKey] = loc
return loc
}
makeLabelLocs := func(s *profile.Sample, keys []string) ([]*profile.Location, bool) {
var locs []*profile.Location
var match bool
for i := range keys {
// Loop backwards, ensuring the first tag is closest to the root,
// and the last tag is closest to the leaves.
k := keys[len(keys)-1-i]
values := formatLabelValues(s, k, outputUnit)
if len(values) > 0 {
match = true
}
locKey := locKey{
functionName: strings.Join(values, ","),
fileName: k,
}
loc := internLoc(locKey)
locs = append(locs, loc)
}
return locs, match
}
for _, s := range p.Sample {
rootsToAdd, sampleMatchedRoot := makeLabelLocs(s, rootKeys)
if sampleMatchedRoot {
rootm = true
}
leavesToAdd, sampleMatchedLeaf := makeLabelLocs(s, leafKeys)
if sampleMatchedLeaf {
leafm = true
}
if len(leavesToAdd)+len(rootsToAdd) == 0 {
continue
}
var newLocs []*profile.Location
newLocs = append(newLocs, leavesToAdd...)
newLocs = append(newLocs, s.Location...)
newLocs = append(newLocs, rootsToAdd...)
s.Location = newLocs
}
return
}
// formatLabelValues returns all the string and numeric labels in Sample, with
// the numeric labels formatted according to outputUnit.
func formatLabelValues(s *profile.Sample, k string, outputUnit string) []string {
var values []string
values = append(values, s.Label[k]...)
numLabels := s.NumLabel[k]
numUnits := s.NumUnit[k]
if len(numLabels) != len(numUnits) && len(numUnits) != 0 {
return values
}
for i, numLabel := range numLabels {
var value string
if len(numUnits) != 0 {
value = measurement.ScaledLabel(numLabel, numUnits[i], outputUnit)
} else {
value = measurement.ScaledLabel(numLabel, "", "")
}
values = append(values, value)
}
return values
}