errors

package
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Jan 20, 2023 License: MIT Imports: 8 Imported by: 2

Documentation

Overview

Package errors provides a generic error carrying useful information:

  • StackTrace for debugging
  • 2 different messages: one for the end user and one for the developer
  • a Kind: a string that can act as an ID for errors
  • a httpStatus
  • a timestamp of when the error was created

This error implement the json.Marshaler and xml.Marshaler interface, so you can return this error in your http handlers.

It also implements the errors.Unwrap interface, allowing you to get the previous error.

It depends on the gapi/log package, as the error will implement several of its interfaces to log the errors correctly.

## Create a new error

To create a new error, simply call the Err() function and use the setter to set any data you want.

The setter functions will modify the data and won't create a new error, you don't need to reassign the error.

import (
	"net/http"
	"github.com/mwm-io/gapi/errors"
)

err := errors.Err("my error).
	WithKind("not_found").
	WithStatusCode(http.StatusNotFound).
	WithMessage("not found")

## Wrap an existing error

To wrap an existing error, simply call the Wrap() function. You can then modify the new error as you want.

Wrapping a nil error will return a nil value.

import (
	"fmt"
	"github.com/mwm-io/gapi/errors"
)

err := fmt.Errorf("source error")
newErr := errors.Wrap(err, "error").WithKind("new_kind")

### Populate data from the source error

You might want to carry more than just the message type from the source error.

In order to do that you need to implement the ErrorBuilder interface and register your builder with an init function.

Your builder should concern a single type of error.

You can read an example with the errors/google package.

import (
	"github.com/mwm-io/gapi/errors"
)

func init() {
	errors.AddBuilder()
}

var GrpcCodeErrorBuilder = errors.ErrorBuilderFunc(func(err errors.Error, sourceError error) errors.Error {
	sourceErrI, ok := sourceErr.(interface{ WithKind() string })
	if !ok {
		return err
	}

	return err.WithKind(sourceErrI.WithKind())
})

## Why is it an interface ?

You may wonder why we use an Error interface and why don't we use the FullError struct directly.

This is because `(*FullError)(nil) != nil`: a nil value with a concrete type won't match nil.

In order to keep the idiomatic `if Err("my err") != nil`, we always return the Error interface.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddBuilders

func AddBuilders(errorBuilders ...ErrorBuilder)

AddBuilders will register the given ErrorBuilder to be used.

Types

type Error

type Error interface {
	error
	Unwrap() error
	json.Marshaler
	xml.Marshaler
	Message() string
	Kind() string
	StatusCode() int
	Severity() gLog.Severity
	Timestamp() time.Time
	StackTrace() gLog.StackTrace

	WithMessage(string) Error
	WithMessagef(string, ...interface{}) Error
	WithKind(string) Error
	WithStatus(int) Error
	WithSeverity(gLog.Severity) Error
	WithTimestamp(time.Time) Error
	WithStackTrace(trace gLog.StackTrace) Error
}

Error represents the interface for the FullError struct. It is necessary so we can compare nil errors. (nil.(*FullError) != nil)

func Build

func Build(err Error, sourceError error) Error

Build will call all registered builders to add additional information on the given Error, depending on the sourceError

func Err

func Err(message string) Error

Err creates a new Error.

Example
err := Err("this is my error").
	WithMessage("message for the final user").
	WithKind("error").
	WithStatus(http.StatusBadGateway).
	WithSeverity(gLog.CriticalSeverity).
	WithStackTrace(stacktrace.New()).
	WithTimestamp(time.Now())

js, _ := err.MarshalJSON()

fmt.Println(string(js))
Output:

{"message":"message for the final user","kind":"error"}

func Wrap

func Wrap(err error) Error

Wrap will wrap the given error and return a new Error.

Example
sourceErr := fmt.Errorf("original error")
err := Wrap(sourceErr, "wrapped error")

fmt.Println(err.Error())
js, _ := err.MarshalJSON()
fmt.Println(string(js))

wrappedErr := errors.Unwrap(err)
fmt.Println(wrappedErr.Error())

var nilErr error
wrappedNilErr := Wrap(nilErr, "nil error")
fmt.Printf("%t\n", wrappedNilErr == nil)
Output:

wrapped error: original error
{"message":"wrapped error","kind":""}
original error
true

type ErrorBuilder

type ErrorBuilder interface {
	Build(err Error, sourceError error) Error
}

ErrorBuilder will try to interpret the sourceErr to populate Error with additional data.

type ErrorBuilderFunc

type ErrorBuilderFunc func(err Error, sourceError error) Error

ErrorBuilderFunc is a function that implements the ErrorBuilder interface.

func (ErrorBuilderFunc) Build

func (e ErrorBuilderFunc) Build(err Error, sourceError error) Error

Build implements the ErrorBuilder interface.

type FullError

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

FullError is a concrete error that implements the Error interface

func (*FullError) Error

func (e *FullError) Error() string

FullError implements the error interface. It will return the "developer" message in opposition to the user message, which is returned by FullError.Message

func (*FullError) Kind

func (e *FullError) Kind() string

Kind returns the error kind.

func (*FullError) MarshalJSON

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

MarshalJSON implements the json.Marshaler interface.

func (*FullError) MarshalXML

func (e *FullError) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error

MarshalXML implements the xml.Marshaler interface.

func (*FullError) Message

func (e *FullError) Message() string

Message returns the user message.

func (*FullError) Severity

func (e *FullError) Severity() gLog.Severity

Severity implements the gLog.WithSeverity interface.

func (*FullError) StackTrace

func (e *FullError) StackTrace() gLog.StackTrace

StackTrace returns the error stacktrace.

func (*FullError) StatusCode

func (e *FullError) StatusCode() int

StatusCode implements server.WithStatusCode

func (*FullError) Timestamp

func (e *FullError) Timestamp() time.Time

Timestamp returns the error timestamp.

func (*FullError) Unwrap

func (e *FullError) Unwrap() error

Unwrap implements the errors.Unwrap interface

func (*FullError) WithKind

func (e *FullError) WithKind(kind string) Error

WithKind sets the error kind.

func (*FullError) WithMessage

func (e *FullError) WithMessage(message string) Error

WithMessage sets the user message.

func (*FullError) WithMessagef added in v0.0.5

func (e *FullError) WithMessagef(message string, opts ...interface{}) Error

WithMessagef sets the user message with format.

func (*FullError) WithSeverity

func (e *FullError) WithSeverity(severity gLog.Severity) Error

WithSeverity sets the error severity.

func (*FullError) WithStackTrace

func (e *FullError) WithStackTrace(trace gLog.StackTrace) Error

WithStackTrace sets the error stacktrace.

func (*FullError) WithStatus

func (e *FullError) WithStatus(status int) Error

WithStatus sets the error status. It will also modify the severity for status >= 400

func (*FullError) WithTimestamp

func (e *FullError) WithTimestamp(t time.Time) Error

WithTimestamp sets the error timestamp.

type HttpError

type HttpError struct {
	Message string `json:"message" xml:"message"`
	Kind    string `json:"kind" xml:"kind"`
}

HttpError is used to json.Marshal or xml.Marshal FullError. You can use it to decode an incoming error.

Directories

Path Synopsis
Package google provides and registers error builders to interpret google errors into gapi errors.
Package google provides and registers error builders to interpret google errors into gapi errors.

Jump to

Keyboard shortcuts

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