a very convenient error handler.
Table of Contents generated with DocToc
- Supporting generate error stacktrace, locating more efficiently than runtime stacktrace.
- Supporting report error to HTTP URL.
- Supporting generate json-marshalled error detail for outer pipeline.
- Supporting differrent mode uses different error handlers.
go get github.com/fwhezfwhez/errorx
package main
import (
"fmt"
"github.com/fwhezfwhez/errorx"
)
func main() {
e := fmt.Errorf("nil return")
fmt.Println(errorx.Wrap(e).Error())
}
Output
2019-08-30 17:51:42 | G:/go_workspace/GOPATH/src/test_X/tmp/main.go: 10 | nil return
In most cases, client requires server to provide specific errmsg and errcode. Service error is exact what you expects.
func Control(c *gin.Context) {
e := Service()
if se, ok := errorx.IsServiceErr(e, balanceLackErr); ok {
c.JSON(200, gin.H{
"errcode": se.Errcode,
"errmsg": se.Errmsg,
})
return
}
if e != nil {
fmt.Println(Wrap(e).Error())
c.JSON(200, gin.H{
"errmsg": "unexpected error",
"errcode": -1,
"debug_message": errorx.Wrap(e).Error()
})
return
}
c.JSON(200, gin.H{"errcode":0})
}
func ManyService() error {
if e:= ServiceToCash();e!=nil {
return errorx.Wrap(e)
}
return nil
}
func ServiceToCash() error {
if e:=UtilToCash();e!=nil {
return errorx.Wrap(e)
}
return nil
}
var balanceLackErr = NewServiceError("balance not enough", 10001)
func UtilToCash() error {
return balanceLackErr
}
HTTP Response:
{"errcode": 10001, "errmsg":"balance not enough"}
Using defaultHandler print in console
error will be log as json on console.
package main
import (
"github.com/fwhezfwhez/errorx"
"fmt"
)
var rp *errorx.Reporter
func init() {
rp = errorx.NewReporter("dev")
rp.AddModeHandler("dev", rp.DefaultHandler)
}
func main() {
e := fmt.Errorf("nil return")
if e != nil {
rp.SaveError(errorx.Wrap(e), map[string]interface{}{
"username": "errorx",
"age": 1,
})
return
}
}
output:
{
"context": {
"api": "/xxx/yyy/"
},
"error_uuid": "11d35e60-5abc-462d-9df1-bb5b01d79807",
"message": "2019-08-31 08:58:29 | G:/go_workspace/GOPATH/src/errorX/error-report.go: 123 | err 'nil return' \n goroutine 51 [running]:\nruntime/debug.Stack(0xc0002022e0, 0xb3604d, 0xa)\n\tE:/go1.12/src/runtime/debug/stack.go:24 +0xa4\nerrorX.Reporter.SaveError(0xc0001fc1e0, 0xb30f5d, 0x3, 0xc0001fc180, 0x0, 0x0, 0x0, 0xc0001fc1b0, 0x0, 0x0, ...)\n\tG:/go_workspace/GOPATH/src/errorX/error-report.go:123 +0x30b\ncreated by errorX.TestReporter\n\tG:/go_workspace/GOPATH/src/errorX/error-report_test.go:45 +0x702\n\n2019-08-31 08:58:29 | G:/go_workspace/GOPATH/src/errorX/error-report.go: 144 | err 'nil return' \n goroutine 51 [running]:\nruntime/debug.Stack(0xc0002022e0, 0xb3604d, 0xa)\n\tE:/go1.12/src/runtime/debug/stack.go:24 +0xa4\nerrorX.Reporter.SaveError(0xc0001fc1e0, 0xb30f5d, 0x3, 0xc0001fc180, 0x0, 0x0, 0x0, 0xc0001fc1b0, 0x0, 0x0, ...)\n\tG:/go_workspace/GOPATH/src/errorX/error-report.go:123 +0x30b\ncreated by errorX.TestReporter\n\tG:/go_workspace/GOPATH/src/errorX/error-report_test.go:45 +0x702\n\n2019-08-31 08:58:29 | G:/go_workspace/GOPATH/src/errorX/error-report.go: 49 | err 'nil return' \n goroutine 51 [running]:\nruntime/debug.Stack(0xc0002022e0, 0xb3604d, 0xa)\n\tE:/go1.12/src/runtime/debug/stack.go:24 +0xa4\nerrorX.Reporter.SaveError(0xc0001fc1e0, 0xb30f5d, 0x3, 0xc0001fc180, 0x0, 0x0, 0x0, 0xc0001fc1b0, 0x0, 0x0, ...)\n\tG:/go_workspace/GOPATH/src/errorX/error-report.go:123 +0x30b\ncreated by errorX.TestReporter\n\tG:/go_workspace/GOPATH/src/errorX/error-report_test.go:45 +0x702\n\n"
}
Using url report
error will POST into specific url.
server
package main
import (
"fmt"
"github.com/fwhezfwhez/errorx"
"github.com/gin-gonic/gin"
"io/ioutil"
)
func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
buf, e := ioutil.ReadAll(c.Request.Body)
if e != nil {
fmt.Println(errorx.Wrap(e).Error())
return
}
fmt.Println("Recv:", string(buf))
})
r.Run(":9191")
}
package main
import (
"github.com/fwhezfwhez/errorx"
"fmt"
)
var rp *errorx.Reporter
func init() {
rp = errorx.NewReporter("pro")
rp.AddURL("pro", "http://localhost:9191")
rp.AddURL("dev", "http://localhost:9192")
rp.AddModeHandler("pro", rp.ReportURLHandler)
rp.AddModeHandler("dev", rp.Mode("dev").DefaultHandler)
}
func main() {
e := fmt.Errorf("nil return")
if e != nil {
// rp's mode is pro, it will send error to localhost:9191
_ = rp.SaveError(errorx.Wrap(e), map[string]interface{}{
"username": "errorx",
"age": 1,
})
// clone a rp and reset its mode to dev, it will print error in console by DefaultHandler
_ = rp.Mode("dev").SaveError(errorx.Wrap(e), map[string]interface{}{
"username": "errorx",
"age": 1,
})
return
}
}
Output in server panel:
Recv:
{
"context": {
"api": "/xxx/yyy/"
},
"error_uuid": "11d35e60-5abc-462d-9df1-bb5b01d79807",
"message": "2019-08-31 08:58:29 | G:/go_workspace/GOPATH/src/errorX/error-report.go: 123 | err 'nil return' \n goroutine 51 [running]:\nruntime/debug.Stack(0xc0002022e0, 0xb3604d, 0xa)\n\tE:/go1.12/src/runtime/debug/stack.go:24 +0xa4\nerrorX.Reporter.SaveError(0xc0001fc1e0, 0xb30f5d, 0x3, 0xc0001fc180, 0x0, 0x0, 0x0, 0xc0001fc1b0, 0x0, 0x0, ...)\n\tG:/go_workspace/GOPATH/src/errorX/error-report.go:123 +0x30b\ncreated by errorX.TestReporter\n\tG:/go_workspace/GOPATH/src/errorX/error-report_test.go:45 +0x702\n\n2019-08-31 08:58:29 | G:/go_workspace/GOPATH/src/errorX/error-report.go: 144 | err 'nil return' \n goroutine 51 [running]:\nruntime/debug.Stack(0xc0002022e0, 0xb3604d, 0xa)\n\tE:/go1.12/src/runtime/debug/stack.go:24 +0xa4\nerrorX.Reporter.SaveError(0xc0001fc1e0, 0xb30f5d, 0x3, 0xc0001fc180, 0x0, 0x0, 0x0, 0xc0001fc1b0, 0x0, 0x0, ...)\n\tG:/go_workspace/GOPATH/src/errorX/error-report.go:123 +0x30b\ncreated by errorX.TestReporter\n\tG:/go_workspace/GOPATH/src/errorX/error-report_test.go:45 +0x702\n\n2019-08-31 08:58:29 | G:/go_workspace/GOPATH/src/errorX/error-report.go: 49 | err 'nil return' \n goroutine 51 [running]:\nruntime/debug.Stack(0xc0002022e0, 0xb3604d, 0xa)\n\tE:/go1.12/src/runtime/debug/stack.go:24 +0xa4\nerrorX.Reporter.SaveError(0xc0001fc1e0, 0xb30f5d, 0x3, 0xc0001fc180, 0x0, 0x0, 0x0, 0xc0001fc1b0, 0x0, 0x0, ...)\n\tG:/go_workspace/GOPATH/src/errorX/error-report.go:123 +0x30b\ncreated by errorX.TestReporter\n\tG:/go_workspace/GOPATH/src/errorX/error-report_test.go:45 +0x702\n\n"
}
JSON and JSONIndent will generate a json buf from error and context.
package main
import (
"github.com/fwhezfwhez/errorx"
"fmt"
)
func main() {
eUuid, buf, e := errorx.JSON(errorx.NewFromString("nil return"), map[string]interface{}{
"api": "/xx/xxx/xx",
})
fmt.Println(eUuid)
fmt.Println(string(buf))
fmt.Println(e)
}
Output:
befe4742-6905-4817-96aa-19fdb63bd83f
{"context":{"api":"/xx/xxx/xx"},"error_uuid":"befe4742-6905-4817-96aa-19fdb63bd83f","message":"2019-08-31 09:18:41 | G:/go_workspace/GOPATH/src/errorX/error-report_test.go: 56 | nil return\n2019-08-31 09:18:41 | G:/go_workspace/GOPATH/src/errorX/error-report.go: 171 | nil return\n"}