serrors

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2024 License: Apache-2.0 Imports: 11 Imported by: 6

Documentation

Overview

Package serrors provides enhanced errors. Errors created with serrors can have additional log context in form of key value pairs. The package provides wrapping methods. The returned errors support new Is and As error functionality. For any returned error err, errors.Is(err, err) is always true, for any err which wraps err2 or has err2 as msg, errors.Is(err, err2) is always true, for any other combination of errors errors.Is(x,y) can be assumed to return false.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsTemporary

func IsTemporary(err error) bool

IsTemporary returns whether err is or is caused by a temporary error.

func IsTimeout

func IsTimeout(err error) bool

IsTimeout returns whether err is or is caused by a timeout error.

func Join added in v0.9.0

func Join(err, cause error, errCtx ...interface{}) error

Join returns an error that associates the given error, with the given cause (an underlying error) unless nil, and the given context.

A stack dump is added unless cause is a basicError or joinedError (in which case it is assumed to contain a stack dump).

The returned error supports Is. If cause isn't nil, Is(cause) returns true. Is(error) returns true.

This is best used as an alternative to Wrap when deriving an error from a sentinel error. If there is an underlying error it may be used as the cause (with the same effect as Wrap. When creating a new error (not due to an underlying error) nil may be passed as the cause. In that case the result is a sentinel error enriched with context. For such a purpose this is better than Wrap, since Wrap would retain any irrelevant context possibly attached to the sentinel error and store a redundant message string.

Example
package main

import (
	"errors"
	"fmt"
	"io"

	"github.com/scionproto/scion/pkg/private/serrors"
)

func main() {
	// ErrNoProgress is a sentinel error defined at package scope. cause is an error from a lower
	// layer, based on ErrNoSpace, with an more specific message.
	var cause = fmt.Errorf("sd0 unresponsive: %w", io.ErrNoProgress)
	// ErrDB is a sentinel error defined at package scope in the upper layer.
	var ErrDB = errors.New("db")
	wrapped := serrors.Join(ErrDB, cause, "ctx", 1)

	// Now we can identify specific errors:
	fmt.Println(errors.Is(wrapped, io.ErrNoProgress))
	fmt.Println(errors.Is(wrapped, cause))
	// But we can also identify the broader error class ErrDB:
	fmt.Println(errors.Is(wrapped, ErrDB))

	fmt.Printf("\n%v", wrapped)
}
Output:

true
true
true

db {ctx=1}: sd0 unresponsive: multiple Read calls return no data or error

func JoinNoStack added in v0.12.0

func JoinNoStack(err, cause error, errCtx ...interface{}) error

JoinNoStack behaves like Join except that no stack dump is added regardless of cause's underlying type.

Example
package main

import (
	"fmt"

	"github.com/scionproto/scion/pkg/private/serrors"
)

func main() {
	// BrokenPacket is a sentinel error defined at package scope.
	var brokenPacket = serrors.New("invalid packet")
	// ErrBadL4 is a sentinel error defined at package scope.
	var ErrBadL4 = serrors.New("Unsupported L4 protocol")
	addedCtx := serrors.JoinNoStack(brokenPacket, ErrBadL4, "type", "SCTP")

	fmt.Println(addedCtx)
}
Output:

invalid packet {type=SCTP}: Unsupported L4 protocol

func New

func New(msg string, errCtx ...interface{}) error

New creates a new basicError with the given message and context, plus a stack dump. It returns a pointer as the underlying type of the error interface object. Avoid using this in performance-critical code: it is the most expensive variant. If used to construct other errors, such as with Join, the embedded stack trace and context serve no purpose. Therefore, to make sentinel errors, errors.New() should be preferred.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/scionproto/scion/pkg/private/serrors"
)

func main() {
	err1 := serrors.New("errtxt")
	err2 := serrors.New("errtxt")

	// Self equality always works:
	fmt.Println(errors.Is(err1, err1))
	fmt.Println(errors.Is(err2, err2))
	// On the other hand different errors with same text should not be "equal".
	// That is to prevent that errors with same message in different packages
	// with same text are seen as the same thing:
	fmt.Println(errors.Is(err1, err2))
}
Output:

true
true
false

func Wrap

func Wrap(msg string, cause error, errCtx ...interface{}) error

Wrap returns an error that associates the given error, with the given cause (an underlying error) unless nil, and the given context.

A stack dump is added unless cause is a basicError or joinedError (in which case it is assumed to contain a stack dump).

The returned error supports Is. Is(cause) returns true.

This is best used when adding context to an error that already has some. The existing error is used as the cause; all of its existing context and stack trace are preserved for printing and logging. The new context is attached to the new error.

Passing nil as the cause is legal but of little use. In that case, prefer New. The only difference is the underlying type of the returned interface.

To enrich a sentinel error with context only, do not use

Wrap("dummy message", sentinel, ...)

instead use Join

Join(sentinel, nil, ...)

Wrap may be useful to enrich sentinel errors if the main message needs to be different than that supplied by the sentinel error.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/scionproto/scion/pkg/private/serrors"
)

func main() {
	// ErrNoSpace is an error defined at package scope. It should be is an error from lower layers,
	// with some context already attached.
	var ErrNoSpace = serrors.New("no space", "dev", "sd0")
	wrappedErr := serrors.Wrap("wrap with more context", ErrNoSpace, "ctx", 1)

	fmt.Println(errors.Is(wrappedErr, ErrNoSpace))
	fmt.Printf("\n%v", wrappedErr)
}
Output:

true

wrap with more context {ctx=1}: no space {dev=sd0}

func WrapNoStack added in v0.12.0

func WrapNoStack(msg string, cause error, errCtx ...interface{}) error

WrapNoStack behaves like Wrap, except that no stack dump is added, regardless of cause's underlying type.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/scionproto/scion/pkg/private/serrors"
)

func main() {
	// ErrBadL4 is a sentinel defined at package scope.
	var ErrBadL4 = errors.New("Unsupported L4 protocol")
	addedCtx := serrors.WrapNoStack("parsing packet", ErrBadL4, "type", "SCTP")

	fmt.Println(addedCtx)
}
Output:

parsing packet {type=SCTP}: Unsupported L4 protocol

Types

type Frame

type Frame uintptr

Frame represents a program counter inside a stack frame. For historical reasons if Frame is interpreted as a uintptr its value represents the program counter + 1.

func (Frame) Format

func (f Frame) Format(s fmt.State, verb rune)

Format formats the frame according to the fmt.Formatter interface.

%s    source file
%d    source line
%n    function name
%v    equivalent to %s:%d

Format accepts flags that alter the printing of some verbs, as follows:

%+s   function name and path of source file relative to the compile time
      GOPATH separated by \n\t (<funcname>\n\t<path>)
%+v   equivalent to %+s:%d

func (Frame) MarshalText

func (f Frame) MarshalText() ([]byte, error)

MarshalText formats a stacktrace Frame as a text string. The output is the same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.

type List

type List []error

List is a slice of errors.

func (List) Error

func (e List) Error() string

Error implements the error interface.

func (List) MarshalLogArray

func (e List) MarshalLogArray(ae zapcore.ArrayEncoder) error

MarshalLogArray implements zapcore.ArrayMarshaller for nicer logging format of error lists.

func (List) ToError

func (e List) ToError() error

ToError returns the object as error interface implementation.

type StackTrace

type StackTrace []Frame

StackTrace is stack of Frames from innermost (newest) to outermost (oldest).

func (StackTrace) Format

func (st StackTrace) Format(s fmt.State, verb rune)

Format formats the stack of Frames according to the fmt.Formatter interface.

%s	lists source files for each Frame in the stack
%v	lists the source file and line number for each Frame in the stack

Format accepts flags that alter the printing of some verbs, as follows:

%+v   Prints filename, function, and line number for each Frame in the stack.

Jump to

Keyboard shortcuts

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