diff --git a/exerr/errinit.go b/exerr/errinit.go index eadb7cc..7c2d1a2 100644 --- a/exerr/errinit.go +++ b/exerr/errinit.go @@ -6,12 +6,13 @@ import ( ) type ErrorPackageConfig struct { - ZeroLogErrTraces bool // autom print zerolog logs on .Build() (for SevErr and SevFatal) - ZeroLogAllTraces bool // autom print zerolog logs on .Build() (for all Severities) - RecursiveErrors bool // errors contains their Origin-Error - ExtendedGinOutput bool // Log extended data (trace, meta, ...) to gin in err.Output() - ExtendGinOutput func(err *ExErr, json map[string]any) // (Optionally) extend the gin output with more fields - ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any) // (Optionally) extend the gin `__data` output with more fields + ZeroLogErrTraces bool // autom print zerolog logs on .Build() (for SevErr and SevFatal) + ZeroLogAllTraces bool // autom print zerolog logs on .Build() (for all Severities) + RecursiveErrors bool // errors contains their Origin-Error + ExtendedGinOutput bool // Log extended data (trace, meta, ...) to gin in err.Output() + IncludeMetaInGinOutput bool // Log meta fields ( from e.g. `.Str(key, val).Build()` ) to gin in err.Output() + ExtendGinOutput func(err *ExErr, json map[string]any) // (Optionally) extend the gin output with more fields + ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any) // (Optionally) extend the gin `__data` output with more fields } type ErrorPackageConfigInit struct { diff --git a/exerr/gin.go b/exerr/gin.go index 917ccdf..4f2c756 100644 --- a/exerr/gin.go +++ b/exerr/gin.go @@ -8,7 +8,7 @@ import ( "time" ) -func (ee *ExErr) toJson(depth int, applyExtendListener bool) langext.H { +func (ee *ExErr) toJson(depth int, applyExtendListener bool, outputMeta bool) langext.H { ginJson := langext.H{} if ee.UniqueID != "" { @@ -39,7 +39,15 @@ func (ee *ExErr) toJson(depth int, applyExtendListener bool) langext.H { ginJson["wrappedErrType"] = ee.WrappedErrType } if ee.OriginalError != nil { - ginJson["original"] = ee.OriginalError.toJson(depth+1, applyExtendListener) + ginJson["original"] = ee.OriginalError.toJson(depth+1, applyExtendListener, outputMeta) + } + + if outputMeta { + metaJson := langext.H{} + for metaKey, metaVal := range ee.Meta { + metaJson[metaKey] = metaVal.rawValueForJson() + } + ginJson["meta"] = metaJson } if applyExtendListener { @@ -55,7 +63,8 @@ func (ee *ExErr) toJson(depth int, applyExtendListener bool) langext.H { // Parameters: // - [applyExtendListener]: if false the pkgconfig.ExtendGinOutput / pkgconfig.ExtendGinDataOutput will not be applied // - [includeWrappedErrors]: if false we do not include the recursive/wrapped errors in `__data` -func (ee *ExErr) ToAPIJson(applyExtendListener bool, includeWrappedErrors bool) langext.H { +// - [includeMetaFields]: if true we also include meta-values (aka from `.Str(key, value).Build()`), needs includeWrappedErrors=true +func (ee *ExErr) ToAPIJson(applyExtendListener bool, includeWrappedErrors bool, includeMetaFields bool) langext.H { apiOutput := langext.H{ "errorid": ee.UniqueID, @@ -65,7 +74,7 @@ func (ee *ExErr) ToAPIJson(applyExtendListener bool, includeWrappedErrors bool) } if includeWrappedErrors { - apiOutput["__data"] = ee.toJson(0, applyExtendListener) + apiOutput["__data"] = ee.toJson(0, applyExtendListener, includeMetaFields) } if applyExtendListener { @@ -97,7 +106,7 @@ func (ee *ExErr) Output(g *gin.Context) { statuscode = *baseType.DefaultStatusCode } - ginOutput := ee.ToAPIJson(true, pkgconfig.ExtendedGinOutput) + ginOutput := ee.ToAPIJson(true, pkgconfig.ExtendedGinOutput, pkgconfig.IncludeMetaInGinOutput) g.Render(statuscode, json.GoJsonRender{Data: ginOutput, NilSafeSlices: true, NilSafeMaps: true}) } diff --git a/exerr/meta.go b/exerr/meta.go index 4bd1393..102d0da 100644 --- a/exerr/meta.go +++ b/exerr/meta.go @@ -585,6 +585,40 @@ func (v MetaValue) ValueString() string { return "(err)" } +// rawValueForJson returns most-of-the-time the `Value` field +// but for some datatyes we do special processing +// all, so we can pluck the output value in json.Marshal without any suprises +func (v MetaValue) rawValueForJson() any { + if v.DataType == MDTAny { + if v.Value.(AnyWrap).IsNil { + return nil + } + return v.Value.(AnyWrap).Serialize() + } + if v.DataType == MDTID { + if v.Value.(IDWrap).IsNil { + return nil + } + return v.Value.(IDWrap).Value + } + if v.DataType == MDTBytes { + return hex.EncodeToString(v.Value.([]byte)) + } + if v.DataType == MDTDuration { + return v.Value.(time.Duration).String() + } + if v.DataType == MDTTime { + return v.Value.(time.Time).Format(time.RFC3339Nano) + } + if v.DataType == MDTObjectID { + return v.Value.(primitive.ObjectID).Hex() + } + if v.DataType == MDTNil { + return nil + } + return v.Value +} + func (mm MetaMap) FormatOneLine(singleMaxLen int) string { r := "" diff --git a/goextVersion.go b/goextVersion.go index 46c0ef6..2db1c9e 100644 --- a/goextVersion.go +++ b/goextVersion.go @@ -1,5 +1,5 @@ package goext -const GoextVersion = "0.0.232" +const GoextVersion = "0.0.233" -const GoextVersionTimestamp = "2023-08-08T18:01:00+0200" +const GoextVersionTimestamp = "2023-08-09T10:37:59+0200"