Skip to content

Commit

Permalink
gops: add Go execution trace support
Browse files Browse the repository at this point in the history
  • Loading branch information
rakyll committed Jan 20, 2017
1 parent 3fe5c6c commit 671bd43
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 8 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,15 @@ To enter the heap profile, run:
$ gops pprof-heap <pid>
```

#### 4. gc
#### 4. trace

gops allows you to start the runtime tracer for 5 seconds and examine the results.

```sh
$ gops trace <pid>
```

#### 5. gc

If you want to force run garbage collection on the target program, run the following command.
It will block until the GC is completed.
Expand All @@ -100,15 +108,15 @@ It will block until the GC is completed.
$ gops gc <pid>
```

#### 5. version
#### 6. version

gops reports the Go version the target program is built with, if you run the following:

```sh
$ gops version <pid>
```

#### 6. stats
#### 7. stats

To print the runtime statistics such as number of goroutines and `GOMAXPROCS`, run the following:

Expand Down
5 changes: 5 additions & 0 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
gosignal "os/signal"
"runtime"
"runtime/pprof"
"runtime/trace"
"strconv"
"sync"
"time"
Expand Down Expand Up @@ -189,6 +190,10 @@ func handle(conn net.Conn, msg []byte) error {
fmt.Fprintf(conn, "OS threads: %v\n", pprof.Lookup("threadcreate").Count())
fmt.Fprintf(conn, "GOMAXPROCS: %v\n", runtime.GOMAXPROCS(0))
fmt.Fprintf(conn, "num CPU: %v\n", runtime.NumCPU())
case signal.Trace:
trace.Start(conn)
time.Sleep(5 * time.Second)
trace.Stop()
}
return nil
}
45 changes: 40 additions & 5 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"os"
Expand All @@ -21,6 +22,7 @@ var cmds = map[string](func(pid int) error){
"pprof-heap": pprofHeap,
"pprof-cpu": pprofCPU,
"stats": stats,
"trace": trace,
}

func stackTrace(pid int) error {
Expand Down Expand Up @@ -49,6 +51,31 @@ func pprofCPU(pid int) error {
return pprof(pid, signal.CPUProfile)
}

func trace(pid int) error {
fmt.Println("Tracing now, will take 5 secs...")
out, err := cmd(pid, signal.Trace)
if err != nil {
return err
}
if len(out) == 0 {
return errors.New("nothing has traced")
}
tmpfile, err := ioutil.TempFile("", "trace")
if err != nil {
return err
}
defer os.Remove(tmpfile.Name())
if err := ioutil.WriteFile(tmpfile.Name(), out, 0); err != nil {
return err
}
cmd := exec.Command("go", "tool", "trace", tmpfile.Name())
cmd.Env = os.Environ()
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}

func pprof(pid int, p byte) error {
out, err := cmd(pid, p)
if err != nil {
Expand Down Expand Up @@ -96,20 +123,28 @@ func cmdWithPrint(pid int, c byte) error {
}

func cmd(pid int, c byte) ([]byte, error) {
port, err := internal.GetPort(pid)
conn, err := cmdLazy(pid, c)
if err != nil {
return nil, err
}
conn, err := net.Dial("tcp", "127.0.0.1:"+port)
all, err := ioutil.ReadAll(conn)
if err != nil {
return nil, err
}
if _, err := conn.Write([]byte{c}); err != nil {
return all, nil
}

func cmdLazy(pid int, c byte) (io.Reader, error) {
port, err := internal.GetPort(pid)
if err != nil {
return nil, err
}
all, err := ioutil.ReadAll(conn)
conn, err := net.Dial("tcp", "127.0.0.1:"+port)
if err != nil {
return nil, err
}
return all, nil
if _, err := conn.Write([]byte{c}); err != nil {
return nil, err
}
return conn, nil
}
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Commands:
help Prints this help text.
Profiling commands:
trace Runs the runtime tracer for 5 secs and launches "go tool trace".
pprof-heap Reads the heap profile and launches "go tool pprof".
pprof-cpu Reads the CPU profile and launches "go tool pprof".
Expand Down
3 changes: 3 additions & 0 deletions signal/signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ const (

// Stats returns Go runtime statistics such as number of goroutines, GOMAXPROCS, and NumCPU.
Stats = byte(0x7)

// Trace starts the Go execution tracer, waits 5 seconds and launches the trace tool.
Trace = byte(0x8)
)

0 comments on commit 671bd43

Please sign in to comment.