diff options
author | Rohith Ravi <entombedvirus@gmail.com> | 2020-04-19 02:21:15 +0000 |
---|---|---|
committer | Hyang-Ah Hana Kim <hyangah@gmail.com> | 2020-04-21 14:57:43 +0000 |
commit | af55060b39d2f6f39711abc95a23bd8f47968e8e (patch) | |
tree | 4a4553517ef29e3ce7146eb155b4e2eb76ba07eb /src/cmd/trace | |
parent | 664d2707276b3523895d98f1233c3ad7b7297220 (diff) | |
download | go-af55060b39d2f6f39711abc95a23bd8f47968e8e.tar.gz go-af55060b39d2f6f39711abc95a23bd8f47968e8e.zip |
cmd/trace: fix the broken link in region pages and improve UX
The trace tool had a broken link due to a parameter encoding error,
which has been corrected.
In addition:
- the user regions page has been enhanced to include links to
pprof style profiles for region specific io, block, syscall and
schedwait profiles.
- sortable table headers have a pointer cursor to indicate they're
clickable.
Fixes #38518
Change-Id: I26cd5157bd9753750f5f53ea03aac5d2d41b021c
Reviewed-on: https://go-review.googlesource.com/c/go/+/228899
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Diffstat (limited to 'src/cmd/trace')
-rw-r--r-- | src/cmd/trace/annotations.go | 55 | ||||
-rw-r--r-- | src/cmd/trace/goroutines.go | 16 |
2 files changed, 59 insertions, 12 deletions
diff --git a/src/cmd/trace/annotations.go b/src/cmd/trace/annotations.go index 817ed0d4a2..9b45457436 100644 --- a/src/cmd/trace/annotations.go +++ b/src/cmd/trace/annotations.go @@ -12,6 +12,7 @@ import ( "log" "math" "net/http" + "net/url" "reflect" "sort" "strconv" @@ -146,10 +147,12 @@ func httpUserRegion(w http.ResponseWriter, r *http.Request) { MaxTotal int64 Data []regionDesc Name string + Filter *regionFilter }{ MaxTotal: maxTotal, Data: data, Name: filter.name, + Filter: filter, }) if err != nil { http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) @@ -748,8 +751,9 @@ func taskMatches(t *taskDesc, text string) bool { } type regionFilter struct { - name string - cond []func(regionTypeID, regionDesc) bool + name string + params url.Values + cond []func(regionTypeID, regionDesc) bool } func (f *regionFilter) match(id regionTypeID, s regionDesc) bool { @@ -768,6 +772,7 @@ func newRegionFilter(r *http.Request) (*regionFilter, error) { var name []string var conditions []func(regionTypeID, regionDesc) bool + filterParams := make(url.Values) param := r.Form if typ, ok := param["type"]; ok && len(typ) > 0 { @@ -775,12 +780,15 @@ func newRegionFilter(r *http.Request) (*regionFilter, error) { conditions = append(conditions, func(id regionTypeID, s regionDesc) bool { return id.Type == typ[0] }) + filterParams.Add("type", typ[0]) } if pc, err := strconv.ParseUint(r.FormValue("pc"), 16, 64); err == nil { - name = append(name, fmt.Sprintf("pc=%x", pc)) + encPC := fmt.Sprintf("%x", pc) + name = append(name, "pc="+encPC) conditions = append(conditions, func(id regionTypeID, s regionDesc) bool { return id.Frame.PC == pc }) + filterParams.Add("pc", encPC) } if lat, err := time.ParseDuration(r.FormValue("latmin")); err == nil { @@ -788,15 +796,21 @@ func newRegionFilter(r *http.Request) (*regionFilter, error) { conditions = append(conditions, func(_ regionTypeID, s regionDesc) bool { return s.duration() >= lat }) + filterParams.Add("latmin", lat.String()) } if lat, err := time.ParseDuration(r.FormValue("latmax")); err == nil { name = append(name, fmt.Sprintf("latency <= %s", lat)) conditions = append(conditions, func(_ regionTypeID, s regionDesc) bool { return s.duration() <= lat }) + filterParams.Add("latmax", lat.String()) } - return ®ionFilter{name: strings.Join(name, ","), cond: conditions}, nil + return ®ionFilter{ + name: strings.Join(name, ","), + cond: conditions, + params: filterParams, + }, nil } type durationHistogram struct { @@ -946,7 +960,7 @@ var templUserRegionTypes = template.Must(template.New("").Parse(` {{range $}} <tr> <td>{{.Type}}<br>{{.Frame.Fn}}<br>{{.Frame.File}}:{{.Frame.Line}}</td> - <td><a href="/userregion?type={{.Type}}&pc={{.Frame.PC}}">{{.Histogram.Count}}</a></td> + <td><a href="/userregion?type={{.Type}}&pc={{.Frame.PC | printf "%x"}}">{{.Histogram.Count}}</a></td> <td>{{.Histogram.ToHTML (.UserRegionURL)}}</td> </tr> {{end}} @@ -1181,14 +1195,27 @@ var templUserRegionType = template.Must(template.New("").Funcs(template.FuncMap{ } return 0 }, + "filterParams": func(f *regionFilter) template.URL { + return template.URL(f.params.Encode()) + }, }).Parse(` <!DOCTYPE html> -<title>Goroutine {{.Name}}</title> +<title>User Region {{.Name}}</title> <style> th { background-color: #050505; color: #fff; } +th.total-time, +th.exec-time, +th.io-time, +th.block-time, +th.syscall-time, +th.sched-time, +th.sweep-time, +th.pause-time { + cursor: pointer; +} table { border-collapse: collapse; } @@ -1235,19 +1262,28 @@ function reloadTable(key, value) { <h2>{{.Name}}</h2> +{{ with $p := filterParams .Filter}} +<table class="summary"> + <tr><td>Network Wait Time:</td><td> <a href="/regionio?{{$p}}">graph</a><a href="/regionio?{{$p}}&raw=1" download="io.profile">(download)</a></td></tr> + <tr><td>Sync Block Time:</td><td> <a href="/regionblock?{{$p}}">graph</a><a href="/regionblock?{{$p}}&raw=1" download="block.profile">(download)</a></td></tr> + <tr><td>Blocking Syscall Time:</td><td> <a href="/regionsyscall?{{$p}}">graph</a><a href="/regionsyscall?{{$p}}&raw=1" download="syscall.profile">(download)</a></td></tr> + <tr><td>Scheduler Wait Time:</td><td> <a href="/regionsched?{{$p}}">graph</a><a href="/regionsched?{{$p}}&raw=1" download="sched.profile">(download)</a></td></tr> +</table> +{{ end }} +<p> <table class="details"> <tr> <th> Goroutine </th> <th> Task </th> -<th onclick="reloadTable('sortby', 'TotalTime')"> Total</th> +<th onclick="reloadTable('sortby', 'TotalTime')" class="total-time"> Total</th> <th></th> <th onclick="reloadTable('sortby', 'ExecTime')" class="exec-time"> Execution</th> <th onclick="reloadTable('sortby', 'IOTime')" class="io-time"> Network wait</th> <th onclick="reloadTable('sortby', 'BlockTime')" class="block-time"> Sync block </th> <th onclick="reloadTable('sortby', 'SyscallTime')" class="syscall-time"> Blocking syscall</th> <th onclick="reloadTable('sortby', 'SchedWaitTime')" class="sched-time"> Scheduler wait</th> -<th onclick="reloadTable('sortby', 'SweepTime')"> GC sweeping</th> -<th onclick="reloadTable('sortby', 'GCTime')"> GC pause</th> +<th onclick="reloadTable('sortby', 'SweepTime')" class="sweep-time"> GC sweeping</th> +<th onclick="reloadTable('sortby', 'GCTime')" class="pause-time"> GC pause</th> </tr> {{range .Data}} <tr> @@ -1274,4 +1310,5 @@ function reloadTable(key, value) { </tr> {{end}} </table> +</p> `)) diff --git a/src/cmd/trace/goroutines.go b/src/cmd/trace/goroutines.go index 100891d64e..74d1b0a11d 100644 --- a/src/cmd/trace/goroutines.go +++ b/src/cmd/trace/goroutines.go @@ -193,6 +193,16 @@ th { background-color: #050505; color: #fff; } +th.total-time, +th.exec-time, +th.io-time, +th.block-time, +th.syscall-time, +th.sched-time, +th.sweep-time, +th.pause-time { + cursor: pointer; +} table { border-collapse: collapse; } @@ -250,15 +260,15 @@ function reloadTable(key, value) { <table class="details"> <tr> <th> Goroutine</th> -<th onclick="reloadTable('sortby', 'TotalTime')"> Total</th> +<th onclick="reloadTable('sortby', 'TotalTime')" class="total-time"> Total</th> <th></th> <th onclick="reloadTable('sortby', 'ExecTime')" class="exec-time"> Execution</th> <th onclick="reloadTable('sortby', 'IOTime')" class="io-time"> Network wait</th> <th onclick="reloadTable('sortby', 'BlockTime')" class="block-time"> Sync block </th> <th onclick="reloadTable('sortby', 'SyscallTime')" class="syscall-time"> Blocking syscall</th> <th onclick="reloadTable('sortby', 'SchedWaitTime')" class="sched-time"> Scheduler wait</th> -<th onclick="reloadTable('sortby', 'SweepTime')"> GC sweeping</th> -<th onclick="reloadTable('sortby', 'GCTime')"> GC pause</th> +<th onclick="reloadTable('sortby', 'SweepTime')" class="sweep-time"> GC sweeping</th> +<th onclick="reloadTable('sortby', 'GCTime')" class="pause-time"> GC pause</th> </tr> {{range .GList}} <tr> |