github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/pkg/stack/stackdump.go (about) 1 package stack // import "github.com/Prakhar-Agarwal-byte/moby/pkg/stack" 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strings" 9 "time" 10 11 "github.com/pkg/errors" 12 ) 13 14 const stacksLogNameTemplate = "goroutine-stacks-%s.log" 15 16 // Dump outputs the runtime stack to os.StdErr. 17 func Dump() { 18 _ = dump(os.Stderr) 19 } 20 21 // DumpToFile appends the runtime stack into a file named "goroutine-stacks-<timestamp>.log" 22 // in dir and returns the full path to that file. If no directory name is 23 // provided, it outputs to os.Stderr. 24 func DumpToFile(dir string) (string, error) { 25 var f *os.File 26 if dir != "" { 27 path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.ReplaceAll(time.Now().Format(time.RFC3339), ":", ""))) 28 var err error 29 f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o666) 30 if err != nil { 31 return "", errors.Wrap(err, "failed to open file to write the goroutine stacks") 32 } 33 defer f.Close() 34 defer f.Sync() 35 } else { 36 f = os.Stderr 37 } 38 return f.Name(), dump(f) 39 } 40 41 func dump(f *os.File) error { 42 var ( 43 buf []byte 44 stackSize int 45 ) 46 bufferLen := 16384 47 for stackSize == len(buf) { 48 buf = make([]byte, bufferLen) 49 stackSize = runtime.Stack(buf, true) 50 bufferLen *= 2 51 } 52 buf = buf[:stackSize] 53 if _, err := f.Write(buf); err != nil { 54 return errors.Wrap(err, "failed to write goroutine stacks") 55 } 56 return nil 57 }