kerrs

package
v0.0.0-...-81c75b8 Latest Latest
Warning

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

Go to latest
Published: Apr 21, 2024 License: MIT Imports: 5 Imported by: 2

README

Package kerrs provide the following purpose

  • Wrap context values pair for structure logging
  • Include stacktrace automatically
  • Support multiple error return for continue a loop when error happens

Append

func Append(err error, errs ...error) error

Append returns a multi error, useful when say you are looping csv file lines for return orders. one of them have error, But you should continue to deal with next lines, But you want the function to return error.

	var handleCSV = func(csvContent string) (err error) {
	    var handleLine = func(line string) (err error) {
	        if len(line) > 3 {
	            err = fmt.Errorf("Invalid Length for %s", line)
	        }
	        return
	    }
	    lines := strings.Split(csvContent, "\n")
	    for _, line := range lines {
	        lineErr := handleLine(line)
	        if lineErr != nil {
	            err = kerrs.Append(err, lineErr)
	            continue
	        }
	
	        // NOT
	        // if err != nil {
	        //	return
	        // }
	    }
	    return
	}
	
	err3 := handleCSV("a\n1234\nb11111\nc")
	fmt.Printf("%+v\n", err3)
	
	// Output:
	// 2 errors occurred:
	//
	// * Invalid Length for 1234
	// * Invalid Length for b11111

Extract

func Extract(err error) (kvs []interface{}, msg string, stacktrace string)

Extract an error of it's context values and message, it loop through to each level of errors, and concat each err message to a whole error message, and cause field is removed for easy to read, and concat each level error's stacktrace together to make a new whole stacktrace.

	err0 := errors.New("hi, I am an error")
	err1 := kerrs.Wrapv(err0, "wrong", "code", "12123", "value", 12312)
	err2 := kerrs.Wrapv(err1, "more explain about the error", "product_name", "iphone", "color", "red")
	err3 := kerrs.Wrapv(err2, "in regexp", "request_id", "T1212123129983")
	kvs, msg, stacktrace := kerrs.Extract(err3)
	
	var actual = bytes.NewBuffer(nil)
	fmt.Fprintln(actual, "\nmsg:", msg)
	fmt.Fprintf(actual, "\nkeyvals: %#+v\n\n", kvs)
	fmt.Fprintf(actual, "stacktrace:\n%s", cleanStacktrace(stacktrace))
	
	expected := `
	msg: in regexp: more explain about the error: wrong: hi, I am an error
	
	keyvals: []interface {}{"request_id", "T1212123129983", "product_name", "iphone", "color", "red", "code", "12123", "value", 12312}
	
	stacktrace:
	in regexp request_id=T1212123129983: more explain about the error product_name=iphone color=red: wrong code=12123 value=12312: hi, I am an error
	github.com/theplant/appkit/kerrs.Wrapv
	github.com/theplant/appkit/kerrs/errors.go:27
	github.com/theplant/appkit/kerrs_test.ExampleExtract_errors
	github.com/theplant/appkit/kerrs/example_test.go:76`
	
	diff := testingutils.PrettyJsonDiff(expected, actual.String())
	fmt.Println(diff)
	// Output:
	//

Wrapv

func Wrapv(err error, message string, keyvals ...interface{}) error

Wrapv should be invoked whenever an error returned from other libraries you imported, and you didn't handle the error, you should wrap it and return it to upper side. By wrapping it, includes stacktrace, and any context values, like your func parameters, So that when it gets logged, It reveal more contexts for developer to know where and what the problem is.

	err0 := errors.New("hi, I am an error")
	err1 := kerrs.Wrapv(err0, "wrong", "code", "12123", "value", 12312)
	
	// fmt.Printf("%+v", err)
	err2 := kerrs.Wrapv(err1, "more explain about the error", "morecontext", "999")
	
	actual := cleanStacktrace(fmt.Sprintf("\n%+v\n", err2))
	expected := `
	more explain about the error morecontext=999: wrong code=12123 value=12312: hi, I am an error
	github.com/theplant/appkit/kerrs.Wrapv
	github.com/theplant/appkit/kerrs/errors.go:27
	github.com/theplant/appkit/kerrs_test.ExampleWrapv_errors`
	
	diff := testingutils.PrettyJsonDiff(expected, actual)
	fmt.Println(diff)
	// Output:
	//

Documentation

Overview

Package kerrs provide the following purpose

- Wrap context values pair for structure logging - Include stacktrace automatically - Support multiple error return for continue a loop when error happens

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Append

func Append(err error, errs ...error) error

Append returns a multi error, useful when say you are looping csv file lines for return orders. one of them have error, But you should continue to deal with next lines, But you want the function to return error.

Example (Errors)
package main

import (
	"fmt"
	"strings"

	"github.com/theplant/appkit/kerrs"
)

func main() {

	var handleCSV = func(csvContent string) (err error) {
		var handleLine = func(line string) (err error) {
			if len(line) > 3 {
				err = fmt.Errorf("Invalid Length for %s", line)
			}
			return
		}
		lines := strings.Split(csvContent, "\n")
		for _, line := range lines {
			lineErr := handleLine(line)
			if lineErr != nil {
				err = kerrs.Append(err, lineErr)
				continue
			}

			// NOT
			// if err != nil {
			//	return
			// }
		}
		return
	}

	err3 := handleCSV("a\n1234\nb11111\nc")
	fmt.Printf("%+v\n", err3)

}
Output:

2 errors occurred:
	* Invalid Length for 1234
	* Invalid Length for b11111

func Extract

func Extract(err error) (kvs []interface{}, msg string, stacktrace string)

Extract an error of it's context values and message, it loop through to each level of errors, and concat each err message to a whole error message, and cause field is removed for easy to read, and concat each level error's stacktrace together to make a new whole stacktrace.

Example (Errors)
package main

import (
	"errors"
	"fmt"
	"strings"

	"bytes"

	"github.com/theplant/appkit/kerrs"
	"github.com/theplant/testingutils"
)

func main() {
	err0 := errors.New("hi, I am an error")
	err1 := kerrs.Wrapv(err0, "wrong", "code", "12123", "value", 12312)
	err2 := kerrs.Wrapv(err1, "more explain about the error", "product_name", "iphone", "color", "red")
	err3 := kerrs.Wrapv(err2, "in regexp", "request_id", "T1212123129983")
	kvs, msg, stacktrace := kerrs.Extract(err3)

	var actual = bytes.NewBuffer(nil)
	fmt.Fprintln(actual, "\nmsg:", msg)
	fmt.Fprintf(actual, "\nkeyvals: %#+v\n\n", kvs)
	fmt.Fprintf(actual, "stacktrace:\n%s", cleanStacktrace(stacktrace))

	expected := `
msg: in regexp: more explain about the error: wrong: hi, I am an error

keyvals: []interface {}{"request_id", "T1212123129983", "product_name", "iphone", "color", "red", "code", "12123", "value", 12312}

stacktrace:
in regexp request_id=T1212123129983: more explain about the error product_name=iphone color=red: wrong code=12123 value=12312: hi, I am an error
<stacktrace>
`

	diff := testingutils.PrettyJsonDiff(expected, actual.String())
	fmt.Println(diff)
}

func cleanStacktrace(stacktrace string) (cleantrace string) {
	cleantrace = strings.Split(stacktrace, "\n")[0]
	cleantrace = cleantrace + "\n<stacktrace>\n"
	return
}
Output:

func Wrapv

func Wrapv(err error, message string, keyvals ...interface{}) error

Wrapv should be invoked whenever an error returned from other libraries you imported, and you didn't handle the error, you should wrap it and return it to upper side. By wrapping it, includes stacktrace, and any context values, like your func parameters, So that when it gets logged, It reveal more contexts for developer to know where and what the problem is.

Example (Errors)
package main

import (
	"errors"
	"fmt"
	"strings"

	"github.com/theplant/appkit/kerrs"
	"github.com/theplant/testingutils"
)

func main() {
	err0 := errors.New("hi, I am an error")
	err1 := kerrs.Wrapv(err0, "wrong", "code", "12123", "value", 12312)

	// fmt.Printf("%+v", err)
	err2 := kerrs.Wrapv(err1, "more explain about the error", "morecontext", "999")

	actual := cleanStacktrace(fmt.Sprintf("%+v\n", err2))
	expected := `more explain about the error morecontext=999: wrong code=12123 value=12312: hi, I am an error
<stacktrace>
`

	diff := testingutils.PrettyJsonDiff(expected, actual)
	fmt.Println(diff)
}

func cleanStacktrace(stacktrace string) (cleantrace string) {
	cleantrace = strings.Split(stacktrace, "\n")[0]
	cleantrace = cleantrace + "\n<stacktrace>\n"
	return
}
Output:

Types

This section is empty.

Jump to

Keyboard shortcuts

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