oops

package module
v0.0.0-...-4b291d6 Latest Latest
Warning

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

Go to latest
Published: Feb 11, 2022 License: MIT Imports: 6 Imported by: 61

README

Package oops adds detailed stacktraces to your Go errors.

See https://godoc.org/github.com/samsarahq/go/oops.

Documentation

Overview

Package oops adds detailed stacktraces to your Go errors.

To use the oops package, calls oops.Errorf when creating a new error, and oops.Wrapf when returning nested errors. To access the original error, use oops.Cause. Each function in the callstack can add extra debugging information to help you track down errors.

An example error (from the program below) looks as follows:

20 is too large!

main.Foo
  github.com/samsarahq/go/oops/example/main.go:12
main.Legacy
  github.com/samsarahq/go/oops/example/main.go:19
main.Bar: Legacy(20) didn't work
  github.com/samsarahq/go/oops/example/main.go:24
main.Go.func1
  github.com/samsarahq/go/oops/example/main.go:35

main.Go: goroutine had a problem
  github.com/samsarahq/go/oops/example/main.go:38
main.main
  github.com/samsarahq/go/oops/example/main.go:42
runtime.main
  runtime/proc.go:185

The first time oops.Errorf or oops.Wrapf is called, it captures a stacktrace. To keep your stacktraces as detailed as possible, it is best to call oops.Wrapf every time you return an error. If you have no context to add, you can always pass an empty format string to oops.Wrapf.

When adding oops to an existing package or program, you might have intermediate functions that don't yet call oops.Wrapf when returning errors. That is no problem, as later calls to oops.Wrapf will attach their messages to right stackframe. However, you might as well add oops.Wrapf there as well!

Usage:

package main

import (
  "fmt"

  "github.com/samsarahq/go/oops"
)

// Foo creates new errors using oops.Errorf.
func Foo(i int) error {
  if i > 10 {
    return oops.Errorf("%d is too large!", i)
  }
  return nil
}

// Legacy is old code that does not use oops.
func Legacy(i int) error {
  return Foo(i)
}

// Bar wraps errors using Wrapf.
func Bar() error {
  if err := Legacy(20); err != nil {
    return oops.Wrapf(err, "Legacy(20) didn't work")
  }
  return nil
}

// Go wraps errors using Wrapf after receiving one from a channel!
func Go() error {
  ch := make(chan error)

  go func() {
    ch <- Bar()
  }()

  return oops.Wrapf(<-ch, "goroutine had a problem")
}

func main() {
  if err := Go(); err != nil {
    fmt.Print(err)
  }
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func As

func As(err error, target interface{}) bool

As finds the first error in err's chain that matches the type to which target points, and if so, sets the target to its value and returns true. An error matches a type if it is assignable to the target type, or if it has a method As(interface{}) bool such that As(target) returns true. As will panic if target is not a non-nil pointer to a type which implements error or is of interface type.

The As method should set the target to its value and return true if err matches the type to which target points.

func Cause

func Cause(err error) error

Cause extracts the cause error of an oops error. If err is not an oops error, err itself is returned.

You can use Cause to check if an error is an expected error. For example, if you know than EOF error is fine, you can handle it with Cause.

func Errorf

func Errorf(format string, a ...interface{}) error

Errorf creates a new error with a reason and a stacktrace.

Use Errorf in places where you would otherwise return an error using fmt.Errorf or errors.New.

Note that the result of Errorf includes a stacktrace. This means that Errorf is not suitable for storing in global variables. For such errors, keep using errors.New.

func Frames

func Frames(err error) [][]Frame

Frames extracts all frames from an oops error. If err is not an oops error, nil is returned.

func Is

func Is(err, target error) bool

Is reports whether any error in err's chain matches target.

An error is considered to match a target if it is equal to that target or if it implements a method Is(error) bool such that Is(target) returns true.

func MainStackToString

func MainStackToString(err error) string

MainStackToString will write the frames of the main goroutine to a string. This will return an empty string if the error is not an oopsError.

func Recover

func Recover(p interface{}) error

Recover recovers from a panic in a defer. If there is no panic, Recover() returns nil. To use, call oops.Recover(recover()) and compare the result to nil.

func SkipFrames

func SkipFrames(err error, numFrames int) error

SkipFrames skips numFrames from the stack trace and returns a new copy of the error. If numFrames is greater than the number of frames in err, SkipFrames will do nothing and return the original err.

func Unwrap

func Unwrap(err error) error

Unwrap returns the result of calling the Unwrap method on err, if err implements Unwrap. Otherwise, Unwrap returns nil.

func Wrapf

func Wrapf(err error, format string, a ...interface{}) error

Wrapf annotates an error with a reason and a stacktrace. If err is nil, Wrapf returns nil.

Use Wrapf in places where you would otherwise return an error directly. If the error passed to Wrapf is nil, Wrapf will also return nil. This makes it safe to use in one-line return statements.

To check if a wrapped error is a specific error, such as io.EOF, you can extract the error passed in to Wrapf using Cause.

Types

type Frame

type Frame struct {
	File     string
	Function string
	Line     int
	Reason   string
}

A Frame represents a Frame in an oops callstack. The Reason is the manual annotation passed to oops.Wrapf.

type Wrapper

type Wrapper interface {
	// Unwrap returns the next error in the error chain.
	// If there is no next error, Unwrap returns nil.
	Unwrap() error
}

A Wrapper provides context around another error.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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