Skip to content

Commit 82b0993

Browse files
committed
Add stacktrace view to monitor page
Using the pprof labels we can now add a stacktrace which can show these labels and name go-routines by the labels if there is a description set. Signed-off-by: Andrew Thornton <[email protected]>
1 parent 5fe764b commit 82b0993

File tree

7 files changed

+110
-4
lines changed

7 files changed

+110
-4
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ require (
4242
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
4343
github.com/golang-jwt/jwt/v4 v4.3.0
4444
github.com/google/go-github/v39 v39.2.0
45+
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1
4546
github.com/google/uuid v1.3.0
4647
github.com/gorilla/feeds v1.1.1
4748
github.com/gorilla/sessions v1.2.1

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,7 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
760760
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
761761
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
762762
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
763+
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
763764
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
764765
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
765766
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=

options/locale/locale_en-US.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2812,6 +2812,7 @@ monitor.next = Next Time
28122812
monitor.previous = Previous Time
28132813
monitor.execute_times = Executions
28142814
monitor.process = Running Processes
2815+
monitor.stacktrace = Stacktraces
28152816
monitor.desc = Description
28162817
monitor.start = Start Time
28172818
monitor.execute_time = Execution Time

routers/web/admin/admin.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ package admin
77

88
import (
99
"fmt"
10+
"io"
1011
"net/http"
1112
"net/url"
1213
"os"
1314
"runtime"
15+
"runtime/pprof"
1416
"strconv"
1517
"strings"
1618
"time"
1719

20+
"github.com/google/pprof/profile"
21+
1822
"code.gitea.io/gitea/models"
1923
"code.gitea.io/gitea/modules/base"
2024
"code.gitea.io/gitea/modules/context"
@@ -35,10 +39,11 @@ import (
3539
)
3640

3741
const (
38-
tplDashboard base.TplName = "admin/dashboard"
39-
tplConfig base.TplName = "admin/config"
40-
tplMonitor base.TplName = "admin/monitor"
41-
tplQueue base.TplName = "admin/queue"
42+
tplDashboard base.TplName = "admin/dashboard"
43+
tplConfig base.TplName = "admin/config"
44+
tplMonitor base.TplName = "admin/monitor"
45+
tplStacktrace base.TplName = "admin/stacktrace"
46+
tplQueue base.TplName = "admin/queue"
4247
)
4348

4449
var sysStatus struct {
@@ -329,9 +334,42 @@ func Monitor(ctx *context.Context) {
329334
ctx.Data["Processes"] = process.GetManager().Processes(true)
330335
ctx.Data["Entries"] = cron.ListTasks()
331336
ctx.Data["Queues"] = queue.GetManager().ManagedQueues()
337+
338+
reader, writer := io.Pipe()
339+
defer reader.Close()
340+
go func() {
341+
err := pprof.Lookup("goroutine").WriteTo(writer, 0)
342+
writer.CloseWithError(err)
343+
}()
344+
p, err := profile.Parse(reader)
345+
jP, _ := json.MarshalIndent(p, "", " ")
346+
log.Info("%v, %v", string(jP), err)
347+
332348
ctx.HTML(http.StatusOK, tplMonitor)
333349
}
334350

351+
// GoroutineStacktrace show admin monitor goroutines page
352+
func GoroutineStacktrace(ctx *context.Context) {
353+
ctx.Data["Title"] = ctx.Tr("admin.monitor")
354+
ctx.Data["PageIsAdmin"] = true
355+
ctx.Data["PageIsAdminMonitor"] = true
356+
357+
reader, writer := io.Pipe()
358+
defer reader.Close()
359+
go func() {
360+
err := pprof.Lookup("goroutine").WriteTo(writer, 0)
361+
writer.CloseWithError(err)
362+
}()
363+
p, err := profile.Parse(reader)
364+
if err != nil {
365+
ctx.ServerError("GoroutineStacktrace", err)
366+
return
367+
}
368+
ctx.Data["Profile"] = p
369+
370+
ctx.HTML(http.StatusOK, tplStacktrace)
371+
}
372+
335373
// MonitorCancel cancels a process
336374
func MonitorCancel(ctx *context.Context) {
337375
pid := ctx.Params("pid")

routers/web/web.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ func RegisterRoutes(m *web.Route) {
408408
m.Post("/config/test_mail", admin.SendTestMail)
409409
m.Group("/monitor", func() {
410410
m.Get("", admin.Monitor)
411+
m.Get("/stacktrace", admin.GoroutineStacktrace)
411412
m.Post("/cancel/{pid}", admin.MonitorCancel)
412413
m.Group("/queue/{qid}", func() {
413414
m.Get("", admin.Queue)

templates/admin/process.tmpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<h4 class="ui top attached header">
22
{{.i18n.Tr "admin.monitor.process"}}
3+
<div class="ui right">
4+
<a class="ui blue tiny button" href="{{AppSubUrl}}/admin/monitor/stacktrace">{{.i18n.Tr "admin.monitor.stacktrace"}}</a>
5+
</div>
36
</h4>
47
<div class="ui attached segment">
58
<div class="ui relaxed divided list">

templates/admin/stacktrace.tmpl

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{{template "base/head" .}}
2+
<div class="page-content admin monitor">
3+
{{template "admin/navbar" .}}
4+
<div class="ui container">
5+
{{template "base/alert" .}}
6+
<h4 class="ui top attached header">
7+
{{.i18n.Tr "admin.monitor.stacktrace"}}
8+
<div class="ui right">
9+
<a class="ui blue tiny button" href="{{AppSubUrl}}/admin/monitor">{{.i18n.Tr "admin.monitor"}}</a>
10+
</div>
11+
</h4>
12+
<div class="ui attached segment">
13+
<div class="ui relaxed divided list">
14+
{{range .Profile.Sample}}
15+
<div class="item">
16+
<div class="df ac">
17+
<div class="content f1">
18+
<details><summary>
19+
<div class="dif header ml-3">{{if index .Label "process-description"}}<span class="icon mr-3">{{svg "octicon-terminal" 16 }}</span><div class="mr-3">{{index (index .Label "process-description") 0}} ({{index (index .Label "pid") 0 }})</div>{{else}}<span class="icon mr-3">{{svg "octicon-cpu" 16 }}</span><div class="mr-3"><code>{{(index (index .Location (Subtract (len .Location) 1)).Line 0).Function.Name}}</code></div>{{end}}{{if gt (index .Value 0) 1}}<div class="mr-3"> * {{index .Value 0}}</div>{{end}}</div>
20+
{{range $key, $value := .Label}}
21+
{{if ne $key "process-description" }}
22+
<div class="ui label">{{$key}}<div class="detail">{{index $value 0}}</div></div>
23+
{{end}}
24+
{{end}}
25+
</summary>
26+
27+
<div class="list">
28+
{{range .Location}}
29+
<div class="item df ac">
30+
<span class="icon mr-4">{{svg "octicon-dot-fill" 16 }}</span>
31+
<div class="content f1">
32+
<div class="header"><code>{{(index .Line 0).Function.Name}}</code></div>
33+
<div class="description"><code>{{(index .Line 0).Function.Filename}}:{{(index .Line 0).Line}}</code></div>
34+
</div>
35+
</div>
36+
{{end}}
37+
</div>
38+
</details>
39+
</div>
40+
<div>
41+
</div>
42+
</div>
43+
</div>
44+
{{end}}
45+
</div>
46+
</div>
47+
</div>
48+
</div>
49+
<div class="ui small basic delete modal">
50+
<div class="ui icon header">
51+
{{svg "octicon-x" 16 "close inside"}}
52+
{{.i18n.Tr "admin.monitor.process.cancel"}}
53+
</div>
54+
<div class="content">
55+
<p>{{$.i18n.Tr "admin.monitor.process.cancel_notices" `<span class="name"></span>` | Safe}}</p>
56+
<p>{{$.i18n.Tr "admin.monitor.process.cancel_desc"}}</p>
57+
</div>
58+
{{template "base/delete_modal_actions" .}}
59+
</div>
60+
61+
{{template "base/footer" .}}

0 commit comments

Comments
 (0)