Dump pprof when orbit is given a SIGUSR1. Fixes #8456 (#8485)

Co-authored-by: Roberto Dip <me@roperzh.com>
This commit is contained in:
Artemis Tosini 2022-10-28 16:39:47 -04:00 committed by GitHub
parent c51927e873
commit a0b11a29d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 0 deletions

View file

@ -0,0 +1,2 @@
- On Unix systems, dump pprof data into a `profiles` directory in the orbit root dir
when receiving a SIGUSR1. This is to assist debugging for memory leaks

View file

@ -666,6 +666,8 @@ func main() {
defer cancel()
g.Add(signalHandler(ctx))
go sigusrListener(c.String("root-dir"))
if err := g.Run(); err != nil {
log.Error().Err(err).Msg("unexpected exit")
}

View file

@ -3,13 +3,86 @@
package main
import (
"archive/tar"
"bytes"
"compress/gzip"
"context"
"fmt"
"os"
"os/signal"
"path"
"runtime/pprof"
"syscall"
"time"
"github.com/fleetdm/fleet/v4/orbit/pkg/constant"
"github.com/fleetdm/fleet/v4/pkg/secure"
"github.com/oklog/run"
"github.com/rs/zerolog/log"
)
func signalHandler(ctx context.Context) (execute func() error, interrupt func(error)) {
return run.SignalHandler(ctx, os.Interrupt, os.Kill, syscall.SIGTERM)
}
func sigusrListener(rootDir string) {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGUSR1)
for {
<-c
if err := dumpProf(rootDir); err != nil {
log.Warn().Err(err).Msg("unable to create pprof")
}
}
}
func dumpProf(rootDir string) error {
if err := secure.MkdirAll(path.Join(rootDir, "profiles"), constant.DefaultDirMode); err != nil {
return err
}
now := time.Now()
// We can't use ISO 8601/RFC 3339 because NTFS and FAT do not allow colons in filenames
timestamp := now.UTC().Format("2006-01-02T15-04-05")
out, err := os.Create(path.Join(rootDir, "profiles", fmt.Sprintf("profiles-%s.tar.gz", timestamp)))
if err != nil {
return err
}
defer out.Close()
gw := gzip.NewWriter(out)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
buf := new(bytes.Buffer)
for _, profile := range pprof.Profiles() {
err = profile.WriteTo(buf, 0)
if err != nil {
return err
}
header := tar.Header{
Typeflag: tar.TypeReg,
Name: fmt.Sprintf("%s.pprof", profile.Name()),
Size: int64(buf.Len()),
Mode: 0o664,
ModTime: now,
AccessTime: now,
ChangeTime: now,
}
err = tw.WriteHeader(&header)
if err != nil {
return err
}
_, err = buf.WriteTo(tw)
if err != nil {
return err
}
buf.Reset()
}
return nil
}

View file

@ -10,3 +10,7 @@ import (
func signalHandler(ctx context.Context) (execute func() error, interrupt func(error)) {
return run.SignalHandler(ctx, os.Interrupt, os.Kill)
}
func sigusrListener(rootDir string) error {
return nil
}