Skip to content

An errors package that will help you handle them gracefully. It allows you to add contextual information to your errors, to wrap them and they even get a stack trace.

License

Notifications You must be signed in to change notification settings

zignd/errors

Repository files navigation

errors GoDocReport card

An errors package that will help you handle them gracefully. It allows you to add additional data to your errors, to wrap it and you even get a stack trace. Inspired by the github.com/pkg/errors package and Node.js' verror module.

Features

  • Add additional data to error values preventing long and hard to read error messages
  • Wrap existing error values into new ones
  • Stack traces for each error value
  • MultiError, wrap multiple errors values into a single one; great for concurrent workflows that may generate multiple errors
  • Pretty print of the whole error value and support JSON marshalling to ease the serialization (check the "Quick demo" section)

Installation

go get -u github.com/zignd/errors

Documentation

For a better understanding of the features provided by the package check the documentation at: pkg.go.dev/github.com/zignd/errors

Quick demo

There's an example at examples/example1/example1.go that shows how to use the package.

Here's the code for the example:
package main import ( "encoding/json""fmt""github.com/zignd/errors" ) funccreateTransaction(idstring) error{bank:="bank_123456"iferr:=updateDatabase(); err!=nil{returnerrors.Wrapdf(err, errors.Data{"transactionId": id, "userId": "67890", }, "failed to complete the transaction on %s", bank) } returnnil } funcupdateDatabase() error{iferr:=createConnection(); err!=nil{returnerrors.Wrapd(err, errors.Data{"tableName": "transactions", "operation": "update", }, "failed to update the database") } returnnil } funccreateConnection() error{iferr:=open(); err!=nil{returnerrors.Wrapd(err, errors.Data{"server": "db-server-01", "timeoutSeconds": 30, }, "connection timeout") } returnnil } funcopen() error{returnerrors.Errord(errors.Data{"network": "internal", "severity": "high", }, "network instability detected") } funcmain(){iferr:=createTransaction("tx_123456"); err!=nil{b, _:=json.MarshalIndent(err, "", " ") fmt.Println("Error logged as a JSON structure using the json.MarshalIndent:") fmt.Printf("%s\n", b) b, _=json.Marshal(err) fmt.Println("\nError logged as a JSON structure using the json.Marshal:") fmt.Printf("%s\n", b) fmt.Println("\nError logged using the s format specifier:") fmt.Printf("%s\n", err) fmt.Println("\nError logged using the +v format specifier:") fmt.Printf("%+v\n", err) } }
Here's the execution of the example:
$ go run examples/example1/example1.go Error logged as a JSON structure using the json.MarshalIndent: [{"data":{"transactionId": "tx_123456", "userId": "67890" }, "message": "failed to complete the transaction on bank_123456", "stack": [ "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:13", "main.main @ /root/hack/errors/examples/example1/example1.go:52", "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194", "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651" ] },{"data":{"operation": "update", "tableName": "transactions" }, "message": "failed to update the database", "stack": [ "main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:24", "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12", "main.main @ /root/hack/errors/examples/example1/example1.go:52", "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194", "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651" ] },{"data":{"server": "db-server-01", "timeoutSeconds": 30 }, "message": "connection timeout", "stack": [ "main.createConnection @ /root/hack/errors/examples/example1/example1.go:35", "main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23", "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12", "main.main @ /root/hack/errors/examples/example1/example1.go:52", "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194", "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651" ] },{"data":{"network": "internal", "severity": "high" }, "message": "network instability detected", "stack": [ "main.open @ /root/hack/errors/examples/example1/example1.go:45", "main.createConnection @ /root/hack/errors/examples/example1/example1.go:34", "main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23", "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12", "main.main @ /root/hack/errors/examples/example1/example1.go:52", "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194", "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651" ] } ] Error logged as a JSON structure using the json.Marshal: [{"data":{"transactionId":"tx_123456","userId":"67890"},"message":"failed to complete the transaction on bank_123456","stack":["main.createTransaction @ /root/hack/errors/examples/example1/example1.go:13","main.main @ /root/hack/errors/examples/example1/example1.go:52","runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194","runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"]},{"data":{"operation":"update","tableName":"transactions"},"message":"failed to update the database","stack":["main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:24","main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12","main.main @ /root/hack/errors/examples/example1/example1.go:52","runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194","runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"]},{"data":{"server":"db-server-01","timeoutSeconds":30},"message":"connection timeout","stack":["main.createConnection @ /root/hack/errors/examples/example1/example1.go:35","main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23","main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12","main.main @ /root/hack/errors/examples/example1/example1.go:52","runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194","runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"]},{"data":{"network":"internal","severity":"high"},"message":"network instability detected","stack":["main.open @ /root/hack/errors/examples/example1/example1.go:45","main.createConnection @ /root/hack/errors/examples/example1/example1.go:34","main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23","main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12","main.main @ /root/hack/errors/examples/example1/example1.go:52","runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194","runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"]}] Error logged using the s format specifier: failed to complete the transaction on bank_123456: failed to update the database: connection timeout: network instability detected Error logged using the +v format specifier: message: "failed to complete the transaction on bank_123456" data: userId: 67890 transactionId: tx_123456 stack: main.createTransaction @ /root/hack/errors/examples/example1/example1.go:13 main.main @ /root/hack/errors/examples/example1/example1.go:52 runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194 runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651 cause: message: "failed to update the database" data: tableName: transactions operation: update stack: main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:24 main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12 main.main @ /root/hack/errors/examples/example1/example1.go:52 runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194 runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651 cause: message: "connection timeout" data: server: db-server-01 timeoutSeconds: 30 stack: main.createConnection @ /root/hack/errors/examples/example1/example1.go:35 main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23 main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12 main.main @ /root/hack/errors/examples/example1/example1.go:52 runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194 runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651 cause: message: "network instability detected" data: severity: high network: internal stack: main.open @ /root/hack/errors/examples/example1/example1.go:45 main.createConnection @ /root/hack/errors/examples/example1/example1.go:34 main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23 main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12 main.main @ /root/hack/errors/examples/example1/example1.go:52 runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194 runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651 

About

An errors package that will help you handle them gracefully. It allows you to add contextual information to your errors, to wrap them and they even get a stack trace.

Resources

License

Stars

Watchers

Forks

Packages

No packages published