| 1 | // Package stacktrace captures and formats Go call stacks. |
| 2 | package stacktrace |
| 3 | |
| 4 | import "runtime" |
| 5 | |
| 6 | // Frame holds a single stack frame. |
| 7 | type Frame struct { |
| 8 | Function string |
| 9 | File string |
| 10 | Line int |
| 11 | } |
| 12 | |
| 13 | // Trace is an ordered list of stack frames, outermost first. |
| 14 | type Trace []Frame |
| 15 | |
| 16 | // Capture returns the current call stack, skipping skip frames from |
| 17 | // the caller's perspective. skip=0 means the caller of Capture is the |
| 18 | // first frame. |
| 19 | func Capture(skip int) Trace { |
| 20 | const depth = 64 |
| 21 | var pcs [depth]uintptr |
| 22 | // skip+2: one for runtime.Callers itself, one for Capture. |
| 23 | n := runtime.Callers(skip+2, pcs[:]) |
| 24 | if n == 0 { |
| 25 | return nil |
| 26 | } |
| 27 | |
| 28 | frames := runtime.CallersFrames(pcs[:n]) |
| 29 | var trace Trace |
| 30 | for { |
| 31 | f, more := frames.Next() |
| 32 | trace = append(trace, Frame{ |
| 33 | Function: f.Function, |
| 34 | File: f.File, |
| 35 | Line: f.Line, |
| 36 | }) |
| 37 | if !more { |
| 38 | break |
| 39 | } |
| 40 | } |
| 41 | return trace |
| 42 | } |
| 43 | |