errorx

package module
v0.0.0-...-cc36139 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2019 License: MIT Imports: 13 Imported by: 0

README

errorx

Godoc Build Status Gitter

a very convenient error handler.

Table of Contents generated with DocToc

1. What is different from the officials

  • 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.

2. Start

go get github.com/fwhezfwhez/errorx

3. Module

3.1 Error stacktrace
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
3.2 Error Report

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"
}
3.3 JSON

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"}

Documentation

Index

Constants

View Source
const (
	LcauseBy = 1 << iota
	LdateTime
	Llongfile
)

Variables

View Source
var DefaultHandler = func(e error, context map[string]interface{}) {
	var tmp = make(map[string]interface{}, 0)
	tmp["error_uuid"] = context["error_uuid"]
	delete(context, "error_uuid")
	tmp["message"] = Wrap(e).Error()
	tmp["context"] = context

	var buf = []byte("")
	var er error
	buf, er = json.MarshalIndent(tmp, "  ", "  ")
	if er != nil {
		buf = []byte(Wrap(er).Error())
	}
	fmt.Println(string(buf))
}

It will fmt error log into console.

Functions

func GenerateKeyword

func GenerateKeyword(e error) string

generate key word to an error type

func GroupErrors

func GroupErrors(errors ...error) error

group series of error to a single error

func JSON

func JSON(e error, context map[string]interface{}) (string, []byte, error)

func JSONIndent

func JSONIndent(e error, context map[string]interface{}, prefix, indent string) (string, []byte, error)

func New

func New(e error) error

New a error

func NewFromStackTrace

func NewFromStackTrace(stackTrace []string, msg string) error

new an error with existed stacktrace and generate the new error with new msg

func NewFromString

func NewFromString(msg string) error

new an error from string

func NewFromStringWithAttach

func NewFromStringWithAttach(msg string, attach interface{}) error

new an error from string with header

func NewFromStringWithAttachf

func NewFromStringWithAttachf(format string, msg string, attach interface{}) error

new an error from well format string with header

func NewFromStringWithHeader

func NewFromStringWithHeader(msg string, header map[string]interface{}) error

new an error from string with header

func NewFromStringWithHeaderf

func NewFromStringWithHeaderf(format string, msg string, header map[string]interface{}) error

new a error from a well format string with header

func NewFromStringWithParam

func NewFromStringWithParam(msg string, params ...interface{}) error

func NewFromStringf

func NewFromStringf(format string, msg ...interface{}) error

new a error from a well format string

func NewWithAttach

func NewWithAttach(e error, msg interface{}) error

func NewWithHeader

func NewWithHeader(e error, header map[string]interface{}) error

New an error with header info

func NewWithParam

func NewWithParam(e error, params ...interface{}) error

new a error from a error with numeric params

func PrintStackFormat

func PrintStackFormat(flag int, file string, line int, cause string) string

func ReGen

func ReGen(old error, new error) error

ReGenerate a new error and save the old

func Split

func Split(s string, sub string) []string

Split better strings.Split,对 a,,,,,,,b,,c 以","进行切割成[a,b,c]

func Split2

func Split2(s string, sub string, tmp *string, rs *[]string)

Split2 附属于Split,可独立使用

func ToString

func ToString(arg interface{}) string

func Wrap

func Wrap(e error) error

wrap an official error to Error type function do the same as New() New() or Wrap() depends on its semantics. mixing them is also correct.

Types

type Error

type Error struct {
	// basic
	E           error
	StackTraces []string

	// do not use context, it's tracking bug on development
	Context map[string]interface{}
	Header  map[string][]string

	// upper
	ReGenerated bool
	Errors      []error
	Flag        int
	Keyword     string
}

an Error instance wraps an official error and storage its stackTrace. E and StackTraces work for the basic server When tries to wrap the origin error to another, logic does like:

if er := f(); er!=nil{
    log.Println(er.Error())
	return errors.New("inner service error")
}

'ReGenerated' should be set true and different errors should be saved in 'Errors',and the 'stackTrace' should include all stackTraces above.But in this case,'Error.E' only point to the origin one It's ok to storage both official error and 'Error'

func Empty

func Empty() Error

func MustWrap

func MustWrap(e error) Error

return an Error regardless of e's type

func (Error) BasicError

func (e Error) BasicError() string

func (Error) Error

func (e Error) Error() string

func (Error) GenerateKeyword

func (e Error) GenerateKeyword() string

generate an error key word. key word is used to help save errors in database It's suggested to set unique(date, keyword), when error with same keyword in a day,database only saves field 'times' rather than another error record

func (Error) GetHeader

func (e Error) GetHeader(key string) string

GetHeader is safe wheter header is nil

func (Error) PrintStackTrace

func (e Error) PrintStackTrace() string

print error stack trace e.Flag only controls 'Error' type or official error which has been wrapped to 'Error'. e.Flag only controls stack trace inner an Error type ,rather than some stack trace which has been init by api NewFromStackTrace([]string,string)

func (*Error) SetHeader

func (e *Error) SetHeader(key string, value string)

set header for an error obj SetHeader is safe whether e.Header is nil or not

func (Error) StackTrace

func (e Error) StackTrace() string

return its stacktrace

func (Error) StackTraceValue

func (e Error) StackTraceValue() string

func (Error) String

func (e Error) String() string

type Reporter

type Reporter struct {
	Url map[string]string

	HandleMode map[string]func(e error, context map[string]interface{})
	// contains filtered or unexported fields
}

func NewReporter

func NewReporter(mode string) *Reporter

func (*Reporter) AddModeHandler

func (r *Reporter) AddModeHandler(mode string, f func(e error, context map[string]interface{})) *Reporter

func (*Reporter) AddURL

func (r *Reporter) AddURL(mode string, url string) *Reporter

func (Reporter) DefaultHandler

func (r Reporter) DefaultHandler(e error, context map[string]interface{})

func (Reporter) JSON

func (r Reporter) JSON(e error, context map[string]interface{}) (string, []byte, error)

rp.Mode unrelated returns errorUUID, json-buf, error

func (Reporter) JSONIndent

func (r Reporter) JSONIndent(e error, context map[string]interface{}, prefix, indent string) (string, []byte, error)

func (*Reporter) Mode

func (r *Reporter) Mode(mode string) *Reporter

Mode will clone a copy of reporter to avoid different goroutine using a unsafe clone

func (Reporter) ReportURLHandler

func (r Reporter) ReportURLHandler(e error, context map[string]interface{})

rp.Mode related, should call like rp.Mode("dev").ReportURLHandler It will post error with context to an url storaged in reporter.Url

func (Reporter) SaveError

func (r Reporter) SaveError(e error, context map[string]interface{}) string

rp.Mode related, should call as r.Mode("dev").SaveError()

func (*Reporter) SetContextName

func (r *Reporter) SetContextName(name string)

func (*Reporter) SetMode

func (r *Reporter) SetMode(mode string)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL