Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ func formatBytes(val uint64) string {
return fmt.Sprintf("%d bytes", val)
}

type fileConn interface {
File() (f *os.File, err error)
}

func handle(conn io.ReadWriter, msg []byte) error {
switch msg[0] {
case signal.StackTrace:
Expand Down Expand Up @@ -290,6 +294,19 @@ func handle(conn io.ReadWriter, msg []byte) error {
return err
}
fmt.Fprintf(conn, "New GC percent set to %v. Previous value was %v.\n", perc, debug.SetGCPercent(int(perc)))
case signal.WriteHeapDump:
fc, ok := conn.(fileConn)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What guarantees that you can perform this cast?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's implemented by both IPConn and UnixConn

if !ok {
return fmt.Errorf("unable to get file descriptor for connection: %T", conn)
}
f, err := fc.File()
if err != nil {
return err
}
defer f.Close()

runtime.GC()
debug.WriteHeapDump(f.Fd())
}
return nil
}
26 changes: 26 additions & 0 deletions internal/cmd/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ func AgentCommands() []*cobra.Command {
short: "Reads the CPU profile and launches \"go tool pprof\".",
fn: pprofCPU,
},
{
name: "heap-dump",
short: "writes the results of debug.WriteHeapDump to a file.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the other shorts are capitalised

Suggested change
short: "writes the results of debug.WriteHeapDump to a file.",
short: "Writes the results of debug.WriteHeapDump to a file.",

fn: heapDump,
},
{
name: "version",
short: "Prints the Go version used to build the program.",
Expand Down Expand Up @@ -249,6 +254,27 @@ func pprof(addr net.TCPAddr, p byte, prefix string) error {
return cmd.Run()
}

func heapDump(addr net.TCPAddr, params []string) error {
tmpDumpFile, err := os.CreateTemp("", "heap_dump")
if err != nil {
return err
}

out, err := cmd(addr, signal.WriteHeapDump)
if err != nil {
return err
}
if len(out) == 0 {
return errors.New("failed to read the dump")
}
if err := os.WriteFile(tmpDumpFile.Name(), out, 0); err != nil {
return err
}
fmt.Printf("Heap dump saved to: %s\n", tmpDumpFile.Name())

return nil
}

func stats(addr net.TCPAddr, _ []string) error {
return cmdWithPrint(addr, signal.Stats)
}
Expand Down
3 changes: 3 additions & 0 deletions signal/signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ const (

// SetGCPercent sets the garbage collection target percentage.
SetGCPercent = byte(0x10)

// WriteHeapDump writes the results of debug.WriteHeapDump to a file.
WriteHeapDump = byte(0x11)
)