v0.0.490 documentation and extra-params in exerr
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 4m2s
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 4m2s
This commit is contained in:
@@ -30,6 +30,10 @@ import (
|
||||
// If possible add metadata to the error (eg the id that was not found, ...), the methods are the same as in zerolog
|
||||
// return nil, exerror.Wrap(err, "do something failed").Str("someid", id).Int("count", in.Count).Build()
|
||||
//
|
||||
// You can also add extra-data to an error with Extra(..)
|
||||
// in contrast to metadata is extradata always printed in the resulting error and is more intended for additional (programmatically readable) data in addition to the errortype
|
||||
// (metadata is more internal debug info/help)
|
||||
//
|
||||
// You can change the errortype with `.User()` and `.System()` (User-errors are 400 and System-errors 500)
|
||||
// You can also manually set the statuscode with `.WithStatuscode(http.NotFound)`
|
||||
// You can set the type with `WithType(..)`
|
||||
@@ -76,12 +80,14 @@ func Wrap(err error, msg string) *Builder {
|
||||
return &Builder{errorData: newExErr(CatSystem, TypeInternal, msg)} // prevent NPE if we call Wrap with err==nil
|
||||
}
|
||||
|
||||
v := FromError(err)
|
||||
|
||||
if !pkgconfig.RecursiveErrors {
|
||||
v := FromError(err)
|
||||
v.Message = msg
|
||||
return &Builder{wrappedErr: err, errorData: v}
|
||||
} else {
|
||||
return &Builder{wrappedErr: err, errorData: wrapExErr(v, msg, CatWrap, 1)}
|
||||
}
|
||||
return &Builder{wrappedErr: err, errorData: wrapExErr(FromError(err), msg, CatWrap, 1)}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -368,29 +374,6 @@ func (b *Builder) CtxData(method Method, ctx context.Context) *Builder {
|
||||
return b
|
||||
}
|
||||
|
||||
func formatHeader(header map[string][]string) string {
|
||||
ml := 1
|
||||
for k, _ := range header {
|
||||
if len(k) > ml {
|
||||
ml = len(k)
|
||||
}
|
||||
}
|
||||
r := ""
|
||||
for k, v := range header {
|
||||
if r != "" {
|
||||
r += "\n"
|
||||
}
|
||||
for _, hval := range v {
|
||||
value := hval
|
||||
value = strings.ReplaceAll(value, "\n", "\\n")
|
||||
value = strings.ReplaceAll(value, "\r", "\\r")
|
||||
value = strings.ReplaceAll(value, "\t", "\\t")
|
||||
r += langext.StrPadRight(k, " ", ml) + " := " + value
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func extractHeader(header map[string][]string) []string {
|
||||
r := make([]string, 0, len(header))
|
||||
for k, v := range header {
|
||||
@@ -407,6 +390,16 @@ func extractHeader(header map[string][]string) []string {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Extra adds additional data to the error
|
||||
// this is not like the other metadata (like Id(), Str(), etc)
|
||||
// this data is public and will be printed/outputted
|
||||
func (b *Builder) Extra(key string, val any) *Builder {
|
||||
b.errorData.Extra[key] = val
|
||||
return b
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Build creates a new error, ready to pass up the stack
|
||||
// If the errors is not SevWarn or SevInfo it gets also logged (in short form, without stacktrace) onto stdout
|
||||
// Can be gloablly configured with ZeroLogErrTraces and ZeroLogAllTraces
|
||||
@@ -468,6 +461,10 @@ func (b *Builder) Print(ctxs ...context.Context) {
|
||||
b.errorData.Log(pkgconfig.ZeroLogger.Error())
|
||||
} else if b.errorData.Severity == SevWarn {
|
||||
b.errorData.ShortLog(pkgconfig.ZeroLogger.Warn())
|
||||
} else if b.errorData.Severity == SevInfo {
|
||||
b.errorData.ShortLog(pkgconfig.ZeroLogger.Info())
|
||||
} else {
|
||||
b.errorData.ShortLog(pkgconfig.ZeroLogger.Debug())
|
||||
}
|
||||
|
||||
b.errorData.CallListener(MethodPrint)
|
||||
|
@@ -31,6 +31,7 @@ func FromError(err error) *ExErr {
|
||||
Caller: "",
|
||||
OriginalError: nil,
|
||||
Meta: getForeignMeta(err),
|
||||
Extra: make(map[string]any),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +49,7 @@ func newExErr(cat ErrorCategory, errtype ErrorType, msg string) *ExErr {
|
||||
Caller: callername(2),
|
||||
OriginalError: nil,
|
||||
Meta: make(map[string]MetaValue),
|
||||
Extra: make(map[string]any),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +67,7 @@ func wrapExErr(e *ExErr, msg string, cat ErrorCategory, stacktraceskip int) *ExE
|
||||
Caller: callername(1 + stacktraceskip),
|
||||
OriginalError: e,
|
||||
Meta: make(map[string]MetaValue),
|
||||
Extra: langext.CopyMap(langext.ForceMap(e.Extra)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package exerr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rs/xid"
|
||||
"github.com/rs/zerolog"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
@@ -26,7 +27,8 @@ type ExErr struct {
|
||||
|
||||
OriginalError *ExErr `json:"originalError"`
|
||||
|
||||
Meta MetaMap `json:"meta"`
|
||||
Extra map[string]any `json:"extra"`
|
||||
Meta MetaMap `json:"meta"`
|
||||
}
|
||||
|
||||
func (ee *ExErr) Error() string {
|
||||
@@ -81,6 +83,23 @@ func (ee *ExErr) Log(evt *zerolog.Event) {
|
||||
}
|
||||
|
||||
func (ee *ExErr) FormatLog(lvl LogPrintLevel) string {
|
||||
|
||||
// [LogPrintShort]
|
||||
//
|
||||
// - Only print message and type
|
||||
// - Used e.g. for logging to the console when Build is called
|
||||
// - also used in Print() if level == Warn/Info
|
||||
//
|
||||
// [LogPrintOverview]
|
||||
//
|
||||
// - print message, extra and errortrace
|
||||
//
|
||||
// [LogPrintFull]
|
||||
//
|
||||
// - print full error, with meta and extra, and trace, etc
|
||||
// - Used in Output() and Print()
|
||||
//
|
||||
|
||||
if lvl == LogPrintShort {
|
||||
|
||||
msg := ee.Message
|
||||
@@ -101,6 +120,10 @@ func (ee *ExErr) FormatLog(lvl LogPrintLevel) string {
|
||||
|
||||
str := "[" + ee.RecursiveType().Key + "] <" + ee.UniqueID + "> " + strings.ReplaceAll(ee.RecursiveMessage(), "\n", " ") + "\n"
|
||||
|
||||
for exk, exv := range ee.Extra {
|
||||
str += fmt.Sprintf(" # [[[ %s ==> %v ]]]\n", exk, exv)
|
||||
}
|
||||
|
||||
indent := ""
|
||||
for curr := ee; curr != nil; curr = curr.OriginalError {
|
||||
indent += " "
|
||||
@@ -122,6 +145,10 @@ func (ee *ExErr) FormatLog(lvl LogPrintLevel) string {
|
||||
|
||||
str := "[" + ee.RecursiveType().Key + "] <" + ee.UniqueID + "> " + strings.ReplaceAll(ee.RecursiveMessage(), "\n", " ") + "\n"
|
||||
|
||||
for exk, exv := range ee.Extra {
|
||||
str += fmt.Sprintf(" # [[[ %s ==> %v ]]]\n", exk, exv)
|
||||
}
|
||||
|
||||
indent := ""
|
||||
for curr := ee; curr != nil; curr = curr.OriginalError {
|
||||
indent += " "
|
||||
@@ -328,6 +355,14 @@ func (ee *ExErr) GetMetaTime(key string) (time.Time, bool) {
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
func (ee *ExErr) GetExtra(key string) (any, bool) {
|
||||
if v, ok := ee.Extra[key]; ok {
|
||||
return v, true
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// contains test if the supplied error is contained in this error (anywhere in the chain)
|
||||
func (ee *ExErr) contains(original *ExErr) (*ExErr, bool) {
|
||||
if original == nil {
|
||||
|
14
exerr/gin.go
14
exerr/gin.go
@@ -90,6 +90,20 @@ func (ee *ExErr) ToAPIJson(applyExtendListener bool, includeWrappedErrors bool,
|
||||
apiOutput["__data"] = ee.toJson(0, applyExtendListener, includeMetaFields)
|
||||
}
|
||||
|
||||
for exkey, exval := range ee.Extra {
|
||||
|
||||
// ensure we do not override existing values
|
||||
for {
|
||||
if _, ok := apiOutput[exkey]; ok {
|
||||
exkey = "_" + exkey
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
apiOutput[exkey] = exval
|
||||
}
|
||||
|
||||
if applyExtendListener {
|
||||
pkgconfig.ExtendGinOutput(ee, apiOutput)
|
||||
}
|
||||
|
Reference in New Issue
Block a user