Runs a crashing program and converts it to a dense text format like pp does.
()
| 27 | |
| 28 | // Runs a crashing program and converts it to a dense text format like pp does. |
| 29 | func Example_text() { |
| 30 | source := `package main |
| 31 | |
| 32 | import "time" |
| 33 | |
| 34 | func main() { |
| 35 | c := crashy{} |
| 36 | go func() { |
| 37 | c.die(42.) |
| 38 | }() |
| 39 | select {} |
| 40 | } |
| 41 | |
| 42 | type crashy struct{} |
| 43 | |
| 44 | func (c crashy) die(f float32) { |
| 45 | time.Sleep(time.Millisecond) |
| 46 | panic(int(f)) |
| 47 | }` |
| 48 | |
| 49 | // Skipped error handling to make the example shorter. |
| 50 | root, _ := os.MkdirTemp("", "stack") |
| 51 | defer os.RemoveAll(root) |
| 52 | p := filepath.Join(root, "main.go") |
| 53 | os.WriteFile(p, []byte(source), 0600) |
| 54 | // Disable both optimization (-N) and inlining (-l). |
| 55 | c := exec.Command("go", "run", "-gcflags", "-N -l", p) |
| 56 | // This is important, otherwise only the panicking goroutine will be printed. |
| 57 | c.Env = append(os.Environ(), "GOTRACEBACK=1") |
| 58 | raw, _ := c.CombinedOutput() |
| 59 | stream := bytes.NewReader(raw) |
| 60 | |
| 61 | s, suffix, err := stack.ScanSnapshot(stream, os.Stdout, stack.DefaultOpts()) |
| 62 | if err != nil && err != io.EOF { |
| 63 | log.Fatal(err) |
| 64 | } |
| 65 | |
| 66 | // Find out similar goroutine traces and group them into buckets. |
| 67 | buckets := s.Aggregate(stack.AnyValue).Buckets |
| 68 | |
| 69 | // Calculate alignment. |
| 70 | srcLen := 0 |
| 71 | pkgLen := 0 |
| 72 | for _, bucket := range buckets { |
| 73 | for _, line := range bucket.Signature.Stack.Calls { |
| 74 | if l := len(fmt.Sprintf("%s:%d", line.SrcName, line.Line)); l > srcLen { |
| 75 | srcLen = l |
| 76 | } |
| 77 | if l := len(filepath.Base(line.Func.ImportPath)); l > pkgLen { |
| 78 | pkgLen = l |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | for _, bucket := range buckets { |
| 84 | // Print the goroutine header. |
| 85 | extra := "" |
| 86 | if s := bucket.SleepString(); s != "" { |
nothing calls this directly
no test coverage detected
searching dependent graphs…