11# errors [ ![ GoDoc] ( https://godoc.org/github.com/zignd/errors?status.svg )] ( https://godoc.org/github.com/zignd/errors ) [ ![ Report card] ( https://goreportcard.com/badge/github.com/zignd/errors )] ( https://goreportcard.com/report/github.com/zignd/errors )
22
3- 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. Inspired by the [ github.com/pkg/errors] ( https://www.github.com/pkg/errors ) package and Node.js' [ verror] ( https://github.com/joyent/node-verror ) module.
3+ 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] ( https://www.github.com/pkg/errors ) package and Node.js' [ verror] ( https://github.com/joyent/node-verror ) module.
44
55# Features
66
7- * Add contextual information to error values preventing long and hard to read error messages
7+ * Add additional data to error values preventing long and hard to read error messages
88* Wrap existing error values into new ones
9- * Stack traces
9+ * Stack traces for each error value
1010* MultiError, wrap multiple errors values into a single one; great for concurrent workflows that may generate multiple errors
1111* Pretty print of the whole error value and support JSON marshalling to ease the serialization (check the [ "Quick demo"] ( https://github.com/zignd/errors#quick-demo ) section)
1212
13+ # Installation
14+
15+ ``` bash
16+ go get -u github.com/zignd/errors
17+ ```
18+
1319# Documentation
1420
1521For a better understanding of the features provided by the package check the documentation at: [ godoc.org/github.com/zignd/errors] ( https://godoc.org/github.com/zignd/errors )
1622
1723# Quick demo
1824
19- ** Consider the following usages of the package in the functions defined below **
25+ There's an example at ` examples/example1/example1.go ` that shows how to use the package. Here's the code for the example:
2026
2127``` go
2228package main
@@ -28,126 +34,184 @@ import (
2834 " github.com/zignd/errors"
2935)
3036
31- func foo ( ) error {
32- model := " iop-40392 "
33-
34- if err := launch (model); err != nil {
35- return errors. Wrapc (err, map [ string ] interface {}{
36- " model " : model ,
37- }, " failed to launch rocket " )
37+ func createTransaction ( id string ) error {
38+ bank := " bank_123456 "
39+ if err := updateDatabase (); err != nil {
40+ return errors. Wrapdf ( err, errors. Data {
41+ " transactionId " : id,
42+ " userId " : " 67890 " ,
43+ }, " failed to complete the transaction on %s " , bank )
3844 }
3945
4046 return nil
4147}
4248
43- func launch (model string ) error {
44- return errors.Errorc (map [string ]interface {}{
45- " rocket" : map [string ]interface {}{
46- " ID" : " 123" ,
47- " Fuel" : 10 ,
48- " AutoPilot" : true ,
49- },
50- }, " something catastrofic just happened to rocket #123" )
51- }
52- ```
49+ func updateDatabase () error {
50+ if err := createConnection (); err != nil {
51+ return errors.Wrapd (err, errors.Data {
52+ " tableName" : " transactions" ,
53+ " operation" : " update" ,
54+ }, " failed to update the database" )
55+ }
5356
54- ** JSON marshalling an error value**
57+ return nil
58+ }
5559
56- ``` go
57- func main () {
58- if err := foo (); err != nil {
59- // Type assertions using the exposed Error type
60- if err , ok := err.(*errors.Error ); ok {
61- b , _ := json.MarshalIndent (err, " " , " \t " )
62- fmt.Printf (" %s " , b)
63- }
60+ func createConnection () error {
61+ if err := open (); err != nil {
62+ return errors.Wrapd (err, errors.Data {
63+ " server" : " db-server-01" ,
64+ " timeoutSeconds" : 30 ,
65+ }, " connection timeout" )
6466 }
67+
68+ return nil
6569}
66- ```
6770
68- ** Output**
71+ func open () error {
72+ return errors.Errord (errors.Data {
73+ " network" : " internal" ,
74+ " severity" : " high" ,
75+ }, " network instability detected" )
76+ }
6977
70- ```
71- {
72- "Message": "failed to launch rocket",
73- "Context": {
74- "model": "iop-40392"
75- },
76- "Stack": "main.foo\n\t/home/zignd/go/src/github.com/zignd/test/main.go:38\nmain.main\n\t/home/zignd/go/src/github.com/zignd/test/main.go:11\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:194\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:2198",
77- "Cause": {
78- "Message": "something catastrofic just happened to rocket #123",
79- "Context": {
80- "rocket": {
81- "AutoPilot": true,
82- "Fuel": 10,
83- "ID": "123"
84- }
85- },
86- "Stack": "main.launch\n\t/home/zignd/go/src/github.com/zignd/test/main.go:51\nmain.foo\n\t/home/zignd/go/src/github.com/zignd/test/main.go:35\nmain.main\n\t/home/zignd/go/src/github.com/zignd/test/main.go:11\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:194\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:2198",
87- "Cause": null
88- }
89- }
90- ```
78+ func main () {
79+ if err := createTransaction (" tx_123456" ); err != nil {
80+ b , _ := json.MarshalIndent (err, " " , " " )
81+ fmt.Println (" Error logged as a JSON structure using the JSON.MarshalIndent:" )
82+ fmt.Printf (" %s \n " , b)
9183
92- ** ` fmt.Formatter ` implementation supporting the ` +v ` format for recursive pretty print of the whole error value**
84+ b, _ = json.Marshal (err)
85+ fmt.Println (" \n Error logged as a JSON structure using the JSON.Marshal:" )
86+ fmt.Printf (" %s \n " , b)
9387
94- ``` go
95- func main () {
96- if err := foo (); err != nil {
97- if err , ok := err.(*errors.Error ); ok {
98- fmt.Printf (" %+v " , err)
99- }
88+ fmt.Println (" \n Error logged using the s format specifier:" )
89+ fmt.Printf (" %s \n " , err)
90+
91+ fmt.Println (" \n Error logged using the +v format specifier:" )
92+ fmt.Printf (" %+v \n " , err)
10093 }
10194}
10295```
10396
104- ** Output **
97+ Here's the execution of the example:
10598
10699```
107- Message:
108- "failed to launch rocket"
109- Context:
110- model: iop-40392
111- Stack:
112- main.foo
113- /home/zignd/go/src/github.com/zignd/test/main.go:38
114- main.main
115- /home/zignd/go/src/github.com/zignd/test/main.go:11
116- runtime.main
117- /usr/local/go/src/runtime/proc.go:194
118- runtime.goexit
119- /usr/local/go/src/runtime/asm_amd64.s:2198
120- Cause:
121- Message:
122- "something catastrofic just happened to rocket #123"
123- Context:
124- rocket: map[ID:123 Fuel:10 AutoPilot:true]
125- Stack:
126- main.launch
127- /home/zignd/go/src/github.com/zignd/test/main.go:51
128- main.foo
129- /home/zignd/go/src/github.com/zignd/test/main.go:35
130- main.main
131- /home/zignd/go/src/github.com/zignd/test/main.go:11
132- runtime.main
133- /usr/local/go/src/runtime/proc.go:194
134- runtime.goexit
135- /usr/local/go/src/runtime/asm_amd64.s:2198
136- ```
137-
138- ** The usual ` %s ` format support**
139-
140- ``` go
141- func main () {
142- if err := foo (); err != nil {
143- if err , ok := err.(*errors.Error ); ok {
144- fmt.Printf (" %s " , err)
145- }
146- }
100+ $ go run examples/example1/example1.go
101+ Error logged as a JSON structure using the JSON.MarshalIndent:
102+ {
103+ "message": "failed to complete the transaction on bank_123456",
104+ "data": {
105+ "transactionId": "tx_123456",
106+ "userId": "67890"
107+ },
108+ "stack": [
109+ "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:13",
110+ "main.main @ /root/hack/errors/examples/example1/example1.go:52",
111+ "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194",
112+ "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"
113+ ],
114+ "cause": {
115+ "message": "failed to update the database",
116+ "data": {
117+ "operation": "update",
118+ "tableName": "transactions"
119+ },
120+ "stack": [
121+ "main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:24",
122+ "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12",
123+ "main.main @ /root/hack/errors/examples/example1/example1.go:52",
124+ "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194",
125+ "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"
126+ ],
127+ "cause": {
128+ "message": "connection timeout",
129+ "data": {
130+ "server": "db-server-01",
131+ "timeoutSeconds": 30
132+ },
133+ "stack": [
134+ "main.createConnection @ /root/hack/errors/examples/example1/example1.go:35",
135+ "main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23",
136+ "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12",
137+ "main.main @ /root/hack/errors/examples/example1/example1.go:52",
138+ "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194",
139+ "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"
140+ ],
141+ "cause": {
142+ "message": "network instability detected",
143+ "data": {
144+ "network": "internal",
145+ "severity": "high"
146+ },
147+ "stack": [
148+ "main.open @ /root/hack/errors/examples/example1/example1.go:45",
149+ "main.createConnection @ /root/hack/errors/examples/example1/example1.go:34",
150+ "main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23",
151+ "main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12",
152+ "main.main @ /root/hack/errors/examples/example1/example1.go:52",
153+ "runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194",
154+ "runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651"
155+ ]
156+ }
157+ }
158+ }
147159}
148- ```
149- ** Output**
150160
151- ```
152- failed to launch rocket: something catastrofic just happened to rocket #123
153- ```
161+ Error logged as a JSON structure using the JSON.Marshal:
162+ {"message":"failed to complete the transaction on bank_123456","data":{"transactionId":"tx_123456","userId":"67890"},"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":{"operation":"update","tableName":"transactions"},"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":{"network":"internal","severity":"high"},"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"]}}}}
163+
164+ Error logged using the s format specifier:
165+ failed to complete the transaction on bank_123456: failed to update the database: connection timeout: network instability detected
166+
167+ Error logged using the +v format specifier:
168+ message:
169+ "failed to complete the transaction on bank_123456"
170+ data:
171+ transactionId: tx_123456
172+ userId: 67890
173+ stack:
174+ main.createTransaction @ /root/hack/errors/examples/example1/example1.go:13
175+ main.main @ /root/hack/errors/examples/example1/example1.go:52
176+ runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194
177+ runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651
178+ cause:
179+ message:
180+ "failed to update the database"
181+ data:
182+ tableName: transactions
183+ operation: update
184+ stack:
185+ main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:24
186+ main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12
187+ main.main @ /root/hack/errors/examples/example1/example1.go:52
188+ runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194
189+ runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651
190+ cause:
191+ message:
192+ "connection timeout"
193+ data:
194+ server: db-server-01
195+ timeoutSeconds: 30
196+ stack:
197+ main.createConnection @ /root/hack/errors/examples/example1/example1.go:35
198+ main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23
199+ main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12
200+ main.main @ /root/hack/errors/examples/example1/example1.go:52
201+ runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194
202+ runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651
203+ cause:
204+ message:
205+ "network instability detected"
206+ data:
207+ network: internal
208+ severity: high
209+ stack:
210+ main.open @ /root/hack/errors/examples/example1/example1.go:45
211+ main.createConnection @ /root/hack/errors/examples/example1/example1.go:34
212+ main.updateDatabase @ /root/hack/errors/examples/example1/example1.go:23
213+ main.createTransaction @ /root/hack/errors/examples/example1/example1.go:12
214+ main.main @ /root/hack/errors/examples/example1/example1.go:52
215+ runtime/internal/atomic.(*Uint32).Load @ /root/go/version/go1.21.0/src/runtime/internal/atomic/types.go:194
216+ runtime.goexit @ /root/go/version/go1.21.0/src/runtime/asm_amd64.s:1651
217+ ```
0 commit comments