Skip to content

Commit fc72af5

Browse files
authored
v0.9.0
[minor] `Stacktrace(err error) string` - returns a prettified stacktrace of the error [minor] `StacktraceCustomFormat(msgformat string, traceFormat string, err error) string` - supports using custom format [minor] `RuntimeFrames(err error)` - returns *runtime.Frames* of the error, based on combined (if nested) program counters of the error [minor] `ProgramCounters(err error) []uintptr` - returns combined (if nested) program counters of the error [minor] fmt.Formatter interface implementation
1 parent 6ac87c7 commit fc72af5

6 files changed

+768
-1376
lines changed

README.md

+71-41
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
[![](https://godoc.org/github.com/nathany/looper?status.svg)](https://pkg.go.dev/github.com/bnkamalesh/errors?tab=doc)
88
[![](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go#error-handling)
99

10-
# Errors
10+
# Errors v0.9.0
1111

1212
Errors package is a drop-in replacement of the built-in Go errors package with no external dependencies. It lets you create errors of 11 different types which should handle most of the use cases. Some of them are a bit too specific for web applications, but useful nonetheless. Following are the primary features of this package:
1313

1414
1. Multiple (11) error types
1515
2. User friendly message
16-
3. File & line number prefixed to errors
17-
4. HTTP status code and user friendly message (wrapped messages are concatenated) for all error types
18-
5. Helper functions to generate each error type
19-
6. Helper function to get error Type, error type as int, check if error type is wrapped anywhere in chain
16+
3. Stacktrace - formatted, unfromatted, custom format (refer tests in errors_test.go)
17+
4. Retrieve the Program Counters, for compatibility external libraries which generate their own stacktrace
18+
5. Retrieve *runtime.Frames using `errors.RuntimeFrames(err error)`, for compatibility external libraries which generate their own stacktrace
19+
6. HTTP status code and user friendly message (wrapped messages are concatenated) for all error types
20+
7. Helper functions to generate each error type
21+
8. Helper function to get error Type, error type as int, check if error type is wrapped anywhere in chain
22+
9. fmt.Formatter support
2023

2124
In case of nested errors, the messages & errors are also looped through the full chain of errors.
2225

@@ -50,44 +53,72 @@ There are helper functions for all the error types, when in need of setting a fr
5053

5154
```golang
5255
package main
53-
import(
54-
"fmt"
55-
"github.com/bnkamalesh/errors"
56+
57+
import (
58+
"fmt"
59+
60+
"github.com/bnkamalesh/errors"
5661
)
5762

5863
func Bar() error {
59-
return fmt.Errorf("hello %s", "world!")
64+
return fmt.Errorf("hello %s", "world!")
6065
}
6166

6267
func Foo() error {
63-
err := Bar()
64-
if err != nil {
65-
return errors.InternalErr(err, "bar is not happy")
66-
}
67-
return nil
68+
err := Bar()
69+
if err != nil {
70+
return errors.InternalErr(err, "bar is not happy")
71+
}
72+
return nil
6873
}
6974

7075
func main() {
71-
err := Foo()
72-
fmt.Println(err)
73-
_,msg,_ := errors.HTTPStatusCodeMessage(err)
74-
fmt.Println(msg)
76+
err := Foo()
77+
78+
fmt.Println("err:", err)
79+
fmt.Println("\nerr.Error():", err.Error())
80+
81+
fmt.Printf("\nformatted +v: %+v\n", err)
82+
fmt.Printf("\nformatted v: %v\n", err)
83+
fmt.Printf("\nformatted +s: %+s\n", err)
84+
fmt.Printf("\nformatted s: %s\n", err)
85+
86+
_, msg, _ := errors.HTTPStatusCodeMessage(err)
87+
fmt.Println("\nmsg:", msg)
7588
}
7689
```
7790

91+
Output
92+
```
93+
err: bar is not happy
94+
95+
err.Error(): /path/to/file.go:16: bar is not happy
96+
hello world!
97+
98+
formatted +v: /path/to/file.go:16: bar is not happy
99+
hello world!
100+
101+
formatted v: bar is not happy
102+
103+
formatted +s: bar is not happy: hello world!
104+
105+
formatted s: bar is not happy
106+
107+
msg: bar is not happy
108+
```
109+
110+
[Playground link](https://go.dev/play/p/-WzDH46f_U5)
111+
78112
### File & line number prefixed to errors
79113

80-
A common annoyance with Go errors which most people are aware of is, figuring out the origin of the error, especially when there are nested function calls. Ever since error annotation was introduced in Go, a lot of people have tried using it to trace out an errors origin by giving function names, contextual message etc in it. e.g. `fmt.Errorf("database query returned error %w", err)`. This errors package, whenever you call the Go error interface's `Error() string` function, it'll print the error prefixed by the filepath and line number. It'd look like `../Users/JohnDoe/apps/main.go:50 hello world` where 'hello world' is the error message.
114+
A common annoyance with Go errors which most people are aware of is, figuring out the origin of the error, especially when there are nested function calls. Ever since error annotation was introduced in Go, a lot of people have tried using it to trace out an errors origin by giving function names, contextual message etc in it. e.g. `fmt.Errorf("database query returned error %w", err)`. However this errors package, whenever you call the Go error interface's `Error() string` function, prints the error prefixed by the filepath and line number. It'd look like `../Users/JohnDoe/apps/main.go:50 hello world` where 'hello world' is the error message.
81115

82116
### HTTP status code & message
83117

84-
The function `errors.HTTPStatusCodeMessage(error) (int, string, bool)` returns the HTTP status code, message, and a boolean value. The boolean is true, if the error is of type *Error from this package.
85-
If error is nested with multiple errors, it loops through all the levels and returns a single concatenated message. This is illustrated in the 'How to use?' section
118+
The function `errors.HTTPStatusCodeMessage(error) (int, string, bool)` returns the HTTP status code, message, and a boolean value. The boolean is true, if the error is of type *Error from this package. If error is nested, it unwraps and returns a single concatenated message. Sample described in the 'How to use?' section
86119

87120
## How to use?
88121

89-
Before that, over the years I have tried error with stack trace, annotation, custom error package with error codes etc. Finally, I think this package gives the best of all worlds, for most generic usecases.
90-
91122
A sample was already shown in the user friendly message section, following one would show a few more scenarios.
92123

93124
```golang
@@ -179,34 +210,33 @@ And the `fmt.Println(err.Error())` generated output on stdout would be:
179210
/Users/username/go/src/errorscheck/main.go:28 /Users/username/go/src/errorscheck/main.go:20 sinking bar
180211
```
181212

182-
## Benchmark
213+
## Benchmark [2021-12-13]
183214

184-
Benchmark run on:
185-
<p><img width="320" alt="Screenshot 2020-07-18 at 6 25 22 PM" src="https://user-images.githubusercontent.com/1092882/87852981-241b5c80-c924-11ea-9d22-296acdead7cc.png"></p>
186-
187-
Results
188215
```bash
189216
$ go version
190-
go version go1.14.4 darwin/amd64
191-
$ go test -bench=.
192-
goos: darwin
217+
go version go1.17.4 linux/amd64
218+
219+
$ go test -benchmem -bench .
220+
goos: linux
193221
goarch: amd64
194222
pkg: github.com/bnkamalesh/errors
195-
Benchmark_Internal-8 1874256 639 ns/op 368 B/op 5 allocs/op
196-
Benchmark_InternalErr-8 1612707 755 ns/op 368 B/op 5 allocs/op
197-
Benchmark_InternalGetError-8 1700966 706 ns/op 464 B/op 6 allocs/op
198-
Benchmark_InternalGetErrorWithNestedError-8 1458368 823 ns/op 464 B/op 6 allocs/op
199-
Benchmark_InternalGetMessage-8 1866562 643 ns/op 368 B/op 5 allocs/op
200-
Benchmark_InternalGetMessageWithNestedError-8 1656597 770 ns/op 400 B/op 6 allocs/op
201-
Benchmark_HTTPStatusCodeMessage-8 26003678 46.1 ns/op 16 B/op 1 allocs/op
202-
BenchmarkHasType-8 84689433 14.2 ns/op 0 B/op 0 allocs/op
223+
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
224+
Benchmark_Internal-8 772088 1412 ns/op 1272 B/op 5 allocs/op
225+
Benchmark_Internalf-8 695674 1692 ns/op 1296 B/op 6 allocs/op
226+
Benchmark_InternalErr-8 822500 1404 ns/op 1272 B/op 5 allocs/op
227+
Benchmark_InternalGetError-8 881791 1319 ns/op 1368 B/op 6 allocs/op
228+
Benchmark_InternalGetErrorWithNestedError-8 712803 1488 ns/op 1384 B/op 6 allocs/op
229+
Benchmark_InternalGetMessage-8 927864 1237 ns/op 1272 B/op 5 allocs/op
230+
Benchmark_InternalGetMessageWithNestedError-8 761164 1675 ns/op 1296 B/op 6 allocs/op
231+
Benchmark_HTTPStatusCodeMessage-8 29116684 41.62 ns/op 16 B/op 1 allocs/op
232+
BenchmarkHasType-8 100000000 11.50 ns/op 0 B/op 0 allocs/op
203233
PASS
204-
ok github.com/bnkamalesh/errors 14.478s
234+
ok github.com/bnkamalesh/errors 10.604s
205235
```
206236

207237
## Contributing
208238

209-
More error types, customization etc; PRs & issues are welcome!
239+
More error types, customization, features etc; PRs & issues are welcome!
210240

211241
## The gopher
212242

0 commit comments

Comments
 (0)