@@ -17,39 +17,30 @@ import (
17
17
"net/http"
18
18
"slices"
19
19
"sort"
20
- "strconv"
21
20
"strings"
22
21
"time"
23
22
)
24
23
25
24
// GoroutinesHandlerFunc returns a HandlerFunc that serves list of goroutine groups.
26
25
func GoroutinesHandlerFunc (summaries map [tracev2.GoID ]* trace.GoroutineSummary ) http.HandlerFunc {
27
26
return func (w http.ResponseWriter , r * http.Request ) {
28
- // goroutineGroup describes a group of goroutines grouped by start PC .
27
+ // goroutineGroup describes a group of goroutines grouped by name .
29
28
type goroutineGroup struct {
30
- ID uint64 // Unique identifier (PC).
31
29
Name string // Start function.
32
30
N int // Total number of goroutines in this group.
33
31
ExecTime time.Duration // Total execution time of all goroutines in this group.
34
32
}
35
- // Accumulate groups by PC .
36
- groupsByPC := make (map [uint64 ]goroutineGroup )
33
+ // Accumulate groups by Name .
34
+ groupsByName := make (map [string ]goroutineGroup )
37
35
for _ , summary := range summaries {
38
- group := groupsByPC [summary .PC ]
39
- group .ID = summary .PC
36
+ group := groupsByName [summary .Name ]
40
37
group .Name = summary .Name
41
38
group .N ++
42
39
group .ExecTime += summary .ExecTime
43
- groupsByPC [summary .PC ] = group
40
+ groupsByName [summary .Name ] = group
44
41
}
45
42
var groups []goroutineGroup
46
- for pc , group := range groupsByPC {
47
- group .ID = pc
48
- // If goroutine didn't run during the trace (no sampled PC),
49
- // the v.ID and v.Name will be zero value.
50
- if group .ID == 0 && group .Name == "" {
51
- group .Name = "(Inactive, no stack trace sampled)"
52
- }
43
+ for _ , group := range groupsByName {
53
44
groups = append (groups , group )
54
45
}
55
46
slices .SortFunc (groups , func (a , b goroutineGroup ) int {
@@ -92,7 +83,7 @@ Click a start location to view more details about that group.<br>
92
83
</tr>
93
84
{{range $}}
94
85
<tr>
95
- <td><code><a href="/goroutine?id ={{.ID }}">{{.Name}}</a></code></td>
86
+ <td><code><a href="/goroutine?name ={{.Name }}">{{or .Name "(Inactive, no stack trace sampled)" }}</a></code></td>
96
87
<td>{{.N}}</td>
97
88
<td>{{.ExecTime}}</td>
98
89
</tr>
@@ -106,11 +97,7 @@ Click a start location to view more details about that group.<br>
106
97
// goroutines in a particular group.
107
98
func GoroutineHandler (summaries map [tracev2.GoID ]* trace.GoroutineSummary ) http.HandlerFunc {
108
99
return func (w http.ResponseWriter , r * http.Request ) {
109
- pc , err := strconv .ParseUint (r .FormValue ("id" ), 10 , 64 )
110
- if err != nil {
111
- http .Error (w , fmt .Sprintf ("failed to parse id parameter '%v': %v" , r .FormValue ("id" ), err ), http .StatusInternalServerError )
112
- return
113
- }
100
+ goroutineName := r .FormValue ("name" )
114
101
115
102
type goroutine struct {
116
103
* trace.GoroutineSummary
@@ -130,7 +117,7 @@ func GoroutineHandler(summaries map[tracev2.GoID]*trace.GoroutineSummary) http.H
130
117
for _ , summary := range summaries {
131
118
totalExecTime += summary .ExecTime
132
119
133
- if summary .PC != pc {
120
+ if summary .Name != goroutineName {
134
121
continue
135
122
}
136
123
nonOverlappingStats := summary .NonOverlappingStats ()
@@ -198,9 +185,8 @@ func GoroutineHandler(summaries map[tracev2.GoID]*trace.GoroutineSummary) http.H
198
185
}
199
186
sort .Strings (allRangeStats )
200
187
201
- err = templGoroutine .Execute (w , struct {
188
+ err : = templGoroutine .Execute (w , struct {
202
189
Name string
203
- PC uint64
204
190
N int
205
191
ExecTimePercent string
206
192
MaxTotal time.Duration
@@ -209,7 +195,6 @@ func GoroutineHandler(summaries map[tracev2.GoID]*trace.GoroutineSummary) http.H
209
195
RangeStats []string
210
196
}{
211
197
Name : name ,
212
- PC : pc ,
213
198
N : len (goroutines ),
214
199
ExecTimePercent : execTimePercent ,
215
200
MaxTotal : maxTotalTime ,
@@ -339,19 +324,19 @@ Table of contents
339
324
</tr>
340
325
<tr>
341
326
<td>Network wait profile:</td>
342
- <td> <a href="/io?id ={{.PC }}">graph</a> <a href="/io?id ={{.PC }}&raw=1" download="io.profile">(download)</a></td>
327
+ <td> <a href="/io?name ={{.Name }}">graph</a> <a href="/io?name ={{.Name }}&raw=1" download="io.profile">(download)</a></td>
343
328
</tr>
344
329
<tr>
345
330
<td>Sync block profile:</td>
346
- <td> <a href="/block?id ={{.PC }}">graph</a> <a href="/block?id ={{.PC }}&raw=1" download="block.profile">(download)</a></td>
331
+ <td> <a href="/block?name ={{.Name }}">graph</a> <a href="/block?name ={{.Name }}&raw=1" download="block.profile">(download)</a></td>
347
332
</tr>
348
333
<tr>
349
334
<td>Syscall profile:</td>
350
- <td> <a href="/syscall?id ={{.PC }}">graph</a> <a href="/syscall?id ={{.PC }}&raw=1" download="syscall.profile">(download)</a></td>
335
+ <td> <a href="/syscall?name ={{.Name }}">graph</a> <a href="/syscall?name ={{.Name }}&raw=1" download="syscall.profile">(download)</a></td>
351
336
</tr>
352
337
<tr>
353
338
<td>Scheduler wait profile:</td>
354
- <td> <a href="/sched?id ={{.PC }}">graph</a> <a href="/sched?id ={{.PC }}&raw=1" download="sched.profile">(download)</a></td>
339
+ <td> <a href="/sched?name ={{.Name }}">graph</a> <a href="/sched?name ={{.Name }}&raw=1" download="sched.profile">(download)</a></td>
355
340
</tr>
356
341
</table>
357
342
0 commit comments