stacktrace

package
v1.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2026 License: MIT Imports: 5 Imported by: 1

Documentation

Overview

Package stacktrace captures and formats call stack information using the Go runtime. It provides GetStack to capture the current program stack, and Wrap / Extract to attach a StackTrace to an error. StackTrace implements slog.LogValuer for structured logging integration.

Index

Examples

Constants

This section is empty.

Variables

View Source
var Disabled atomic.Bool

Disabled disables stacktrace collection in Wrap when set to true.

Functions

func Wrap

func Wrap(err error) error

Wrap extends err by attaching a StackTrace captured at the call site. If err is nil or Disabled is true, err is returned unchanged. If err already carries a StackTrace, it is not wrapped again.

Example
package main

import (
	"bytes"
	"errors"
	"fmt"
	"log/slog"
	"regexp"

	"github.com/wood-jp/xerrors"
	"github.com/wood-jp/xerrors/stacktrace"
)

func newLogger(buf *bytes.Buffer) *slog.Logger {
	return slog.New(slog.NewJSONHandler(buf, &slog.HandlerOptions{
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey && len(groups) == 0 {
				return slog.Attr{}
			}
			return a
		},
	}))
}

var (
	reSource = regexp.MustCompile(`"source":"[^"]*"`)
	reLine   = regexp.MustCompile(`"line":\d+`)
)

func normalizeStack(s string) string {
	s = reSource.ReplaceAllString(s, `"source":"..."`)
	s = reLine.ReplaceAllString(s, `"line":0`)
	return s
}

func main() {
	var buf bytes.Buffer
	err := stacktrace.Wrap(errors.New("something failed"))
	newLogger(&buf).Error("operation failed", xerrors.Log(err))
	fmt.Print(normalizeStack(buf.String()))
}
Output:
{"level":"ERROR","msg":"operation failed","error":{"error":"something failed","error_detail":{"stacktrace":[{"func":"github.com/wood-jp/xerrors/stacktrace_test.ExampleWrap","line":0,"source":"..."},{"func":"main.main","line":0,"source":"..."}]}}}

Types

type Frame

type Frame struct {
	// File is the source file path of the frame.
	File string `json:"source"`
	// LineNumber is the line number within File where the call was made.
	LineNumber int `json:"line"`
	// Function is the fully-qualified function name of the frame.
	Function string `json:"func"`
}

Frame represents human-readable information about a single frame in a stack trace.

type StackTrace

type StackTrace []Frame

StackTrace represents a program stack trace as a series of frames.

func Extract

func Extract(err error) StackTrace

Extract returns the StackTrace attached to err, or nil if none is present or err is nil.

Example (NoStack)
package main

import (
	"errors"
	"fmt"

	"github.com/wood-jp/xerrors/stacktrace"
)

func main() {
	err := errors.New("plain error")
	fmt.Println(stacktrace.Extract(err) == nil)
}
Output:
true

func GetStack

func GetStack(skipFrames int, skipRuntime bool) StackTrace

GetStack captures the current program stack trace and returns it as a StackTrace. skipFrames controls how many frames to skip: passing 1 makes GetStack itself the first captured frame. When skipRuntime is true, frames from the Go runtime (e.g. runtime.main, runtime.panic) and the testing package are omitted from the result.

func (StackTrace) LogValue

func (st StackTrace) LogValue() slog.Value

LogValue implements slog.LogValuer. It returns a group containing a single "stacktrace" attr whose value is an array of frame objects, each with "func", "line", and "source" keys.

Each frame is represented as map[string]any rather than slog.GroupValue because slog handlers only resolve slog.LogValuer at the top level of an attribute value — they do not recursively resolve slog.Value elements nested inside a []slog.Value wrapped in slog.AnyValue. JSON and text handlers would encode those as empty objects ({}). map[string]any is handled correctly by encoding/json and produces the expected key-value output.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL