errorutils

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 5, 2025 License: MIT Imports: 7 Imported by: 13

README

Errorutils

Errorutils is a reusable optional functions error framework that extends the logrus package. It provides a simple and flexible way to instantiate custom error types with additional information.

Installation

To use Errorutils in your Go project, you can install it using go get:

> go get github.com/TgenNorth/errorutils

Usage

To use Errorutils in your project, you first need to import it:

package myPackage
import "github.com/TGenNorth/errorutils"
When to use errorutils

Errorutils enables error checking and handling at the location where the error is generated or captured. In general, our recommendation is to use ExitOnFail() in places where panic() or logrus.Error() could be used, WarnOnFail() provides notifications to users in cases where the program could continue operating. These functions do not need to be wrapped in if conditions to check for nil.

When not to use errorutils

The functionality of this package is constrained to only handling failure errors. The following are some examples where the use of alternatives is encouraged:

  • In places where it makes more sense to return the error, use the common construct if err != nil.
  • In code tests, do not replace any of the error and logging functionality of a testing object.
  • Sharing information such as EOF should not be handled with this framework.
  • Recoverable panics or terminations that expect the defer stack to be executed should rely on built-in panic() instead.
  • The Details error type is not meant to be compared.
Creating a new error with line references

To add details to an error, use the New function. This function takes an error and functions of type Option that take in the informational values.

err := myfunc()
if err !=nil {
    detailed := errorutils.New(err, errorutils.WithExitCode(3), errorutils.WithLineRef("OKP8PK1CosD"))
    return detailed
}

Errorutils provides a way to add line references to error values that are only printed when logrus.DebugLevel is enabled. Line references indicate the location in the code where the error occurred. Ideally, unique identifiers such as random strings are better to avoid outdating the reference.

Error handling abstraction

Errorutils offers error handling that replaces simple cases of error checking with if statements. For more complex error handling use errorutils.HandleFailure as described below.

err := myFunc()
//handle with one of these
errorutils.LogFailures(err)
errorutils.LogFailuresf(err, "other error info: %%s")
errorutils.WarnOnFail(err)
errorutils.WarnOnFailf(err, "additional info: %%s")
errorutils.ExitonFail(err)
Handler functions and safe closer

Errorutils accepts handler functions that deal with errors consistently. Additionally, the package offers safe closing functions that visibilize closing errors for Closers.

The following example based on TGenNorth/kmare/database, stashes the result if writing fails.

func x() {
    //... this function did some valuable work that needs to be saved.
    seqFile, err := os.Create(filepath.Join(libLoc, fmt.Sprintf("%s.fasta", name)))
        if err != nil {
            goto handleError
        }

    {
        defer errorutils.NotifyClose(seqFile)
        //bufio writer
        seqWriter := bufio.NewWriter(seqFile)
        _, err = seqWriter.Write(formattedBytes)
        indexWriter.Flush()
    }
handleError:
    // if file cannot be created or there is a writting error, stash the sequences
    stashingErr := errorutils.HandleFailure(
                    err,
                    errorutils.Handler(func() *Details {
                        r, err2 := writeTemp(sha1)
                        if err2 != nil {
                        return errorutils.New(err2)
                        }
                        _, err2 = r.Write(formattedBytes)
                        errorutils.SafeClose(r, &err2)
                        return errorutils.New(err2)
                        }),
                    errorutils.WithMsg(fmt.Sprintf("sequences file could not be created for %s at %s, a stash was ATTEMPTED as temporaryfile accessible with hash name %s", name, libLoc, sha1)),
                    errorutils.WithLineRef("uDIKN3XCREp"))
    // in this case format string must have a scaped string verb '%%s' to ensure WarnOnFailf will have a place to print error value.
    errorutils.WarnOnFailf(stashingErr, fmt.Sprintf("Sequences for %s cound not be saved: %%s\nSkipping...", name), errorutils.WithLineRef("XqZsHJI8ABs"))
}

License

Errorutils is released under our custom Academic and Research license. See LICENSE for details.

Documentation

Overview

ErrorUtils facilitates error handling and reporting

The package provides a custom error type that can be used to add additional information to an error message. The recommendation is to use the NewReport function to create a new error report. The lineRef is only used in debug mode. The exitcode is only used for terminating errors. Return simple errors such as user errors with fmt.Errorf and not with NewReport to avoid verbosity. Details type is capable of wrapping and extends urfave/cli functionality to retain information on exit codes.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExitOnFail

func ExitOnFail(err error, o ...Option)

irrecoverable programming error

func LogFailures

func LogFailures(err error, o ...Option)

Failure has been detected, log it

func LogFailuresf

func LogFailuresf(err error, format string, o ...Option)

Failure has been detected, log it formatted string should contain one '%s' for the error message

func NotifyClose

func NotifyClose(file io.Closer)

NotifyClose visibilizes errors on defer for functions that do not return an error

func PanicOnFail

func PanicOnFail(err error, o ...Option)

depriecated legacy panic, replace with ExitOnFail or use panic() instead does not support altPrint and can't handle detail nils

func SafeClose

func SafeClose(file io.Closer, origErr *error)

SafeClose closes a file and appends any errors to the error that a function is supposed to return https://wstrm.dev/posts/errors-join-heart-defer/

func WarnOnFail

func WarnOnFail(err error, o ...Option)

func WarnOnFailf

func WarnOnFailf(err error, format string, o ...Option)

formatted string should contain one '%s' for the error message

Types

type Details

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

Details is a custom error type that can be used to add additional information to an error message

func HandleFailure

func HandleFailure(err error, handleFn Handler, o ...Option) (err2 *Details)

HandleFailure handles an error by logging it and then calling the handler function If the handler function returns an error, it is logged as well

func New

func New(err error, o ...Option) *Details

Adds context to an error. Subtle nil check: returns nil if both error and withInner are nil. Bubbles up inner if err is nil. WithMessage does *not* guarantee a new error report (use NewReport); undefined behavior with multiple withInner options.

func NewReport

func NewReport(msg string, lineRef string, o ...Option) *Details

Succinct syntax for new error report

Recommended for errors that could potentially be bugs, otherwise use fmt.Errorf. LineRef is only used in debug mode

func (*Details) Error

func (e *Details) Error() string

func (*Details) ExitCode

func (e *Details) ExitCode() int

func (*Details) HasAltprint

func (e *Details) HasAltprint() bool

func (*Details) Striptype

func (e *Details) Striptype() error

func (*Details) Unwrap

func (e *Details) Unwrap() error

type Handler

type Handler func() *Details

func (Handler) Handle

func (fn Handler) Handle() *Details

type Option

type Option func(*Details)

func WithAltPrint

func WithAltPrint(altM string) Option

Alternative message for nil errors

func WithExitCode

func WithExitCode(exitcode int) Option

func WithInner

func WithInner(err error) Option

func WithLineRef

func WithLineRef(lineRef string) Option

WithLineRef is an option to add a line reference to the error message. use a random string instead of the line number. Calling this option on an existing Details value will append the new lineref to the existing one with a '_' separator.

func WithMsg

func WithMsg(msg string) Option

Jump to

Keyboard shortcuts

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