errs

package module
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2020 License: MIT Imports: 8 Imported by: 6

README

errs

Carve out of errors package from the upspin project

Documentation

Overview

Package errs is a modified copy of the upspin.io/errors package Copyright 2016 The Upspin Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. Package errs defines the error handling used by all Upspin software.

Index

Examples

Constants

View Source
const Separator = "] "

Separator is the string used to separate nested errors. By default, to make errors easier on the eye, nested errors are indented on a new line. A server may instead choose to keep each error on a single line by modifying the separator string, perhaps to ":: ". was previously var Separator = ":\n\t" changed to remove Global var

Variables

This section is empty.

Functions

func E

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

E builds an error value from its arguments. There must be at least one argument or E panics. The type of each argument determines its meaning. If more than one argument of a given type is presented, only the last one is recorded.

The types are:

upspin.PathName
	The Upspin path name of the item being accessed.
upspin.UserName
	The Upspin name of the user attempting the operation.
errors.Op
	The operation being performed, usually the method
	being invoked (Get, Put, etc.).
string
	Treated as an error message and assigned to the
	Err field after a call to errors.Str. To avoid a common
	class of misuse, if the string contains an @, it will be
	treated as a PathName or UserName, as appropriate. Use
	errors.Str explicitly to avoid this special-casing.
errors.Kind
	The class of error, such as permission failure.
error
	The underlying error that triggered this one.

If the error is printed, only those items that have been set to non-zero values will appear in the result.

If Kind is not specified or Other, we set it to the Kind of the underlying error.

Example
package main

import (
	"fmt"

	"github.com/gilcrest/errs"
)

func main() {
	err := layer4()

	fmt.Println(err)
}

func layer4() error {
	const op errs.Op = "errors/layer4"
	err := layer3()
	return errs.E(op, err)
}

func layer3() error {
	const op errs.Op = "errors/layer3"
	err := layer2()
	return errs.E(op, err)
}

func layer2() error {
	const op errs.Op = "errors/layer2"
	err := layer1()
	return errs.E(op, err)
}

func layer1() error {
	const op errs.Op = "errors/layer1"
	return errs.E(op, errs.Validation, errs.Parameter("testParam"), errs.Code("0212"), "Actual error message")
}
Output:

errors/layer4: input_validation_error] errors/layer3] errors/layer2] errors/layer1|: Actual error message

func HTTPErrorResponse added in v0.6.0

func HTTPErrorResponse(w http.ResponseWriter, logger zerolog.Logger, err error)

HTTPErrorResponse takes a writer, error and a logger, performs a type switch to determine if the type is an Error (which meets the Error interface as defined in this package), then sends the Error as a response to the client. If the type does not meet the Error interface as defined in this package, then a proper error is still formed and sent to the client, however, the Kind and Code will be Unanticipated. Logging of error is also done using https://github.com/rs/zerolog

Example
package main

import (
	"fmt"
	"net/http/httptest"
	"os"

	"github.com/rs/zerolog"

	"github.com/gilcrest/errs"
)

func main() {

	w := httptest.NewRecorder()
	logger := setupLogger()

	err := layer4()
	errs.HTTPErrorResponse(w, logger, err)

	fmt.Println(w.Body)
}

func layer4() error {
	const op errs.Op = "errors/layer4"
	err := layer3()
	return errs.E(op, err)
}

func layer3() error {
	const op errs.Op = "errors/layer3"
	err := layer2()
	return errs.E(op, err)
}

func layer2() error {
	const op errs.Op = "errors/layer2"
	err := layer1()
	return errs.E(op, err)
}

func layer1() error {
	const op errs.Op = "errors/layer1"
	return errs.E(op, errs.Validation, errs.Parameter("testParam"), errs.Code("0212"), "Actual error message")
}

func setupLogger() zerolog.Logger {
	zerolog.TimeFieldFormat = ""

	zerolog.SetGlobalLevel(zerolog.DebugLevel)

	return zerolog.New(os.Stdout).With().Logger()
}
Output:

{"level":"error","error":"errors/layer4: input_validation_error] errors/layer3] errors/layer2] errors/layer1|: Actual error message","HTTPStatusCode":400,"Kind":"input_validation_error","Parameter":"testParam","Code":"0212","message":"Response Error Sent"}
{"error":{"kind":"input_validation_error","code":"0212","param":"testParam","message":"Actual error message"}}

func KindIs

func KindIs(kind Kind, err error) bool

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

func Match

func Match(err1, err2 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 iff 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.

For example,

Match(errors.E(upspin.UserName("joe@schmoe.com"), errors.Permission), err)

tests whether err is an Error with Kind=Permission and User=joe@schmoe.com.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/gilcrest/errs"
)

func main() {
	path := errs.PathName("jane@doe.com/file")
	user := errs.UserName("joe@blow.com")
	err := errors.New("network unreachable")
	// Construct an error, one we pretend to have received from a test.
	got := errs.E(errs.Op("Get"), path, user, errs.IO, err)
	// Now construct a reference error, which might not have all
	// the fields of the error from the test.
	expect := errs.E(user, errs.IO, err)
	fmt.Println("Match:", errs.Match(expect, got))
	// Now one that's incorrect - wrong Kind.
	got = errs.E(errs.Op("Get"), path, user, errs.Permission, err)
	fmt.Println("Mismatch:", errs.Match(expect, got))
}
Output:

Match: true
Mismatch: false

Types

type BazError

type BazError struct {
	Reason string
	Inner  error
}

BazError is a temp error until I figure this out

func (BazError) Error

func (e BazError) Error() string

func (BazError) Unwrap

func (e BazError) Unwrap() error

Unwrap does some unwrapping

type Code

type Code string

Code is a human-readable, short representation of the error

type ErrResponse

type ErrResponse struct {
	Error ServiceError `json:"error"`
}

ErrResponse is used as the Response Body

type Error

type Error struct {
	// Path is the path name of the item being accessed.
	Path PathName
	// User is the Upspin name of the user attempting the operation.
	User UserName
	// Op is the operation being performed, usually the name of the method
	// being invoked (Get, Put, etc.). It should not contain an at sign @.
	Op Op
	// Kind is the class of error, such as permission failure,
	// or "Other" if its class is unknown or irrelevant.
	Kind Kind
	// Param is for when the error is parameter-specific and represents the parameter
	// related to the error.
	Param Parameter
	// Code is a human-readable, short representation of the error
	Code Code
	// StripError denotes whether to remove the error "stack"
	// If true, the error "stack" details are removed, if false,
	// the error "stack" details are appended
	StripError bool
	// The underlying error that triggered this one, if any.
	Err error
}

Error is the type that implements the error interface. It contains a number of fields, each of different type. An Error value may leave some values unset.

Example
package main

import (
	"fmt"

	"github.com/gilcrest/errs"
)

func main() {
	path := errs.PathName("jane@doe.com/file")
	user := errs.UserName("joe@blow.com")
	// Single error.
	e1 := errs.E(errs.Op("Get"), path, errs.IO, "network unreachable")
	fmt.Println("\nSimple error:")
	fmt.Println(e1)
	// Nested error.
	fmt.Println("\nNested error:")
	e2 := errs.E(errs.Op("Read"), path, user, errs.Other, e1)
	fmt.Println(e2)
}
Output:

Simple error:
Get: jane@doe.com/file: I/O_error|: network unreachable

Nested error:
Read: jane@doe.com/file, user joe@blow.com: I/O_error] Get|: network unreachable

func (*Error) Error

func (e *Error) Error() string

func (Error) Unwrap

func (e Error) Unwrap() error

Unwrap method allows for unwrapping errors using errors.As

type InputUnwanted

type InputUnwanted string

InputUnwanted is an error type that can be used when validating input fields that have a value, but should should not

func (InputUnwanted) Error

func (e InputUnwanted) Error() string

type Kind

type Kind uint8

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

const (
	Other           Kind = iota // Unclassified error. This value is not printed in the error message.
	Invalid                     // Invalid operation for this type of item.
	Permission                  // Permission denied.
	IO                          // External I/O error such as network failure.
	Exist                       // Item already exists.
	NotExist                    // Item does not exist.
	Private                     // Information withheld.
	Internal                    // Internal error or inconsistency.
	BrokenLink                  // Link target does not exist.
	Database                    // Error from database.
	Validation                  // Input validation error.
	Unanticipated               // Unanticipated error.
	InvalidRequest              // Invalid Request
	Unauthenticated             // User did not properly authenticate
	Unauthorized                // User is not authorized for the resource
)

Kinds of errors.

The values of the error kinds are common between both clients and servers. Do not reorder this list or remove any items since that will change their values. New items must be added only to the end.

func (Kind) String

func (k Kind) String() string

type MissingField

type MissingField string

MissingField is an error type that can be used when validating input fields that do not have a value, but should

func (MissingField) Error

func (e MissingField) Error() string

type Op

type Op string

Op describes an operation, usually as the package and method, such as "key/server.Lookup".

type Parameter

type Parameter string

Parameter is for parameter-specific errors and represents the parameter related to the error.

type PathName

type PathName string

A PathName is just a string representing a full path name. It is given a unique type so the API is clear. Example: gopher@google.com/burrow/hoard

type ServiceError

type ServiceError struct {
	Kind    string `json:"kind,omitempty"`
	Code    string `json:"code,omitempty"`
	Param   string `json:"param,omitempty"`
	Message string `json:"message,omitempty"`
}

ServiceError has fields for Service errors. All fields with no data will be omitted

type UserName

type UserName string

UserName is a string representing a user

Jump to

Keyboard shortcuts

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