feat: add full goroutine stack dump (#8790)

This commit is contained in:
Gus Eggert 2022-03-16 09:42:22 -04:00 committed by GitHub
parent 04e7e9502e
commit 5e1b2248c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 0 deletions

View File

@ -24,6 +24,8 @@ fi
echo Collecting goroutine stacks
curl -s -o goroutines.stacks "$SOURCE_URL"'/debug/pprof/goroutine?debug=2'
curl -s -o goroutines.stacks.full "$SOURCE_URL"'/debug/stack'
echo Collecting goroutine profile
go tool pprof -symbolize=remote -svg -output goroutine.svg "$SOURCE_URL/debug/pprof/goroutine"

View File

@ -660,6 +660,7 @@ func serveHTTPApi(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, error
corehttp.VersionOption(),
defaultMux("/debug/vars"),
defaultMux("/debug/pprof/"),
defaultMux("/debug/stack"),
corehttp.MutexFractionOption("/debug/pprof-mutex/"),
corehttp.BlockProfileRateOption("/debug/pprof-block/"),
corehttp.MetricsScrapingOption("/debug/metrics/prometheus"),

15
cmd/ipfs/debug.go Normal file
View File

@ -0,0 +1,15 @@
package main
import (
"net/http"
"github.com/ipfs/go-ipfs/core/commands"
)
func init() {
http.HandleFunc("/debug/stack",
func(w http.ResponseWriter, _ *http.Request) {
_ = commands.WriteAllGoroutineStacks(w)
},
)
}

View File

@ -121,6 +121,25 @@ However, it could reveal:
},
}
func WriteAllGoroutineStacks(w io.Writer) error {
// this is based on pprof.writeGoroutineStacks, and removes the 64 MB limit
buf := make([]byte, 1<<20)
for i := 0; ; i++ {
n := runtime.Stack(buf, true)
if n < len(buf) {
buf = buf[:n]
break
}
// if len(buf) >= 64<<20 {
// // Filled 64 MB - stop there.
// break
// }
buf = make([]byte, 2*len(buf))
}
_, err := w.Write(buf)
return err
}
func writeProfiles(ctx context.Context, cpuProfileTime time.Duration, w io.Writer) error {
archive := zip.NewWriter(w)
@ -143,6 +162,17 @@ func writeProfiles(ctx context.Context, cpuProfileTime time.Duration, w io.Write
file: "heap.pprof",
}}
{
out, err := archive.Create("goroutines-all.stacks")
if err != nil {
return err
}
err = WriteAllGoroutineStacks(out)
if err != nil {
return err
}
}
for _, profile := range profiles {
prof := pprof.Lookup(profile.name)
out, err := archive.Create(profile.file)

View File

@ -61,4 +61,8 @@ test_expect_success "goroutines stacktrace is valid" '
grep -q "goroutine" "profiles/goroutines.stacks"
'
test_expect_success "full goroutines stacktrace is valid" '
grep -q "goroutine" "profiles/goroutines-all.stacks"
'
test_done