errorx

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 7, 2022 License: BSD-3-Clause Imports: 4 Imported by: 5

README

Errorx

Error package ideas comes and is a subset copy from Upspin project.

Error

Error is value in Go, and because error is a value, we need to check them. Go proverbs said:

Don't just check errorx, handle them gracefully

and

Log an error or return the error, never both - Dave Channey

Why another error package

As Dave Channey said, we should log an error or just return the error, but never both. But how can we log a meaningful error in go and still can compare the error itself?

In order to do that, we need a modified implementation of error. Put more context into error and print the context when we need to log. That way we don't need to log and return an error at the same time, just to put more context into the log.

errorx function

In order to create a meaningful error from this package, we need to use errorx.E(args...) function. Why errorx.E() instead of errorx.New()like errorx package from Go itself?

  1. Following upspin convention to create the error.
  2. Let the standard be a standard (errors.New), and the new one should have a new convention.

Example

Simple error creation
import "github.com/rizalgowandy/gdk/pkg/errorx/v2"

func main() {
    err := errorx.E("this is error from library")
    // do something with the error
}

Error with fields

Error with fields is useful to give context to error. For example user_id of user.

import "github.com/rizalgowandy/gdk/pkg/errorx/v2"

func main() {
    err := errorx.E("this is error from library", errorx.Fields{"user_id": 1234})
    // do something with the error
}
Error with operations

Sometimes we need to know what kind of operations we do in error, we want to know where exactly error happens.

import "github.com/rizalgowandy/gdk/pkg/errorx/v2"

func main() {
    err := SomeFunction()
    // do something with the error
}

func SomeFunction() error {
    const op errorx.Op = "userService.FindUser"
    return errorx.E(op, "this is error from library")
}
Real life example

This is an example where we need to call a function from handler and we need to know the error context

import (
    "net/http"
    "strings"

    "github.com/rizalgowandy/gdk/pkg/errorx/v2"
)

// Error variables for error matching example
var (
    // Given string parameter on errorx.E() will directly converted to error message
    ErrParamIsEqual      = errorx.E("param1 is equal to param2")
    ErrMoreThanConstanta = errorx.E("param1 length is more than constanta")
)

func main() {
    http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        param1 := r.FormValue("param1")
        param2 := r.FormValue("param2")

        err := BusinessLogic(param1, param2)
        // sample implementation of errorx.Match() to handle error regarding to error types
        if errorx.Match(err, ErrParamIsEqual) {
            w.WriteHeader(http.StatusBadRequest)
            w.Write([]byte("Not OK"))
            return
        }

        w.WriteHeader(http.StatusOK)
        w.Write([]byte("OK"))
    })

    http.ListenAndServe(":9090", nil)
}

func BusinessLogic(param1, param2 string) error {
    const op errorx.Op = "business/BusinessLogic"

    if strings.Compare(param1, param2) == 0 {
        return errorx.E(ErrParamIsEqual, errorx.Fields{
            "param1": param1,
            "param2": param2,
        }, op)
    }
    return ResourceLogic(param1)
}

const constVal string = "constanta"

func ResourceLogic(param1 string) error {
    const op errorx.Op = "resource/ResourceLogic"

    if len(param1) > len(constVal) {
        return errorx.E(ErrMoreThanConstanta, op, errorx.Fields{"param1": param1})
    }
    return nil
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func E

func E(args ...interface{}) error

E for creating new error. error should always be the first param.

func Errorf

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

Errorf is equivalent to fmt.Errorf, but allows clients to import only this package for all error handling.

func Is

func Is(err error, code Code) bool

Is reports whether err is an *Error of the given Code. If err is nil then Is returns false.

func Match

func Match(errs1, errs2 error) bool

Match compares its two error arguments. It can be used to check for expected errors in tests. Both arguments must have underlying type *Error or Match will return false. Otherwise it returns true if every non-zero element of the first error is equal to the corresponding element of the second. If the Err field is a *Error, Match recurs on that field; otherwise it compares the strings returned by the Error methods. Elements that are in the second argument but not present in the first are ignored.

func New

func New(text string) error

New returns an error that formats as the given text. It is intended to be used as the error-typed argument to the E function.

Types

type Code

type Code string

Code defines the kind of error this is, mostly for use by systems that must act differently depending on the error.

const (
	CodeUnknown        Code = ""                // Unclassified or unknown error.
	CodePermission     Code = "permission"      // Permission denied.
	CodeInternal       Code = "internal"        // Internal error or inconsistency.
	CodeConflict       Code = "conflict"        // Action cannot be performed.
	CodeInvalid        Code = "invalid"         // Validation failed.
	CodeNotFound       Code = "not_found"       // Entity does not exist.
	CodeGateway        Code = "gateway"         // Gateway or third party service return error.
	CodeConfig         Code = "config"          // Wrong configuration.
	CodeCircuitBreaker Code = "circuit_breaker" // Circuit breaker error.
	CodeMarshal        Code = "marshal"         // JSON marshal error.
	CodeUnmarshal      Code = "unmarshal"       // JSON unmarshal error.
	CodeConversion     Code = "conversion"      // Conversion error, e.g. string to time conversion.
	CodeEncryption     Code = "encryption"      // Encryption error.
	CodeDecryption     Code = "decryption"      // Decryption error.
	CodeDB             Code = "db"              // Database operation error.
	CodeDBScan         Code = "db_scan"         // Database scan error.
	CodeDBExec         Code = "db_exec"         // Database exec error.
	CodeDBQuery        Code = "db_query"        // Database query error.
	CodeDBBegin        Code = "db_begin"        // Database begin transaction error.
	CodeDBCommit       Code = "db_commit"       // Database commit error.
	CodeDBRollback     Code = "db_rollback"     // Database rollback error.
)

Application error codes.

func GetCode

func GetCode(err error) Code

GetCode returns the code of the root error, if available. Otherwise returns CodeInternal.

type Error

type Error struct {
	// Underlying error.
	Err error

	// Codes used for Errs to identify known errors in the application.
	// If the error is expected by Errs object, the errors will be shown as listed in Codes.
	Code Code

	// Fields is a fields context similar to logrus.Fields.
	// Can be used for adding more context to the errors.
	Fields Fields

	// OpTraces is a trace of operations.
	OpTraces []Op

	// Message is a human-readable message.
	Message Message

	// Line describes current error original line.
	// Only injected when the underlying error is from standard error.
	Line Line

	// MetricStatus defines the kind of error should be tracked or not.
	MetricStatus MetricStatus
}

Error defines a standard application error.

func (*Error) Error

func (e *Error) Error() string

Error returns the string representation of the error message.

func (*Error) GetFields

func (e *Error) GetFields() Fields

GetFields return available fields in errors.

type Fields

type Fields map[string]interface{}

Fields of error

type Line

type Line string

Line describes the original err line.

type Message

type Message string

Message is a human-readable message.

type MetricStatus

type MetricStatus string

MetricStatus defines the kind of error should be tracked or not. Useful for alerting system.

const (
	MetricStatusSuccess     MetricStatus = "success"
	MetricStatusErr         MetricStatus = "error"
	MetricStatusExpectedErr MetricStatus = "expected_error"
)

type Op

type Op string

Op is operation of error.

Jump to

Keyboard shortcuts

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