Skip to content

Commit a08537a

Browse files
committed
Add more process descriptors to goroutines
Signed-off-by: Andrew Thornton <[email protected]>
1 parent 82b0993 commit a08537a

File tree

12 files changed

+71
-27
lines changed

12 files changed

+71
-27
lines changed

modules/context/private.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,6 @@ func PrivateContexter() func(http.Handler) http.Handler {
7979
// the underlying request has timed out from the ssh/http push
8080
func OverrideContext(ctx *PrivateContext) (cancel context.CancelFunc) {
8181
// We now need to override the request context as the base for our work because even if the request is cancelled we have to continue this work
82-
ctx.Override, _, cancel = process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("PrivateContext: %s", ctx.Req.RequestURI))
82+
ctx.Override, _, cancel = process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), fmt.Sprintf("PrivateContext: %s", ctx.Req.RequestURI), process.RequestProcessType)
8383
return
8484
}

modules/eventsource/manager_run.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"code.gitea.io/gitea/models"
1212
"code.gitea.io/gitea/modules/graceful"
1313
"code.gitea.io/gitea/modules/log"
14+
"code.gitea.io/gitea/modules/process"
1415
"code.gitea.io/gitea/modules/setting"
1516
"code.gitea.io/gitea/modules/timeutil"
1617
)
@@ -25,6 +26,9 @@ func (m *Manager) Init() {
2526

2627
// Run runs the manager within a provided context
2728
func (m *Manager) Run(ctx context.Context) {
29+
ctx, _, finished := process.GetManager().AddTypedContext(ctx, "EventSource", process.SystemProcessType)
30+
defer finished()
31+
2832
then := timeutil.TimeStampNow().Add(-2)
2933
timer := time.NewTicker(setting.UI.Notification.EventSourceUpdateTime)
3034
loop:

modules/graceful/manager_unix.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"time"
1919

2020
"code.gitea.io/gitea/modules/log"
21+
"code.gitea.io/gitea/modules/process"
2122
"code.gitea.io/gitea/modules/setting"
2223
)
2324

@@ -73,7 +74,7 @@ func (g *Manager) start(ctx context.Context) {
7374

7475
// Set the running state & handle signals
7576
g.setState(stateRunning)
76-
go g.handleSignals(ctx)
77+
go g.handleSignals(g.managerCtx)
7778

7879
// Handle clean up of unused provided listeners and delayed start-up
7980
startupDone := make(chan struct{})
@@ -112,6 +113,9 @@ func (g *Manager) start(ctx context.Context) {
112113
}
113114

114115
func (g *Manager) handleSignals(ctx context.Context) {
116+
ctx, _, finished := process.GetManager().AddTypedContext(ctx, "Graceful: HandleSignals", process.SystemProcessType)
117+
defer finished()
118+
115119
signalChannel := make(chan os.Signal, 1)
116120

117121
signal.Notify(

modules/log/event.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
package log
66

77
import (
8+
"context"
89
"fmt"
910
"sync"
1011
"time"
12+
13+
"code.gitea.io/gitea/modules/process"
1114
)
1215

1316
// Event represents a logging event
@@ -34,6 +37,7 @@ type EventLogger interface {
3437

3538
// ChannelledLog represents a cached channel to a LoggerProvider
3639
type ChannelledLog struct {
40+
parent string
3741
name string
3842
provider string
3943
queue chan *Event
@@ -44,9 +48,10 @@ type ChannelledLog struct {
4448
}
4549

4650
// NewChannelledLog a new logger instance with given logger provider and config.
47-
func NewChannelledLog(name, provider, config string, bufferLength int64) (*ChannelledLog, error) {
51+
func NewChannelledLog(parent, name, provider, config string, bufferLength int64) (*ChannelledLog, error) {
4852
if log, ok := providers[provider]; ok {
4953
l := &ChannelledLog{
54+
parent: parent,
5055
queue: make(chan *Event, bufferLength),
5156
flush: make(chan bool),
5257
close: make(chan bool),
@@ -66,6 +71,8 @@ func NewChannelledLog(name, provider, config string, bufferLength int64) (*Chann
6671

6772
// Start processing the ChannelledLog
6873
func (l *ChannelledLog) Start() {
74+
_, _, cancel := process.GetManager().AddTypedContext(context.Background(), fmt.Sprintf("Logger: %s.%s(%s)", l.parent, l.name, l.provider), process.SystemProcessType)
75+
defer cancel()
6976
for {
7077
select {
7178
case event, ok := <-l.queue:
@@ -277,6 +284,9 @@ func (m *MultiChannelledLog) Start() {
277284
m.rwmutex.Unlock()
278285
return
279286
}
287+
_, _, cancel := process.GetManager().AddTypedContext(context.Background(), fmt.Sprintf("Logger: %s", m.name), process.SystemProcessType)
288+
defer cancel()
289+
280290
m.started = true
281291
m.rwmutex.Unlock()
282292
paused := false

modules/log/multichannel.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func newLogger(name string, buffer int64) *MultiChannelledLogger {
3131

3232
// SetLogger sets new logger instance with given logger provider and config.
3333
func (l *MultiChannelledLogger) SetLogger(name, provider, config string) error {
34-
eventLogger, err := NewChannelledLog(name, provider, config, l.bufferLength)
34+
eventLogger, err := NewChannelledLog(l.name, name, provider, config, l.bufferLength)
3535
if err != nil {
3636
return fmt.Errorf("Failed to create sublogger (%s): %v", name, err)
3737
}

modules/process/manager.go

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,26 @@ func GetManager() *Manager {
6969
func (pm *Manager) AddContext(parent context.Context, description string) (ctx context.Context, cancel context.CancelFunc, finished FinishedFunc) {
7070
ctx, cancel = context.WithCancel(parent)
7171

72-
ctx, pid, finished := pm.Add(ctx, description, cancel)
72+
ctx, pid, finished := pm.Add(ctx, description, cancel, NormalProcessType)
73+
74+
return &Context{
75+
Context: ctx,
76+
pid: pid,
77+
}, cancel, finished
78+
}
79+
80+
// AddTypedContext creates a new context and adds it as a process. Once the process is finished, finished must be called
81+
// to remove the process from the process table. It should not be called until the process is finished but must always be called.
82+
//
83+
// cancel should be used to cancel the returned context, however it will not remove the process from the process table.
84+
// finished will cancel the returned context and remove it from the process table.
85+
//
86+
// Most processes will not need to use the cancel function but there will be cases whereby you want to cancel the process but not immediately remove it from the
87+
// process table.
88+
func (pm *Manager) AddTypedContext(parent context.Context, description, processType string) (ctx context.Context, cancel context.CancelFunc, finished FinishedFunc) {
89+
ctx, cancel = context.WithCancel(parent)
90+
91+
ctx, pid, finished := pm.Add(ctx, description, cancel, processType)
7392

7493
return &Context{
7594
Context: ctx,
@@ -88,7 +107,7 @@ func (pm *Manager) AddContext(parent context.Context, description string) (ctx c
88107
func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Duration, description string) (ctx context.Context, cancel context.CancelFunc, finshed FinishedFunc) {
89108
ctx, cancel = context.WithTimeout(parent, timeout)
90109

91-
ctx, pid, finshed := pm.Add(ctx, description, cancel)
110+
ctx, pid, finshed := pm.Add(ctx, description, cancel, NormalProcessType)
92111

93112
return &Context{
94113
Context: ctx,
@@ -97,7 +116,7 @@ func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Durati
97116
}
98117

99118
// Add create a new process
100-
func (pm *Manager) Add(ctx context.Context, description string, cancel context.CancelFunc) (context.Context, IDType, FinishedFunc) {
119+
func (pm *Manager) Add(ctx context.Context, description string, cancel context.CancelFunc, processType string) (context.Context, IDType, FinishedFunc) {
101120
parentPID := GetParentPID(ctx)
102121

103122
pm.mutex.Lock()
@@ -114,6 +133,7 @@ func (pm *Manager) Add(ctx context.Context, description string, cancel context.C
114133
Description: description,
115134
Start: start,
116135
Cancel: cancel,
136+
Type: processType,
117137
}
118138

119139
finished := func() {
@@ -128,7 +148,7 @@ func (pm *Manager) Add(ctx context.Context, description string, cancel context.C
128148
pm.processes[pid] = process
129149
pm.mutex.Unlock()
130150

131-
pprofCtx := pprof.WithLabels(ctx, pprof.Labels("process-description", description, "ppid", string(parentPID), "pid", string(pid)))
151+
pprofCtx := pprof.WithLabels(ctx, pprof.Labels("process-description", description, "ppid", string(parentPID), "pid", string(pid), "process-type", processType))
132152
pprof.SetGoroutineLabels(pprofCtx)
133153

134154
return pprofCtx, pid, finished
@@ -191,7 +211,10 @@ func (pm *Manager) Processes(onlyRoots bool) []*Process {
191211
processes := make([]*Process, 0, len(pm.processes))
192212
if onlyRoots {
193213
for _, process := range pm.processes {
194-
if _, has := pm.processes[process.ParentPID]; !has {
214+
if process.Type == SystemProcessType {
215+
continue
216+
}
217+
if parent, has := pm.processes[process.ParentPID]; !has || parent.Type == SystemProcessType {
195218
processes = append(processes, process)
196219
}
197220
}

modules/process/process.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ import (
1010
"time"
1111
)
1212

13+
var (
14+
SystemProcessType = "system"
15+
RequestProcessType = "request"
16+
NormalProcessType = "normal"
17+
)
18+
1319
// Process represents a working process inheriting from Gitea.
1420
type Process struct {
1521
PID IDType // Process ID, not system one.
1622
ParentPID IDType
1723
Description string
1824
Start time.Time
1925
Cancel context.CancelFunc
26+
Type string
2027

2128
lock sync.Mutex
2229
children []*Process

routers/common/middleware.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func Middlewares() []func(http.Handler) http.Handler {
2727
// First of all escape the URL RawPath to ensure that all routing is done using a correctly escaped URL
2828
req.URL.RawPath = req.URL.EscapedPath()
2929

30-
ctx, _, finished := process.GetManager().AddContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI))
30+
ctx, _, finished := process.GetManager().AddTypedContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI), process.RequestProcessType)
3131
defer finished()
3232
next.ServeHTTP(context.NewResponse(resp), req.WithContext(ctx))
3333
})

routers/web/admin/admin.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -335,16 +335,6 @@ func Monitor(ctx *context.Context) {
335335
ctx.Data["Entries"] = cron.ListTasks()
336336
ctx.Data["Queues"] = queue.GetManager().ManagedQueues()
337337

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-
348338
ctx.HTML(http.StatusOK, tplMonitor)
349339
}
350340

@@ -358,7 +348,7 @@ func GoroutineStacktrace(ctx *context.Context) {
358348
defer reader.Close()
359349
go func() {
360350
err := pprof.Lookup("goroutine").WriteTo(writer, 0)
361-
writer.CloseWithError(err)
351+
_ = writer.CloseWithError(err)
362352
}()
363353
p, err := profile.Parse(reader)
364354
if err != nil {

services/webhook/deliver.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@ import (
2424
"code.gitea.io/gitea/modules/graceful"
2525
"code.gitea.io/gitea/modules/hostmatcher"
2626
"code.gitea.io/gitea/modules/log"
27+
"code.gitea.io/gitea/modules/process"
2728
"code.gitea.io/gitea/modules/proxy"
2829
"code.gitea.io/gitea/modules/setting"
2930

3031
"github.com/gobwas/glob"
3132
)
3233

3334
// Deliver deliver hook task
34-
func Deliver(t *webhook_model.HookTask) error {
35+
func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
3536
w, err := webhook_model.GetWebhookByID(t.HookID)
3637
if err != nil {
3738
return err
@@ -172,7 +173,7 @@ func Deliver(t *webhook_model.HookTask) error {
172173
return fmt.Errorf("webhook task skipped (webhooks disabled): [%d]", t.ID)
173174
}
174175

175-
resp, err := webhookHTTPClient.Do(req.WithContext(graceful.GetManager().ShutdownContext()))
176+
resp, err := webhookHTTPClient.Do(req.WithContext(ctx))
176177
if err != nil {
177178
t.ResponseInfo.Body = fmt.Sprintf("Delivery: %v", err)
178179
return err
@@ -204,6 +205,8 @@ func DeliverHooks(ctx context.Context) {
204205
return
205206
default:
206207
}
208+
ctx, _, finished := process.GetManager().AddTypedContext(ctx, "DeliverHooks", process.SystemProcessType)
209+
defer finished()
207210
tasks, err := webhook_model.FindUndeliveredHookTasks()
208211
if err != nil {
209212
log.Error("DeliverHooks: %v", err)
@@ -217,7 +220,7 @@ func DeliverHooks(ctx context.Context) {
217220
return
218221
default:
219222
}
220-
if err = Deliver(t); err != nil {
223+
if err = Deliver(ctx, t); err != nil {
221224
log.Error("deliver: %v", err)
222225
}
223226
}
@@ -249,7 +252,7 @@ func DeliverHooks(ctx context.Context) {
249252
return
250253
default:
251254
}
252-
if err = Deliver(t); err != nil {
255+
if err = Deliver(ctx, t); err != nil {
253256
log.Error("deliver: %v", err)
254257
}
255258
}

templates/admin/process-row.tmpl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
<div class="item">
22
<div class="df ac">
3+
<div class="icon ml-3 mr-3">{{if eq .Process.Type "request"}}{{svg "octicon-globe" 16 }}{{else if eq .Process.Type "system"}}{{svg "octicon-cpu" 16 }}{{else}}{{svg "octicon-terminal" 16 }}{{end}}</div>
34
<div class="content f1">
45
<div class="header">{{.Process.Description}}</div>
56
<div class="description"><span title="{{DateFmtLong .Process.Start}}">{{TimeSince .Process.Start .root.i18n.Lang}}</span></div>
67
</div>
78
<div>
8-
<a class="delete-button icon" href="" data-url="{{.root.Link}}/cancel/{{.Process.PID}}" data-id="{{.Process.PID}}" data-name="{{.Process.Description}}">{{svg "octicon-trash" 16 "text-red"}}</a>
9+
{{if ne .Process.Type "system"}}
10+
<a class="delete-button icon" href="" data-url="{{.root.Link}}/cancel/{{.Process.PID}}" data-id="{{.Process.PID}}" data-name="{{.Process.Description}}">{{svg "octicon-trash" 16 "text-red"}}</a>
11+
{{end}}
912
</div>
1013
</div>
1114

templates/admin/stacktrace.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<div class="df ac">
1717
<div class="content f1">
1818
<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>
19+
<div class="dif header ml-3" style="max-width: 95%">{{if index .Label "process-description"}}<span class="icon mr-3">{{if eq (index (index .Label "process-type") 0) "request"}}{{svg "octicon-globe" 16 }}{{else if eq (index (index .Label "process-type") 0) "system"}}{{svg "octicon-cpu" 16 }}{{else}}{{svg "octicon-terminal" 16 }}{{end}}</span><div class="mr-3">{{index (index .Label "process-description") 0}}</div>{{else}}<span class="icon mr-3">{{svg "octicon-code" 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>
2020
{{range $key, $value := .Label}}
2121
{{if ne $key "process-description" }}
2222
<div class="ui label">{{$key}}<div class="detail">{{index $value 0}}</div></div>

0 commit comments

Comments
 (0)