Compare commits
5 commits
Author | SHA1 | Date | |
---|---|---|---|
55ed5598e0 | |||
0570e1925b | |||
616835f641 | |||
1154fd39a2 | |||
c66ba0e169 |
2 changed files with 105 additions and 28 deletions
26
README.md
26
README.md
|
@ -6,21 +6,41 @@ import (
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.gibonuddevalla.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func errorHandler(err werr.Error) {
|
func errorHandler(err werr.Error) {
|
||||||
// For example print or log error to file
|
// For example print or log error to file
|
||||||
fmt.Printf("ERROR - %s\n", err)
|
fmt.Printf("\x1b[31;1m%s\x1b[0m\n", err)
|
||||||
|
fmt.Printf("\x1b[33;1m%s\x1b[0m\n", err.NoTrace())
|
||||||
|
|
||||||
|
j, _ := json.MarshalIndent(err, "", " ")
|
||||||
|
fmt.Printf("%s\n\n", j)
|
||||||
}
|
}
|
||||||
|
|
||||||
func foo() {
|
func main() {
|
||||||
|
// Make file paths relative to this file.
|
||||||
|
werr.Init()
|
||||||
|
|
||||||
|
// Handler to call when using Log().
|
||||||
werr.SetLogCallback(errorHandler)
|
werr.SetLogCallback(errorHandler)
|
||||||
|
|
||||||
|
// Wrap an existing error.
|
||||||
err := errors.New("foobar 1")
|
err := errors.New("foobar 1")
|
||||||
err1 := werr.Wrap(err)
|
err1 := werr.Wrap(err)
|
||||||
|
|
||||||
err2 := werr.New("foobar 2")
|
// Create a new error with extra information.
|
||||||
|
err2 := werr.New("foobar 2").WithCode("FOO-100").WithData(137)
|
||||||
|
|
||||||
|
// The os error contains more information.
|
||||||
|
_, errOS := os.ReadFile("/tmp/does_not_exist")
|
||||||
|
werr.Wrap(errOS).Log()
|
||||||
|
|
||||||
|
// Log the previously wrapped errors.
|
||||||
|
werr.Wrap(err1).Log()
|
||||||
|
werr.Wrap(err2).Log()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
89
pkg.go
89
pkg.go
|
@ -1,25 +1,75 @@
|
||||||
|
/*
|
||||||
|
wrappederror provides traceable errors:
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
// External
|
||||||
|
werr "git.gibonuddevalla.se/go/wrappederror"
|
||||||
|
|
||||||
|
// Standard
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func errorHandler(err werr.Error) {
|
||||||
|
// For example print or log error to file
|
||||||
|
fmt.Printf("\x1b[31;1m%s\x1b[0m\n", err)
|
||||||
|
fmt.Printf("\x1b[33;1m%s\x1b[0m\n", err.NoTrace())
|
||||||
|
|
||||||
|
j, _ := json.MarshalIndent(err, "", " ")
|
||||||
|
fmt.Printf("%s\n\n", j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Make file paths relative to this file.
|
||||||
|
werr.Init()
|
||||||
|
|
||||||
|
// Handler to call when using Log().
|
||||||
|
werr.SetLogCallback(errorHandler)
|
||||||
|
|
||||||
|
// Wrap an existing error.
|
||||||
|
err := errors.New("foobar 1")
|
||||||
|
err1 := werr.Wrap(err)
|
||||||
|
|
||||||
|
// Create a new error with extra information.
|
||||||
|
err2 := werr.New("foobar 2").WithCode("FOO-100").WithData(137)
|
||||||
|
|
||||||
|
// The os error contains more information.
|
||||||
|
_, errOS := os.ReadFile("/tmp/does_not_exist")
|
||||||
|
werr.Wrap(errOS).Log()
|
||||||
|
|
||||||
|
// Log the previously wrapped errors.
|
||||||
|
werr.Wrap(err1).Log()
|
||||||
|
werr.Wrap(err2).Log()
|
||||||
|
}
|
||||||
|
*/
|
||||||
package WrappedError
|
package WrappedError
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// Standard
|
// Standard
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
Wrapped error
|
Wrapped error
|
||||||
ErrStr string // wrapped error isn't necessarily json encodable
|
ErrStr string // wrapped error isn't necessarily json encodable
|
||||||
Code string `json:",omitempty"`
|
Code string
|
||||||
File string
|
File string
|
||||||
Line int
|
Line int
|
||||||
Data any `json:",omitempty"`
|
Data any
|
||||||
}
|
}
|
||||||
|
|
||||||
type CodableError interface {
|
type CodableError interface {
|
||||||
error
|
error
|
||||||
WithCode(string) CodableError
|
WithCode(string) CodableError
|
||||||
WithData(any) CodableError
|
WithData(any) CodableError
|
||||||
|
Log() CodableError
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogCallback func(Error)
|
type LogCallback func(Error)
|
||||||
|
@ -52,10 +102,10 @@ func callback(wrapped Error) {
|
||||||
func (wrapped Error) Error() string {
|
func (wrapped Error) Error() string {
|
||||||
var code string
|
var code string
|
||||||
if wrapped.Code != "" {
|
if wrapped.Code != "" {
|
||||||
code = wrapped.Code + " "
|
code = wrapped.Code + ":"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"%s[%s:%d] %s",
|
"[%s%s:%d] %s",
|
||||||
code,
|
code,
|
||||||
wrapped.File,
|
wrapped.File,
|
||||||
wrapped.Line,
|
wrapped.Line,
|
||||||
|
@ -78,7 +128,6 @@ func create(err error, data interface{}) *Error {
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(wrapped)
|
|
||||||
return &wrapped
|
return &wrapped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,10 +136,6 @@ func Wrap(err error) *Error {
|
||||||
return create(err, nil)
|
return create(err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapData(err error, data interface{}) *Error {
|
|
||||||
return create(err, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new wrapped error with file and line.
|
// New creates a new wrapped error with file and line.
|
||||||
func New(msg string, params ...any) *Error {
|
func New(msg string, params ...any) *Error {
|
||||||
err := fmt.Errorf(msg, params...)
|
err := fmt.Errorf(msg, params...)
|
||||||
|
@ -98,19 +143,31 @@ func New(msg string, params ...any) *Error {
|
||||||
return wrapped
|
return wrapped
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewData creates a new WrappedError with associated data.
|
// WithCode associates a string code with the error.
|
||||||
func NewData(msg string, data interface{}, params ...any) *Error {
|
|
||||||
err := fmt.Errorf(msg, params...)
|
|
||||||
wrapped := create(err, data)
|
|
||||||
return wrapped
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Error) WithCode(code string) CodableError {
|
func (e *Error) WithCode(code string) CodableError {
|
||||||
e.Code = code
|
e.Code = code
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithData associates any data with the error to make troubleshooting easier.
|
||||||
func (e *Error) WithData(data any) CodableError {
|
func (e *Error) WithData(data any) CodableError {
|
||||||
e.Data = data
|
e.Data = data
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log calls the log callback.
|
||||||
|
func (e *Error) Log() CodableError {
|
||||||
|
callback(*e)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoTrace returns the Error() string without the trace.
|
||||||
|
func (e *Error) NoTrace() string {
|
||||||
|
rxp := regexp.MustCompile(`^(\[[^\]]+\.go:\d+\]\s*)*`)
|
||||||
|
return string(
|
||||||
|
rxp.ReplaceAll(
|
||||||
|
[]byte(e.Error()),
|
||||||
|
[]byte(""),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue