werr

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Dec 28, 2022 License: Unlicense Imports: 2 Imported by: 1

README

werr

A package that wraps errors with a stack trace

go.dev reference Check Status Test Status

Overview

This is a very simple package that can be used to wrap an error before returning it. The Wrap function will annotate the error with the stack frame of the function that called Wrap. Subsequent calls to wrap will result in a nested set of stack frames forming a call chain. When the error is formatted, the stack frame can be printed as a multiline trace by using the %+v verb, for example fmt.Printf("error %+v", err)

Wrap will not wrap a nil error so it is idiomatic to return werr.Wrap(err) without a nil check.

This package is compatible with (and uses) golang.org/x/xerrors. The Wrap function is essentially a missing function from the xerrors package.

Many thanks to @ribasushi who gave me the initial idea and code and suggested I make it into a standalone package.

Usage

Wrap an error:

f, err := os.Open("myfile.txt")
if err != nil {
	return werr.Wrap(err) // return the error with the stack frame embedded 
}

Print a wrapped error:

// Just print the wrapped error
fmt.Printf("got error %v", err)

// Print a full stack trace on multiple lines
fmt.Printf("got error %+v", err)

License

This is free and unencumbered software released into the public domain. For more information, see http://unlicense.org/ or the accompanying UNLICENSE file.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Wrap

func Wrap(err error) error

Wrap annotates an error with the current stack frame.

Example
package main

import (
	"errors"
	"fmt"
	"runtime"
	"strings"

	"golang.org/x/xerrors"
)

func source() error {
	return errors.New("base error")
}

func caller1() error {
	return Wrap(source())
}

func caller2() error {
	return Wrap(caller1())
}

var (
	_ error             = (*werr)(nil)
	_ fmt.Formatter     = (*werr)(nil)
	_ xerrors.Formatter = (*werr)(nil)
	_ xerrors.Wrapper   = (*werr)(nil)
)

var ErrBase = errors.New("base error")

func main() {
	base := source()
	fmt.Printf("%v\n", base)

	level1 := caller1()
	fmt.Printf("level 1: %v\n", level1)
	fmt.Println(stripPath(fmt.Sprintf("level 1 detail: %+v\n", level1)))

	level2 := caller2()
	fmt.Printf("level 2: %v\n", level2)
	fmt.Println(stripPath(fmt.Sprintf("level 2 detail: %+v", level2)))

}

func stripPath(s string) string {
	_, filename, _, ok := runtime.Caller(0)
	if !ok {
		return s
	}

	if idx := strings.LastIndex(filename, "/werr/err_test.go"); idx != -1 {
		path := filename[:idx]
		s = strings.ReplaceAll(s, path, "{path}")
	}

	return s
}
Output:

base error
level 1: base error
level 1 detail: base error:
    github.com/iand/werr.caller1
        {path}/werr/err_test.go:17

level 2: base error
level 2 detail: base error:
    github.com/iand/werr.caller1
        {path}/werr/err_test.go:17
    github.com/iand/werr.caller2
        {path}/werr/err_test.go:21

Types

type Formatter

type Formatter = xerrors.Formatter

type Printer

type Printer = xerrors.Printer

Jump to

Keyboard shortcuts

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