Documentation
¶
Overview ¶
Package stacktrace provides optional stack trace support for errx errors.
This package extends errx with stack trace capabilities while keeping the core errx package minimal and zero-dependency. It offers two usage patterns:
Per-error opt-in using Here() as a Classified: err := errx.Wrap("context", cause, ErrNotFound, stacktrace.Here())
Convenience functions that automatically capture traces: err := stacktrace.Wrap("context", cause, ErrNotFound)
Stack traces can be extracted from any error in the chain using Extract():
frames := stacktrace.Extract(err)
for _, frame := range frames {
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
Example (Integration) ¶
Example_integration demonstrates combining stacktrace with other errx features
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/stacktrace"
)
func main() {
var ErrNotFound = errx.NewSentinel("not found")
// Combine stack traces with displayable errors and attributes
displayErr := errx.NewDisplayable("User not found")
attrErr := errx.Attrs("user_id", "12345", "action", "fetch")
err := stacktrace.Wrap("failed to get user profile",
errx.Classify(displayErr, ErrNotFound, attrErr))
// All features work together
fmt.Println("Error:", err.Error())
fmt.Println("Displayable:", errx.DisplayText(err))
fmt.Println("Is not found:", errors.Is(err, ErrNotFound))
fmt.Println("Has attributes:", errx.HasAttrs(err))
fmt.Println("Has stack trace:", stacktrace.Extract(err) != nil)
}
Output: Error: failed to get user profile: User not found Displayable: User not found Is not found: true Has attributes: true Has stack trace: true
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Classify ¶
func Classify(cause error, classifications ...errx.Classified) error
Classify attaches one or more classifications to an error, automatically capturing a stack trace at the call site.
This is a convenience function equivalent to:
errx.Classify(cause, append(classifications, stacktrace.Here())...)
If cause is nil, Classify returns nil.
Example:
err := stacktrace.Classify(cause, ErrNotFound)
Example ¶
ExampleClassify demonstrates using stacktrace.Classify
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/stacktrace"
)
func main() {
var ErrRetryable = errx.NewSentinel("retryable error")
// stacktrace.Classify adds classification and trace without changing the message
baseErr := errors.New("temporary network failure")
err := stacktrace.Classify(baseErr, ErrRetryable)
// Original message is preserved
fmt.Println(err.Error())
// But classification and trace are added
fmt.Println("Is retryable:", errors.Is(err, ErrRetryable))
fmt.Println("Has trace:", stacktrace.Extract(err) != nil)
}
Output: temporary network failure Is retryable: true Has trace: true
func ClassifyNew ¶ added in v1.2.0
func ClassifyNew(text string, classifications ...errx.Classified) error
ClassifyNew creates a new error with the given text and immediately classifies it with one or more classifications, automatically capturing a stack trace at the call site.
This is a convenience function equivalent to:
errx.ClassifyNew(text, append(classifications, stacktrace.Here())...)
This function is useful when you want to create a new error, classify it, and capture a stack trace in a single step, reducing verbosity.
Example:
var ErrNotFound = errx.NewSentinel("not found")
var ErrDatabase = errx.NewSentinel("database error")
// Instead of:
// err := stacktrace.Classify(errors.New("user record missing"), ErrNotFound, ErrDatabase)
// You can write:
err := stacktrace.ClassifyNew("user record missing", ErrNotFound, ErrDatabase)
fmt.Println(err.Error()) // Output: user record missing
fmt.Println(errors.Is(err, ErrNotFound)) // Output: true
fmt.Println(stacktrace.Extract(err) != nil) // Output: true
Example ¶
ExampleClassifyNew demonstrates creating and classifying an error with automatic trace capture
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/stacktrace"
)
func main() {
var (
ErrDatabase = errx.NewSentinel("database error")
ErrRetryable = errx.NewSentinel("retryable error")
)
// Create a new error, classify it, and capture stack trace in one step
err := stacktrace.ClassifyNew("connection timeout", ErrDatabase, ErrRetryable)
fmt.Println(err.Error())
fmt.Println("Is database error:", errors.Is(err, ErrDatabase))
fmt.Println("Is retryable:", errors.Is(err, ErrRetryable))
fmt.Println("Has trace:", stacktrace.Extract(err) != nil)
}
Output: connection timeout Is database error: true Is retryable: true Has trace: true
Example (WithDisplayable) ¶
ExampleClassifyNew_withDisplayable demonstrates ClassifyNew with displayable errors
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/stacktrace"
)
func main() {
var ErrNotFound = errx.NewSentinel("not found")
displayErr := errx.NewDisplayable("The requested resource was not found")
// Create error with classification, displayable message, and stack trace
err := stacktrace.ClassifyNew("user record missing from database", ErrNotFound, displayErr)
// Full error for logging
fmt.Println("Full error:", err.Error())
// User-facing message
fmt.Println("Display text:", errx.DisplayText(err))
// Classification check
fmt.Println("Is not found:", errors.Is(err, ErrNotFound))
// Stack trace available
fmt.Println("Has trace:", stacktrace.Extract(err) != nil)
}
Output: Full error: user record missing from database Display text: The requested resource was not found Is not found: true Has trace: true
func Here ¶
func Here() errx.Classified
Here captures the current stack trace and returns it as an errx.Classified. It can be used with errx.Wrap() or errx.Classify() to attach stack traces to errors.
The stack trace is captured starting from the caller of Here(), skipping the Here() function itself and the runtime.Callers call.
Example:
err := errx.Wrap("operation failed", cause, ErrNotFound, stacktrace.Here())
The captured stack trace can later be extracted using Extract().
Example ¶
ExampleHere demonstrates using Here() to capture stack traces per-error
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/stacktrace"
)
func main() {
var ErrNotFound = errx.NewSentinel("not found")
// Capture stack trace at this specific error site
baseErr := errors.New("user record missing")
err := errx.Wrap("failed to fetch user", baseErr, ErrNotFound, stacktrace.Here())
// Extract and display the stack trace
frames := stacktrace.Extract(err)
if frames != nil {
fmt.Printf("Stack trace captured: %d frames\n", len(frames))
// In real code, you might log all frames
if len(frames) > 0 {
fmt.Printf("Top frame: %s\n", frames[0].Function)
}
}
}
Output: Stack trace captured: 7 frames Top frame: github.com/go-extras/errx/stacktrace_test.ExampleHere
func Wrap ¶
func Wrap(text string, cause error, classifications ...errx.Classified) error
Wrap wraps an error with additional context text and optional classifications, automatically capturing a stack trace at the call site.
This is a convenience function equivalent to:
errx.Wrap(text, cause, append(classifications, stacktrace.Here())...)
If cause is nil, Wrap returns nil.
Example:
err := stacktrace.Wrap("failed to process order", cause, ErrNotFound)
Example ¶
ExampleWrap demonstrates using stacktrace.Wrap for automatic trace capture
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx"
"github.com/go-extras/errx/stacktrace"
)
func main() {
var ErrDatabase = errx.NewSentinel("database error")
// stacktrace.Wrap automatically captures the stack trace
baseErr := errors.New("connection timeout")
err := stacktrace.Wrap("database query failed", baseErr, ErrDatabase)
// The error works like a normal errx error
fmt.Println(err.Error())
fmt.Println("Is database error:", errors.Is(err, ErrDatabase))
// But also has a stack trace
frames := stacktrace.Extract(err)
fmt.Println("Has stack trace:", frames != nil)
}
Output: database query failed: connection timeout Is database error: true Has stack trace: true
Types ¶
type Frame ¶
type Frame struct {
File string // Full path to the source file
Line int // Line number in the source file
Function string // Fully qualified function name
}
Frame represents a single stack frame with file, line, and function information.
func Extract ¶
Extract returns stack frames from the first traced error found in the error chain. It traverses the entire error chain looking for a traced error and returns its frames.
Returns nil if the error is nil or does not contain any stack trace.
Example:
frames := stacktrace.Extract(err)
if frames != nil {
for _, frame := range frames {
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
}
Example ¶
ExampleExtract demonstrates extracting and formatting stack traces
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/stacktrace"
)
func main() {
// Create an error with a stack trace
err := stacktrace.Wrap("operation failed", errors.New("base error"))
// Extract the stack trace
frames := stacktrace.Extract(err)
if frames != nil {
fmt.Printf("Stack trace (%d frames):\n", len(frames))
for i, frame := range frames {
if i >= 3 { // Limit output for example
fmt.Println(" ...")
break
}
fmt.Printf(" %s:%d\n", frame.Function, frame.Line)
}
}
}
Output: Stack trace (7 frames): github.com/go-extras/errx/stacktrace_test.ExampleExtract:129 testing.runExample:63 testing.runExamples:41 ...
Example (NoTrace) ¶
ExampleExtract_noTrace demonstrates Extract returning nil for errors without traces
package main
import (
"errors"
"fmt"
"github.com/go-extras/errx/stacktrace"
)
func main() {
// Regular error without stack trace
err := errors.New("simple error")
frames := stacktrace.Extract(err)
fmt.Printf("Stack trace: %v\n", frames)
}
Output: Stack trace: []
func (Frame) String ¶
String returns a formatted representation of the frame.
Example ¶
ExampleFrame_String demonstrates formatting a stack frame
package main
import (
"fmt"
"github.com/go-extras/errx/stacktrace"
)
func main() {
frame := stacktrace.Frame{
File: "/home/user/project/main.go",
Line: 42,
Function: "main.processRequest",
}
fmt.Println(frame.String())
}
Output: /home/user/project/main.go:42 main.processRequest