add profile option
This commit is contained in:
parent
160d5751ab
commit
d8ed784311
|
@ -117,15 +117,43 @@ func (p *Profile) HeapProfile(o *ProfileOpts, _ *struct{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Goroutine is an RPC stub which dumps out the stack trace for all running
|
||||
// GoroutineProfile is an RPC stub which dumps out the stack trace for all running
|
||||
// goroutines.
|
||||
func (p *Profile) Goroutine(o *ProfileOpts, _ *struct{}) error {
|
||||
func (p *Profile) GoroutineProfile(o *ProfileOpts, _ *struct{}) error {
|
||||
if len(o.FilePayload.Files) < 1 {
|
||||
return errNoOutput
|
||||
}
|
||||
output := o.FilePayload.Files[0]
|
||||
defer output.Close()
|
||||
if err := pprof.Lookup("goroutine").WriteTo(output, 2); err != nil {
|
||||
if err := pprof.Lookup("goroutine").WriteTo(output, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BlockProfile is an RPC stub which dumps out the stack trace that led to
|
||||
// blocking on synchronization primitives.
|
||||
func (p *Profile) BlockProfile(o *ProfileOpts, _ *struct{}) error {
|
||||
if len(o.FilePayload.Files) < 1 {
|
||||
return errNoOutput
|
||||
}
|
||||
output := o.FilePayload.Files[0]
|
||||
defer output.Close()
|
||||
if err := pprof.Lookup("block").WriteTo(output, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MutexProfile is an RPC stub which dumps out the stack trace of holders of
|
||||
// contended mutexes.
|
||||
func (p *Profile) MutexProfile(o *ProfileOpts, _ *struct{}) error {
|
||||
if len(o.FilePayload.Files) < 1 {
|
||||
return errNoOutput
|
||||
}
|
||||
output := o.FilePayload.Files[0]
|
||||
defer output.Close()
|
||||
if err := pprof.Lookup("mutex").WriteTo(output, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -101,11 +101,14 @@ const (
|
|||
|
||||
// Profiling related commands (see pprof.go for more details).
|
||||
const (
|
||||
StartCPUProfile = "Profile.StartCPUProfile"
|
||||
StopCPUProfile = "Profile.StopCPUProfile"
|
||||
HeapProfile = "Profile.HeapProfile"
|
||||
StartTrace = "Profile.StartTrace"
|
||||
StopTrace = "Profile.StopTrace"
|
||||
StartCPUProfile = "Profile.StartCPUProfile"
|
||||
StopCPUProfile = "Profile.StopCPUProfile"
|
||||
HeapProfile = "Profile.HeapProfile"
|
||||
GoroutineProfile = "Profile.GoroutineProfile"
|
||||
BlockProfile = "Profile.BlockProfile"
|
||||
MutexProfile = "Profile.MutexProfile"
|
||||
StartTrace = "Profile.StartTrace"
|
||||
StopTrace = "Profile.StopTrace"
|
||||
)
|
||||
|
||||
// Logging related commands (see logging.go for more details).
|
||||
|
|
|
@ -32,17 +32,20 @@ import (
|
|||
|
||||
// Debug implements subcommands.Command for the "debug" command.
|
||||
type Debug struct {
|
||||
pid int
|
||||
stacks bool
|
||||
signal int
|
||||
profileHeap string
|
||||
profileCPU string
|
||||
trace string
|
||||
strace string
|
||||
logLevel string
|
||||
logPackets string
|
||||
duration time.Duration
|
||||
ps bool
|
||||
pid int
|
||||
stacks bool
|
||||
signal int
|
||||
profileHeap string
|
||||
profileCPU string
|
||||
profileGoroutine string
|
||||
profileBlock string
|
||||
profileMutex string
|
||||
trace string
|
||||
strace string
|
||||
logLevel string
|
||||
logPackets string
|
||||
duration time.Duration
|
||||
ps bool
|
||||
}
|
||||
|
||||
// Name implements subcommands.Command.
|
||||
|
@ -66,6 +69,9 @@ func (d *Debug) SetFlags(f *flag.FlagSet) {
|
|||
f.BoolVar(&d.stacks, "stacks", false, "if true, dumps all sandbox stacks to the log")
|
||||
f.StringVar(&d.profileHeap, "profile-heap", "", "writes heap profile to the given file.")
|
||||
f.StringVar(&d.profileCPU, "profile-cpu", "", "writes CPU profile to the given file.")
|
||||
f.StringVar(&d.profileGoroutine, "profile-goroutine", "", "writes goroutine profile to the given file.")
|
||||
f.StringVar(&d.profileBlock, "profile-block", "", "writes block profile to the given file.")
|
||||
f.StringVar(&d.profileMutex, "profile-mutex", "", "writes mutex profile to the given file.")
|
||||
f.DurationVar(&d.duration, "duration", time.Second, "amount of time to wait for CPU and trace profiles")
|
||||
f.StringVar(&d.trace, "trace", "", "writes an execution trace to the given file.")
|
||||
f.IntVar(&d.signal, "signal", -1, "sends signal to the sandbox")
|
||||
|
@ -147,6 +153,42 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
|
|||
}
|
||||
log.Infof("Heap profile written to %q", d.profileHeap)
|
||||
}
|
||||
if d.profileGoroutine != "" {
|
||||
f, err := os.Create(d.profileGoroutine)
|
||||
if err != nil {
|
||||
return Errorf(err.Error())
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := c.Sandbox.GoroutineProfile(f); err != nil {
|
||||
return Errorf(err.Error())
|
||||
}
|
||||
log.Infof("Goroutine profile written to %q", d.profileGoroutine)
|
||||
}
|
||||
if d.profileBlock != "" {
|
||||
f, err := os.Create(d.profileBlock)
|
||||
if err != nil {
|
||||
return Errorf(err.Error())
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := c.Sandbox.BlockProfile(f); err != nil {
|
||||
return Errorf(err.Error())
|
||||
}
|
||||
log.Infof("Block profile written to %q", d.profileBlock)
|
||||
}
|
||||
if d.profileMutex != "" {
|
||||
f, err := os.Create(d.profileMutex)
|
||||
if err != nil {
|
||||
return Errorf(err.Error())
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := c.Sandbox.MutexProfile(f); err != nil {
|
||||
return Errorf(err.Error())
|
||||
}
|
||||
log.Infof("Mutex profile written to %q", d.profileMutex)
|
||||
}
|
||||
|
||||
delay := false
|
||||
if d.profileCPU != "" {
|
||||
|
|
|
@ -972,6 +972,66 @@ func (s *Sandbox) StopCPUProfile() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GoroutineProfile writes a goroutine profile to the given file.
|
||||
func (s *Sandbox) GoroutineProfile(f *os.File) error {
|
||||
log.Debugf("Goroutine profile %q", s.ID)
|
||||
conn, err := s.sandboxConnect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
opts := control.ProfileOpts{
|
||||
FilePayload: urpc.FilePayload{
|
||||
Files: []*os.File{f},
|
||||
},
|
||||
}
|
||||
if err := conn.Call(boot.GoroutineProfile, &opts, nil); err != nil {
|
||||
return fmt.Errorf("getting sandbox %q goroutine profile: %v", s.ID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BlockProfile writes a block profile to the given file.
|
||||
func (s *Sandbox) BlockProfile(f *os.File) error {
|
||||
log.Debugf("Block profile %q", s.ID)
|
||||
conn, err := s.sandboxConnect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
opts := control.ProfileOpts{
|
||||
FilePayload: urpc.FilePayload{
|
||||
Files: []*os.File{f},
|
||||
},
|
||||
}
|
||||
if err := conn.Call(boot.BlockProfile, &opts, nil); err != nil {
|
||||
return fmt.Errorf("getting sandbox %q block profile: %v", s.ID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MutexProfile writes a mutex profile to the given file.
|
||||
func (s *Sandbox) MutexProfile(f *os.File) error {
|
||||
log.Debugf("Mutex profile %q", s.ID)
|
||||
conn, err := s.sandboxConnect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
opts := control.ProfileOpts{
|
||||
FilePayload: urpc.FilePayload{
|
||||
Files: []*os.File{f},
|
||||
},
|
||||
}
|
||||
if err := conn.Call(boot.MutexProfile, &opts, nil); err != nil {
|
||||
return fmt.Errorf("getting sandbox %q mutex profile: %v", s.ID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartTrace start trace writing to the given file.
|
||||
func (s *Sandbox) StartTrace(f *os.File) error {
|
||||
log.Debugf("Trace start %q", s.ID)
|
||||
|
|
Loading…
Reference in New Issue