Categorygithub.com/axkit/errors
repositorypackage
0.2.4
Repository: https://github.com/axkit/errors.git
Documentation: pkg.go.dev

# README

errors GoDoc Build Status Coverage Status Go Report Card

errors

The errors package provides an enterprise approach of error handling. Drop in replacement of standard errors package.

Motivation

Make errors helpful for quick problem localization. Reduce amount of emails to the helpdesk due to better explained error reason.

Requirements

  • Wrapping: enhance original error message with context specific one;
  • Capture the calling stack;
  • Cut calling stack related to the HTTP framework;
  • Enhance error with key/value pairs, later could be written into structurized log;
  • Enhance error with the code what can be refered in documentation. (i.g. ORA-0600 in Oracle);
  • Enhance error with severity level;
  • Support different JSON representation for server and client;
  • Possibility to mark any error as protected. It will not be presented in client's JSON.
  • Notify SRE if needed.

Installation

go get -u github.com/axkit/error

Usage Examples

Catch and Enhance Standard Go Error

func (srv *CustomerService)WriteJSON(w io.Writer, c *Customer) (int, error) {

    buf, err := json.Marshal(src)
    if err != nil {
        return 0, errors.Catch(err).Critical().Set("customer", c).StatusCode(500).Msg("internal error")
    }

    n, err := w.Write(buf)
    if err != nil {
        // Level is Tiny by default. 
        return 0, errors.Catch(err).StatusCode(500).Msg("writing to stream failed").Code("APP-0001")
    }
     
    return n, nil  
}

Catch and Enhance Already Catched Error

func AllowedProductAmount(balance, price int) (int, error) {

    res, err := Calc(balance, price)
    if err != nil {
        return 0, errors.Catch(err).SetPairs("balance", balance, "price", price).Msg("no allowed products")
    }

    return res, nil
}


func Calc(a, b int) (int, error) {

    if b == 0 {
        return 0, errors.New("divizion by zero").Critical()
    }

    return a/b, nil
}

Recatch NotFound Error Conditionally

There is a special function errors.IsNotFound() that returns true error has StatusCode = 404 or created using errors.NotFound().

func (srv *CustomerService)AcceptPayment(customerID int, paymentAmount int64) error {

    c, err := srv.repo.CustomerByID(id)
    if err != nil {
        if errors.IsNotFound(err) {
            return nil, errors.Catch(err).Medium().Msg("invalid customer")
        }
        return return nil, errors.Catch(err).Critical().Msg("internal error")
    }

    return c, nil
}

func (srv *CustomerService)CustomerByID(id int) (*Customer, error) {

    c, ok := srv.repo.CustomerByID(id)
    if !ok {
        return nil, errors.NotFound("customer not found").Set("id", id)
    }

    return c, nil
}

Write Error Responce to Client

    err := doSmth()
    
    // err is standard error  
    fmt.Println(errors.ToClientJSON(err))

    // Output:
    {"msg":"result of Error() method"}

Write Error Responce to Server Log

Send Alarm to SRE

License

MIT