The errors package provides an enterprise approach of error handling. Drop in replacement of standard errors package.
Make errors helpful for quick problem localization. Reduce amount of emails to the helpdesk due to better explained error reason.
- 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.
go get -u github.com/axkit/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
}
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
}
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
}
err := doSmth()
// err is standard error
fmt.Println(errors.ToClientJSON(err))
// Output:
{"msg":"result of Error() method"}
MIT