go: github.com/samsarahq/go/oops Index | Files | Directories

package oops

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

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

Package Files

doc.go oops.go

func Cause Uses

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 Uses

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 Uses

func Frames(err error) [][]Frame

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

func Recover Uses

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 Wrapf Uses

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.

type Frame Uses

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.

Directories

PathSynopsis
example

Package oops imports 5 packages (graph) and is imported by 12 packages. Updated 2019-02-01. Refresh now. Tools for package owners.