Documentation ¶
Overview ¶
Package stack analyzes stack dump of Go processes and simplifies it.
It is mostly useful on servers will large number of identical goroutines, making the crash dump harder to read than strictly necessary.
Example ¶
package main import ( "bytes" "fmt" "io" "os" "github.com/maruel/panicparse/stack" ) const crash = `panic: oh no! goroutine 1 [running]: panic(0x0, 0x0) /home/user/src/golang/src/runtime/panic.go:464 +0x3e6 main.crash2(0x7fe50b49d028, 0xc82000a1e0) /home/user/go/src/github.com/maruel/panicparse/cmd/pp/main.go:45 +0x23 main.main() /home/user/go/src/github.com/maruel/panicparse/cmd/pp/main.go:50 +0xa6 ` func main() { // Optional: Check for GOTRACEBACK being set, in particular if there is only // one goroutine returned. in := bytes.NewBufferString(crash) c, err := stack.ParseDump(in, os.Stdout, true) if err != nil { return } // Find out similar goroutine traces and group them into buckets. buckets := stack.Aggregate(c.Goroutines, stack.AnyValue) // Calculate alignment. srcLen := 0 pkgLen := 0 for _, bucket := range buckets { for _, line := range bucket.Signature.Stack.Calls { if l := len(fmt.Sprintf("%s:%d", line.SrcName(), line.Line)); l > srcLen { srcLen = l } if l := len(line.Func.PkgName()); l > pkgLen { pkgLen = l } } } for _, bucket := range buckets { // Print the goroutine header. extra := "" if s := bucket.SleepString(); s != "" { extra += " [" + s + "]" } if bucket.Locked { extra += " [locked]" } if c := bucket.CreatedBy.Func.PkgDotName(); c != "" { extra += fmt.Sprintf(" [Created by %s @ %s:%d]", c, bucket.CreatedBy.SrcName(), bucket.CreatedBy.Line) } fmt.Printf("%d: %s%s\n", len(bucket.IDs), bucket.State, extra) // Print the stack lines. for _, line := range bucket.Stack.Calls { fmt.Printf( " %-*s %-*s %s(%s)\n", pkgLen, line.Func.PkgName(), srcLen, fmt.Sprintf("%s:%d", line.SrcName(), line.Line), line.Func.Name(), &line.Args) } if bucket.Stack.Elided { io.WriteString(os.Stdout, " (...)\n") } } }
Output: panic: oh no! 1: running panic.go:464 panic(0, 0) main main.go:45 crash2(0x7fe50b49d028, 0xc82000a1e0) main main.go:50 main()
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Arg ¶
type Arg struct { Value uint64 // Value is the raw value as found in the stack trace Name string // Name is a pseudo name given to the argument }
Arg is an argument on a Call.
type Args ¶
type Args struct { // Values is the arguments as shown on the stack trace. They are mangled via // simplification. Values []Arg // Processed is the arguments generated from processing the source files. It // can have a length lower than Values. Processed []string // Elided when set means there was a trailing ", ...". Elided bool }
Args is a series of function call arguments.
type Bucket ¶
type Bucket struct { // Signature is the generalized signature for this bucket. Signature // IDs is the ID of each Goroutine with this Signature. IDs []int // First is true if this Bucket contains the first goroutine, e.g. the one // Signature that likely generated the panic() call, if any. First bool }
Bucket is a stack trace signature and the list of goroutines that fits this signature.
func Aggregate ¶ added in v1.2.0
func Aggregate(goroutines []*Goroutine, similar Similarity) []*Bucket
Aggregate merges similar goroutines into buckets.
The buckets are ordered in library provided order of relevancy. You can reorder at your choosing.
type Call ¶
type Call struct { // SrcPath is the full path name of the source file as seen in the trace. SrcPath string // LocalSrcPath is the full path name of the source file as seen in the host, // if found. LocalSrcPath string // Line is the line number. Line int // Func is the fully qualified function name (encoded). Func Func // Args is the call arguments. Args Args // The following are only set if guesspaths is set to true in ParseDump(). // IsStdlib is true if it is a Go standard library function. This includes // the 'go test' generated main executable. IsStdlib bool // RelSrcPath is the relative path to GOROOT or GOPATH. Only set when // Augment() is called. RelSrcPath string }
Call is an item in the stack trace.
func (*Call) FullSrcLine
deprecated
added in
v1.2.0
func (*Call) ImportPath ¶ added in v1.4.0
ImportPath returns the fully qualified package import path.
In the case of package "main", it returns the underlying path to the main package instead of "main" if guesspaths=true was specified to ParseDump().
func (*Call) PkgSrc ¶ added in v1.2.0
PkgSrc returns one directory plus the file name of the source file.
Since the package name can differ from the package import path, the result is incorrect when there's a mismatch between the directory name containing the package and the package name.
type Context ¶ added in v1.2.0
type Context struct { // Goroutines is the Goroutines found. // // They are in the order that they were printed. Goroutines []*Goroutine // GOROOT is the GOROOT as detected in the traceback, not the on the host. // // It can be empty if no root was determined, for example the traceback // contains only non-stdlib source references. // // Empty is guesspaths was false. GOROOT string // GOPATHs is the GOPATH as detected in the traceback, with the value being // the corresponding path mapped to the host. // // It can be empty if only stdlib code is in the traceback or if no local // sources were matched up. In the general case there is only one entry in // the map. // // Nil is guesspaths was false. GOPATHs map[string]string // contains filtered or unexported fields }
Context is a parsing context.
It contains the deduced GOROOT and GOPATH, if guesspaths is true.
func ParseDump ¶
ParseDump processes the output from runtime.Stack().
Returns nil *Context if no stack trace was detected.
It pipes anything not detected as a panic stack trace from r into out. It assumes there is junk before the actual stack trace. The junk is streamed to out.
If guesspaths is false, no guessing of GOROOT and GOPATH is done, and Call entites do not have LocalSrcPath and IsStdlib filled in. If true, be warned that file presence is done, which means some level of disk I/O.
type Func ¶ added in v1.2.0
type Func struct {
Raw string
}
Func is a function call as read in a goroutine stack trace.
Go stack traces print a mangled function call, this wrapper unmangle the string before printing and adds other filtering methods.
The main caveat is that for calls in package main, the package import URL is left out.
func (*Func) IsExported ¶ added in v1.2.0
IsExported returns true if the function is exported.
func (*Func) Name ¶ added in v1.2.0
Name returns the function name.
Methods are fully qualified, including the struct type.
func (*Func) PkgDotName ¶ added in v1.2.0
PkgDotName returns "<package>.<func>" format.
Since the package name can differ from the package import path, the result is incorrect when there's a mismatch between the directory name containing the package and the package name.
type Goroutine ¶
type Goroutine struct { // Signature is the stack trace, internal bits, state, which call site // created it, etc. Signature // ID is the goroutine id. ID int // First is the goroutine first printed, normally the one that crashed. First bool }
Goroutine represents the state of one goroutine, including the stack trace.
type Signature ¶
type Signature struct { // State is the goroutine state at the time of the snapshot. // // Use git grep 'gopark(|unlock)\(' to find them all plus everything listed // in runtime/traceback.go. Valid values includes: // - chan send, chan receive, select // - finalizer wait, mark wait (idle), // - Concurrent GC wait, GC sweep wait, force gc (idle) // - IO wait, panicwait // - semacquire, semarelease // - sleep, timer goroutine (idle) // - trace reader (blocked) // Stuck cases: // - chan send (nil chan), chan receive (nil chan), select (no cases) // Runnable states: // - idle, runnable, running, syscall, waiting, dead, enqueue, copystack, // Scan states: // - scan, scanrunnable, scanrunning, scansyscall, scanwaiting, scandead, // scanenqueue State string // Createdby is the goroutine which created this one, if applicable. CreatedBy Call // SleepMin is the wait time in minutes, if applicable. SleepMin int // SleepMax is the wait time in minutes, if applicable. SleepMax int // Stack is the call stack. Stack Stack // Locked is set if the goroutine was locked to an OS thread. Locked bool }
Signature represents the signature of one or multiple goroutines.
It is effectively the stack trace plus the goroutine internal bits, like it's state, if it is thread locked, which call site created this goroutine, etc.
func (*Signature) CreatedByString
deprecated
added in
v1.2.0
func (*Signature) SleepString ¶ added in v1.2.0
SleepString returns a string "N-M minutes" if the goroutine(s) slept for a long time.
Returns an empty string otherwise.
type Similarity ¶
type Similarity int
Similarity is the level at which two call lines arguments must match to be considered similar enough to coalesce them.
const ( // ExactFlags requires same bits (e.g. Locked). ExactFlags Similarity = iota // ExactLines requests the exact same arguments on the call line. ExactLines // AnyPointer considers different pointers a similar call line. AnyPointer // AnyValue accepts any value as similar call line. AnyValue )