mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 02:48:59 +08:00
feat(errors): add errors package (#5741)
### Summary Add errors package #### Related Issues / PR's https://github.com/SigNoz/signoz/pull/5710
This commit is contained in:
parent
e7b5410c5b
commit
c322fc72d9
3
pkg/errors/doc.go
Normal file
3
pkg/errors/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// package error contains error related utilities. Use this package when
|
||||
// a well-defined error has to be shown.
|
||||
package errors
|
118
pkg/errors/errors.go
Normal file
118
pkg/errors/errors.go
Normal file
@ -0,0 +1,118 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// base is the fundamental struct that implements the error interface.
|
||||
// The order of the struct is 'TCMEUA'.
|
||||
type base struct {
|
||||
// t denotes the custom type of the error.
|
||||
t typ
|
||||
// c denotes the short code for the error message.
|
||||
c string
|
||||
// m contains error message passed through errors.New.
|
||||
m string
|
||||
// e is the actual error being wrapped.
|
||||
e error
|
||||
// u denotes the url for the documentation (if present) for the error.
|
||||
u string
|
||||
// a denotes any additional error messages (if present).
|
||||
a []string
|
||||
}
|
||||
|
||||
// base implements Error interface.
|
||||
func (b *base) Error() string {
|
||||
if b.e != nil {
|
||||
return b.e.Error()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s(%s): %s", b.t.s, b.c, b.m)
|
||||
}
|
||||
|
||||
// New returns a base error. It requires type, code and message as input.
|
||||
func New(t typ, code string, message string) *base {
|
||||
return &base{
|
||||
t: t,
|
||||
c: code,
|
||||
m: message,
|
||||
e: nil,
|
||||
u: "",
|
||||
a: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
// Newf returns a new base by formatting the error message with the supplied format specifier.
|
||||
func Newf(t typ, code string, format string, args ...interface{}) *base {
|
||||
return &base{
|
||||
t: t,
|
||||
c: code,
|
||||
m: fmt.Sprintf(format, args...),
|
||||
e: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapf returns a new error by formatting the error message with the supplied format specifier
|
||||
// and wrapping another error with base.
|
||||
func Wrapf(cause error, t typ, code string, format string, args ...interface{}) *base {
|
||||
return &base{
|
||||
t: t,
|
||||
c: code,
|
||||
m: fmt.Sprintf(format, args...),
|
||||
e: cause,
|
||||
}
|
||||
}
|
||||
|
||||
// WithUrl adds a url to the base error and returns a new base error.
|
||||
func (b *base) WithUrl(u string) *base {
|
||||
return &base{
|
||||
t: b.t,
|
||||
c: b.c,
|
||||
m: b.m,
|
||||
e: b.e,
|
||||
u: u,
|
||||
a: b.a,
|
||||
}
|
||||
}
|
||||
|
||||
// WithUrl adds additional messages to the base error and returns a new base error.
|
||||
func (b *base) WithAdditional(a ...string) *base {
|
||||
return &base{
|
||||
t: b.t,
|
||||
c: b.c,
|
||||
m: b.m,
|
||||
e: b.e,
|
||||
u: b.u,
|
||||
a: a,
|
||||
}
|
||||
}
|
||||
|
||||
// Unwrapb is a combination of built-in errors.As and type casting.
|
||||
// It finds the first error in cause that matches base,
|
||||
// and if one is found, returns the individual fields of base.
|
||||
// Otherwise, it returns TypeInternal, the original error string
|
||||
// and the error itself.
|
||||
//
|
||||
//lint:ignore ST1008 we want to return arguments in the 'TCMEUA' order of the struct
|
||||
func Unwrapb(cause error) (typ, string, string, error, string, []string) {
|
||||
base, ok := cause.(*base)
|
||||
if ok {
|
||||
return base.t, base.c, base.m, base.e, base.u, base.a
|
||||
}
|
||||
|
||||
return TypeInternal, "", cause.Error(), cause, "", []string{}
|
||||
}
|
||||
|
||||
// Ast checks if the provided error matches the specified custom error type.
|
||||
func Ast(cause error, typ typ) bool {
|
||||
t, _, _, _, _, _ := Unwrapb(cause)
|
||||
|
||||
return t == typ
|
||||
}
|
||||
|
||||
// Ast checks if the provided error matches the specified custom error code.
|
||||
func Asc(cause error, code string) bool {
|
||||
_, c, _, _, _, _ := Unwrapb(cause)
|
||||
|
||||
return c == code
|
||||
}
|
53
pkg/errors/errors_test.go
Normal file
53
pkg/errors/errors_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
typ := typ{"test-error"}
|
||||
err := New(typ, "code", "test error info")
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestNewf(t *testing.T) {
|
||||
typ := typ{"test-error"}
|
||||
err := Newf(typ, "test-code", "test error info with %s", "string")
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, "test-error(test-code): test error info with string", err.Error())
|
||||
}
|
||||
|
||||
func TestWrapf(t *testing.T) {
|
||||
typ := typ{"test-error"}
|
||||
err := Wrapf(errors.New("original error"), typ, "test-code", "info for err %d", 2)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestError(t *testing.T) {
|
||||
typ := typ{"test-error"}
|
||||
err1 := New(typ, "test-code", "info for err1")
|
||||
assert.Equal(t, "test-error(test-code): info for err1", err1.Error())
|
||||
|
||||
err2 := Wrapf(err1, typ, "test-code", "info for err2")
|
||||
assert.Equal(t, "test-error(test-code): info for err1", err2.Error())
|
||||
}
|
||||
|
||||
func TestUnwrapb(t *testing.T) {
|
||||
typ := typ{"test-error"}
|
||||
oerr := errors.New("original error")
|
||||
berr := Wrapf(oerr, typ, "test-code", "this is a base err").WithUrl("https://docs").WithAdditional("additional err")
|
||||
|
||||
atyp, acode, amessage, aerr, au, aa := Unwrapb(berr)
|
||||
assert.Equal(t, typ, atyp)
|
||||
assert.Equal(t, "test-code", acode)
|
||||
assert.Equal(t, "this is a base err", amessage)
|
||||
assert.Equal(t, oerr, aerr)
|
||||
assert.Equal(t, "https://docs", au)
|
||||
assert.Equal(t, []string{"additional err"}, aa)
|
||||
|
||||
atyp, _, _, _, _, _ = Unwrapb(oerr)
|
||||
assert.Equal(t, TypeInternal, atyp)
|
||||
}
|
14
pkg/errors/type.go
Normal file
14
pkg/errors/type.go
Normal file
@ -0,0 +1,14 @@
|
||||
package errors
|
||||
|
||||
var (
|
||||
TypeInvalidInput typ = typ{"invalid-input"}
|
||||
TypeInternal = typ{"internal"}
|
||||
TypeUnsupported = typ{"unsupported"}
|
||||
TypeNotFound = typ{"not-found"}
|
||||
TypeMethodNotAllowed = typ{"method-not-allowed"}
|
||||
TypeAlreadyExists = typ{"already-exists"}
|
||||
TypeUnauthenticated = typ{"unauthenticated"}
|
||||
)
|
||||
|
||||
// Defines custom error types
|
||||
type typ struct{ s string }
|
18
pkg/errors/type_test.go
Normal file
18
pkg/errors/type_test.go
Normal file
@ -0,0 +1,18 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
typ := typ{"test-error"}
|
||||
assert.Equal(t, typ.s, "test-error")
|
||||
}
|
||||
|
||||
func TestEquals(t *testing.T) {
|
||||
typ1 := typ{"test-error"}
|
||||
typ2 := typ{"test-error"}
|
||||
assert.True(t, typ1 == typ2)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user