example_test.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright 2018 Marc-Antoine Ruel. All rights reserved.
  2. // Use of this source code is governed under the Apache License, Version 2.0
  3. // that can be found in the LICENSE file.
  4. package stack_test
  5. import (
  6. "bytes"
  7. "fmt"
  8. "io"
  9. "os"
  10. "notabug.org/themusicgod1/panicparse/stack"
  11. )
  12. const crash = `panic: oh no!
  13. goroutine 1 [running]:
  14. panic(0x0, 0x0)
  15. /home/user/src/golang/src/runtime/panic.go:464 +0x3e6
  16. main.crash2(0x7fe50b49d028, 0xc82000a1e0)
  17. /home/user/go/src/notabug.org/themusicgod1/panicparse/cmd/pp/main.go:45 +0x23
  18. main.main()
  19. /home/user/go/src/notabug.org/themusicgod1/panicparse/cmd/pp/main.go:50 +0xa6
  20. `
  21. func Example() {
  22. // Optional: Check for GOTRACEBACK being set, in particular if there is only
  23. // one goroutine returned.
  24. in := bytes.NewBufferString(crash)
  25. c, err := stack.ParseDump(in, os.Stdout, true)
  26. if err != nil {
  27. return
  28. }
  29. // Find out similar goroutine traces and group them into buckets.
  30. buckets := stack.Aggregate(c.Goroutines, stack.AnyValue)
  31. // Calculate alignment.
  32. srcLen := 0
  33. pkgLen := 0
  34. for _, bucket := range buckets {
  35. for _, line := range bucket.Signature.Stack.Calls {
  36. if l := len(line.SrcLine()); l > srcLen {
  37. srcLen = l
  38. }
  39. if l := len(line.Func.PkgName()); l > pkgLen {
  40. pkgLen = l
  41. }
  42. }
  43. }
  44. for _, bucket := range buckets {
  45. // Print the goroutine header.
  46. extra := ""
  47. if s := bucket.SleepString(); s != "" {
  48. extra += " [" + s + "]"
  49. }
  50. if bucket.Locked {
  51. extra += " [locked]"
  52. }
  53. if c := bucket.CreatedByString(false); c != "" {
  54. extra += " [Created by " + c + "]"
  55. }
  56. fmt.Printf("%d: %s%s\n", len(bucket.IDs), bucket.State, extra)
  57. // Print the stack lines.
  58. for _, line := range bucket.Stack.Calls {
  59. fmt.Printf(
  60. " %-*s %-*s %s(%s)\n",
  61. pkgLen, line.Func.PkgName(), srcLen, line.SrcLine(),
  62. line.Func.Name(), &line.Args)
  63. }
  64. if bucket.Stack.Elided {
  65. io.WriteString(os.Stdout, " (...)\n")
  66. }
  67. }
  68. // Output:
  69. // panic: oh no!
  70. //
  71. // 1: running
  72. // panic.go:464 panic(0, 0)
  73. // main main.go:45 crash2(0x7fe50b49d028, 0xc82000a1e0)
  74. // main main.go:50 main()
  75. }