e

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2025 License: MIT Imports: 7 Imported by: 0

README

Package e - Error Wrapper for Go

Go Reference Go Report Card

e is a lightweight Go package providing enhanced error wrapping with stack trace capture and structured logging support using Go's log/slog package.

Features

  • Wrap errors with automatic stack trace capture
  • Attach custom contextual messages to errors
  • Add structured key–value fields to errors for additional context
  • Compatible with Go standard library errors.Is and errors.As
  • Produce structured logs with detailed error trace using slog.Group
  • Simplifies function names in stack traces for better readability
  • Recover from panics and convert them into structured errors (with optional stack trace and fatal handling)

Installation

go get github.com/whynot00/e

Usage

Wrapping errors

Wrap an existing error to capture the current stack frame:

err := errors.New("database error")

wrappedErr := e.Wrap(err)

Wrap with a custom message describing context:

wrappedErr := e.WrapWithMessage(err, "failed to load user profile")
Structured logging with slog

Integrate with log/slog for rich structured logs:

logger := slog.New(slog.NewJSONHandler(os.Stdout))

err := e.WrapWithMessage(someError, "additional context")

logger.Error("operation failed", e.SlogGroup(err))

Example output:

{
  "level": "error",
  "msg": "operation failed",
  "error": {
    "error_text": "some error message",
    "stack_trace": [
      {
        "file": "/path/to/file.go",
        "function": "functionName",
        "line": 42,
        "message": "additional context"
      },
      {
        "file": "/path/to/other.go",
        "function": "otherFunction",
        "line": 10
      }
    ]
  }
}

This logs the error message along with a detailed stack trace and custom messages.

JSON serialization

Wrapped errors implement json.Marshaler, producing structured JSON including error message and stack trace:

jsonData, err := json.Marshal(wrappedErr)
if err != nil {
    // handle error
}
fmt.Println(string(jsonData))

Example output:

{
  "error": "sql: no rows in result set",
  "stack_trace": [
    {
      "file": "/path/to/main.go",
      "function": "main",
      "line": 15
    },
    {
      "file": "/path/to/main.go",
      "function": "work",
      "line": 22
    },
    {
      "file": "/path/to/main.go",
      "function": "anotherWork",
      "line": 32,
      "message": "fetching user data failed"
    }
  ]
}
Custom Fields Support

You can now attach structured key-value fields to wrapped errors for richer context in logs or serialized output. Creating an error with fields:

err := someOperation()
if err != nil {
    err = e.WrapWithFields(err,
        e.Field("user_id", 42),
        e.Field("operation", "database insert"),
    )
}

Example output (structured via slog.Group or JSON):

{
  "error": {
    "error_text": "insert failed",
    "stack_trace": [...],
    "user_id": 42,
    "operation": "database insert"
  }
}
Panic recovery

The package provides helpers for safe panic recovery with optional stack trace capture and structured handling.

defer e.Recover(nil, func(err error) {
    log.Println("panic recovered:", err)
})

Or send to a channel in a goroutine:

errCh := make(chan error, 1)
go func() {
    defer e.RecoverToChannel(nil, errCh)
    // potentially panicking code
}()

Example output (structured via slog.Group or JSON):

{
  "error": "panic: runtime error: index out of range",
  "stack_trace": [
    {
      "file": "/app/service.go",
      "function": "handleRequest",
      "line": 87
    },
    {
      "file": "/app/controller.go",
      "function": "Serve",
      "line": 45
    }
  ]
}

Supports Fatal termination,RecoverOnly suppression, and optional WithoutStack mode.

API

func Wrap(err error) error

Wraps an error with a captured stack frame; returns nil if input is nil.

func WrapWithMessage(err error, msg string) error

Wraps an error with a stack frame and attaches a custom message.

func WrapWithFields(err error, fields ...Fields) error

Wraps an error with a stack frame and attaches structured key–value fields for logging or serialization.

func SlogGroup(err error) slog.Attr

Returns a slog.Attr containing the error message and stack trace as a slog.Group, suitable for structured logging.

func WrapRecovered(opts *RecoverOpts, r any) error

Wraps a value returned from recover() into an error, by default capturing a filtered stack trace.

func Recover(opts *RecoverOpts, callback func(error))

Intercepts and recovers from a panic. Wraps the recovered value as an error and invokes the provided callback.

func RecoverToChannel(opts *RecoverOpts, errChan chan<- error)

Alternative to Recover for use in goroutines. Recovers from a panic and sends the error into the provided channel. Returns a slog.Attr containing the error message and stack trace as a slog.Group, suitable for structured logging.

Documentation

Overview

Package e provides a lightweight error wrapper with stack trace and structured logging support via slog.Group and JSON serialization.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Recover added in v0.3.0

func Recover(opts *RecoverOpts, callback func(error))

Recover is a general-purpose recovery helper. It must be used with `defer`:

defer e.Recover(opts, func(err error) { ... })

If a panic occurs, it wraps the value in an error and calls the provided callback. If Fatal is true, the process exits after the callback is executed.

func RecoverToChannel added in v0.3.0

func RecoverToChannel(opts *RecoverOpts, errChan chan<- error)

RecoverToChannel is a recovery helper for use in goroutines or workers. Instead of calling a callback, it sends the recovered error into the provided channel.

Use it with `defer` inside goroutines:

go func() {
    defer e.RecoverToChannel(opts, errChan)
    ...
}()

func SlogGroup

func SlogGroup(err error) slog.Attr

SlogGroup returns a slog.Group containing structured fields with error and stack trace.

func Wrap

func Wrap(err error) error

Wrap returns an ErrorWrapper with the current call site. If the error is already wrapped, the new frame is prepended.

func WrapRecovered added in v0.3.0

func WrapRecovered(opts *RecoverOpts, r any) error

WrapRecovered wraps the recovered panic value `r` into an error with optional stack trace.

It is intended to be used internally by recovery helpers, but can also be reused in custom handlers.

func WrapWithFields added in v0.4.0

func WrapWithFields(err error, fields ...Fields) error

func WrapWithMessage

func WrapWithMessage(err error, msg string) error

WrapWithMessage is like Wrap but also attaches a custom message to the frame.

Types

type ErrorWrapper

type ErrorWrapper struct {
	// contains filtered or unexported fields
}

ErrorWrapper wraps an underlying error with stack-trace frames and optional custom fields.

func (*ErrorWrapper) Error

func (e *ErrorWrapper) Error() string

Error returns the underlying error message.

func (*ErrorWrapper) Fields added in v0.4.0

func (e *ErrorWrapper) Fields() Fields

Fields returns a deep copy of the custom fields attached to the error. If no fields were attached, a zero value is returned.

func (*ErrorWrapper) MarshalJSON added in v0.2.0

func (e *ErrorWrapper) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler and outputs a single JSON object containing the original error text, stack trace and any custom fields.

func (*ErrorWrapper) StackTrace added in v0.3.0

func (e *ErrorWrapper) StackTrace() []frame

StackTrace returns a shallow copy of the captured stack frames.

func (*ErrorWrapper) Unwrap

func (e *ErrorWrapper) Unwrap() error

Unwrap implements errors.Unwrap, allowing errors.Is / errors.As to work.

type Fields added in v0.4.0

type Fields struct {
	// contains filtered or unexported fields
}

Fields is an ordered collection of key–value pairs that can be attached to an ErrorWrapper for structured logging and serialization.

func Field added in v0.4.0

func Field(key string, value any) Fields

Field returns a new Fields containing a single key/value pair. It is intended for use with WrapWithFields or as a starting point for chaining additional fields.

func (Fields) Get added in v0.4.0

func (f Fields) Get(k string) any

Get retrieves the value associated with the given key k. If the key does not exist, it returns nil.

func (Fields) List added in v0.4.0

func (f Fields) List() []fieldKV

List returns an independent copy of all key-value pairs stored in Fields. Modifications to the returned slice do not affect the original Fields instance.

type RecoverOpts added in v0.3.0

type RecoverOpts struct {
	// WithoutStack disables capturing stack trace when recovering from panic.
	// Useful when you want minimal error information or you're handling tracing/logging manually.
	WithoutStack bool

	// RecoverOnly suppresses all side effects (callback or channel send).
	// The panic is still recovered, but no error will be propagated.
	RecoverOnly bool

	// Fatal forces the application to terminate with exit code 1 after recovering the panic.
	// Useful in CLI tools, workers, or when panic is considered unrecoverable.
	Fatal bool
}

RecoverOpts defines behavior for panic recovery.

It controls whether to include a stack trace, invoke a callback, or exit the process after recovering from a panic.

Jump to

Keyboard shortcuts

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