Documentation
¶
Overview ¶
Package stacktrace provides utilities for capturing and inspecting call stacks associated with errors.
This package allows you to create error objects that include information about where in the code the error occurred, which can be extremely useful for debugging. It includes methods to unwrap underlying errors, retrieve call stack frames, and generate string representations of errors with detailed stack trace information.
Example ¶
if err := stacktrace.Trace(os.Chdir(".")); err != nil { fmt.Println("err.Error():", err.Error()) info := stacktrace.GetDebugInfo(err) fmt.Println("info.Detail:", info.Detail) fmt.Printf("%d stack entries included.", len(info.StackEntries)) panic(stacktrace.GetDebugInfo(err)) } if file, err := stacktrace.Trace2(os.Open("./no/such/file")); err != nil { fmt.Println("err.Error():", err.Error()) info := stacktrace.GetDebugInfo(err) fmt.Println("info.Detail:", info.Detail) fmt.Printf("%d stack entries included.", len(info.StackEntries)) } else { file.Close() }
Output: err.Error(): open ./no/such/file: no such file or directory (stacktrace_test.go:18 Example) info.Detail: open ./no/such/file: no such file or directory (stacktrace_test.go:18 Example) 5 stack entries included.
Index ¶
- func Callers(skip int) []uintptr
- func CallersFrames(callers []uintptr) iter.Seq[*runtime.Frame]
- func CallersLimit(skip, limit int) []uintptr
- func Errorf(format string, a ...any) error
- func Format(err error) string
- func HasStackTracer(err error) bool
- func New(text string) error
- func Trace(err error) error
- func Trace2[T0 any](v0 T0, err error) (T0, error)
- func Trace3[T0, T1 any](v0 T0, v1 T1, err error) (T0, T1, error)
- func Trace4[T0, T1, T2 any](v0 T0, v1 T1, v2 T2, err error) (T0, T1, T2, error)
- type DebugInfo
- type Error
- type StackTracer
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Callers ¶
Callers returns the program counters (PCs) of function invocations on the calling goroutine's stack, skipping the specified number of stack frames.
The skip parameter determines how many initial stack frames to omit from the result. A skip value of 0 starts from the caller of Callers itself.
The returned slice contains the collected program counters, which can be further processed using runtime.CallersFrames to obtain function details.
func CallersFrames ¶
CallersFrames returns an iterator sequence of *runtime.Frame based on the given slice of program counters (PCs). It yields stack frames one by one, stopping if the iterator function returns false, or if there are no more frames.
The function utilizes runtime.CallersFrames to traverse the stack trace and provides each frame through the yield function.
func CallersLimit ¶ added in v2.4.0
CallersLimit returns the program counters (PCs) of function invocations on the calling goroutine's stack, skipping the specified number of stack frames and limiting the number of returned frames.
The skip parameter determines how many initial stack frames to omit from the result. A skip value of 0 starts from the caller of CallersLimit itself.
The limit parameter specifies the maximum number of stack frames to return. If limit is 0, an empty slice is returned. If limit is negative, all available stack frames after skipping are returned (equivalent to calling Callers with skip + 1).
The returned slice contains the collected program counters, which can be further processed using runtime.CallerFrames to obtain function details.
func Errorf ¶
Errorf returns an error formatted according to the format specifier, similar to fmt.Errorf, along with stack trace information in a concise way.
Example usage:
err := stacktrace.Errorf("failed to do %s", action)
This is equivalent to:
err := stacktrace.Trace(fmt.Errorf("failed to do %s", action))
stacktrace.Errorf is slightly more concise and efficient.
func Format ¶
Format returns a formatted string representation of the DebugInfo from err.
If err is nil, it returns an empty string. If err's chain doesn't contain any stack trace information, it returns err.Error().
This is equivalent to:
stacktrace.GetDebugInfo(err).Format()
See DebugInfo.Format.
func HasStackTracer ¶ added in v2.3.0
HasStackTracer returns true if there is at least one StackTracer in the error chain, false otherwise.
func New ¶
New returns an error created with errors.New along with stack trace information in a concise way.
Example usage:
err := stacktrace.New("something went wrong")
This is equivalent to:
err := stacktrace.Trace(errors.New("something went wrong"))
stacktrace.New is slightly more concise and efficient.
func Trace ¶
Trace returns the error along with stack frame information. It returns nil if the input error is nil.
func Trace2 ¶
Trace2 returns the given values unchanged if err is nil. If err is not nil, it wraps err with stack trace information before returning.
The function name "Trace2" indicates that it takes two arguments (a value of any type and an error) and returns two values.
func Trace3 ¶
Trace3 returns the given values unchanged if err is nil. If err is not nil, it wraps err with stack trace information before returning.
The function name "Trace3" indicates that it takes three arguments (two values of any type and an error) and returns three values.
Types ¶
type DebugInfo ¶
type DebugInfo struct { // Detail provides a detailed error message. Detail string `json:"detail,omitempty"` // StackEntries contains a list of stack trace entries related to the error. StackEntries []string `json:"stack_entries,omitempty"` }
DebugInfo represents debug information about an error.
This struct is compatible with google.golang.org/genproto/googleapis/rpc/errdetails.DebugInfo.
Example (Multiple) ¶
ch := make(chan error) go func() { ch <- stacktrace.New("hello") }() go func() { ch <- stacktrace.New("world") }() err1 := <-ch // error from the thread err2 := <-ch // error from the other thread if err1 != nil || err2 != nil { err := errors.Join( stacktrace.New("Two errors"), // error of this thread err1, err2, ) info := stacktrace.GetDebugInfo(err) fmt.Println(info.Format()) // this prints 3 stack frames. }
Output:
func GetDebugInfo ¶
GetDebugInfo extracts debug information from an error. It collects stack trace frames and formats them as strings, then returns this information along with the detailed error message in a DebugInfo struct.
It returns a zero value if err is nil.
func (DebugInfo) Format ¶
Format returns a formatted string representation of the DebugInfo.
The output consists of the Detail message followed by the stack trace entries, each separated by a newline and a tab ("\n\t").
Example ¶
err := stacktrace.Trace(os.Chdir("/no/such/dir")) fmt.Println(stacktrace.Format(err))
Output:
Example (Nil) ¶
err := stacktrace.Trace(nil) fmt.Println(stacktrace.Format(err))
Output:
type Error ¶
type Error struct { // Err holds the original error that occurred. Err error // Callers contains the program counters (PCs) of the function call stack // at the time the error was captured. These can be used to retrieve stack traces. Callers []uintptr }
Error wraps an error and adds a call stack indicating where it occurred.
It is recommended to use the following functions to create an instance of Error:
- Trace: Adds a call stack indicating where Trace was executed to the given error and returns it.
- Trace2, Trace3, Trace4: Variants of Trace that accept multiple arbitrary arguments along with an error and return them. The trailing number represents the number of additional arguments other than the error.
- Errorf: A function that wraps `fmt.Errorf` with `Trace`.
- New: A function that wraps `errors.New` with `Trace`.
If `nil` is passed to Trace and its variants, they return `nil` as an error.
Trace, Trace2, Trace3, Trace4, and Errorf do not add a new call stack if the given error already has one, meaning that if an `Error` instance is already present in the error chain, the original error is returned as-is.
New always returns an error with a newly added call stack.
func NewError ¶
NewError returns a new Error instance with the given error and caller stack information.
func (Error) Error ¶
Error returns a string representation of the custom error, including the original error message. If the call stack information is available, it appends the information about the first frame of the stack trace to the error message.
The format of the returned string is: "<original error message> (<file name>:<line> <function name>)"
func (Error) StackTrace ¶ added in v2.1.0
StackTrace returns a slice of program counters representing the call stack.
type StackTracer ¶ added in v2.1.0
type StackTracer interface { // StackTracer extends the error interface. error // StackTrace returns a slice of program counters representing the call stack. StackTrace() []uintptr }
StackTracer represents an error that provides stack trace information.
func ListStackTracers ¶ added in v2.3.0
func ListStackTracers(err error) []StackTracer
ListStackTracers returns all the StackTracers in the error chain.
Example ¶
var err error for _, v := range stacktrace.ListStackTracers(err) { for frame := range stacktrace.CallersFrames(v.StackTrace()) { _, _ = frame.File, frame.Line } }
Output: