diff --git a/exerr/builder.go b/exerr/builder.go index d963353..838715e 100644 --- a/exerr/builder.go +++ b/exerr/builder.go @@ -68,10 +68,11 @@ func init() { } type Builder struct { - wrappedErr error - errorData *ExErr - containsGinData bool - noLog bool + wrappedErr error + errorData *ExErr + containsGinData bool + containsContextData bool + noLog bool } func Get(err error) *Builder { @@ -365,10 +366,20 @@ func (b *Builder) GinReq(ctx context.Context, g *gin.Context, req *http.Request) } + pkgconfig.ExtendGinMeta(ctx, b, g, req) + b.containsGinData = true return b } +func (b *Builder) CtxData(method Method, ctx context.Context) *Builder { + pkgconfig.ExtendContextMeta(b, method, ctx) + + b.containsContextData = true + + return b +} + func formatHeader(header map[string][]string) string { ml := 1 for k, _ := range header { @@ -412,9 +423,13 @@ func extractHeader(header map[string][]string) []string { // 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 // Can be locally suppressed with Builder.NoLog() -func (b *Builder) Build() error { +func (b *Builder) Build(ctxs ...context.Context) error { warnOnPkgConfigNotInitialized() + for _, dctx := range ctxs { + b.CtxData(MethodBuild, dctx) + } + if pkgconfig.DisableErrorWrapping && b.wrappedErr != nil { return b.wrappedErr } @@ -439,6 +454,8 @@ func (b *Builder) Output(ctx context.Context, g *gin.Context) { b.GinReq(ctx, g, g.Request) } + b.CtxData(MethodOutput, ctx) + b.errorData.Output(g) if (b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal) && (pkgconfig.ZeroLogErrGinOutput || pkgconfig.ZeroLogAllGinOutput) { @@ -452,7 +469,13 @@ func (b *Builder) Output(ctx context.Context, g *gin.Context) { // Print prints the error // If the error is SevErr we also send it to the error-service -func (b *Builder) Print() { +func (b *Builder) Print(ctxs ...context.Context) { + warnOnPkgConfigNotInitialized() + + for _, dctx := range ctxs { + b.CtxData(MethodPrint, dctx) + } + if b.errorData.Severity == SevErr || b.errorData.Severity == SevFatal { b.errorData.Log(stackSkipLogger.Error()) } else if b.errorData.Severity == SevWarn { @@ -468,7 +491,12 @@ func (b *Builder) Format(level LogPrintLevel) string { // Fatal prints the error and terminates the program // If the error is SevErr we also send it to the error-service -func (b *Builder) Fatal() { +func (b *Builder) Fatal(ctxs ...context.Context) { + + for _, dctx := range ctxs { + b.CtxData(MethodFatal, dctx) + } + b.errorData.Severity = SevFatal b.errorData.Log(stackSkipLogger.WithLevel(zerolog.FatalLevel)) diff --git a/exerr/errinit.go b/exerr/errinit.go index 63288ba..4b259c3 100644 --- a/exerr/errinit.go +++ b/exerr/errinit.go @@ -1,21 +1,26 @@ package exerr import ( + "context" "fmt" + "github.com/gin-gonic/gin" "gogs.mikescher.com/BlackForestBytes/goext/langext" + "net/http" ) 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() - 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 - DisableErrorWrapping bool // Disables the exerr.Wrap()...Build() function - will always return the original error - ZeroLogErrGinOutput bool // autom print zerolog logs on ginext.Error() / .Output(gin) (for SevErr and SevFatal) - ZeroLogAllGinOutput bool // autom print zerolog logs on ginext.Error() / .Output(gin) (for all Severities) + 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 + DisableErrorWrapping bool // Disables the exerr.Wrap()...Build() function - will always return the original error + ZeroLogErrGinOutput bool // autom print zerolog logs on ginext.Error() / .Output(gin) (for SevErr and SevFatal) + ZeroLogAllGinOutput bool // autom print zerolog logs on ginext.Error() / .Output(gin) (for all Severities) + ExtendGinMeta func(ctx context.Context, b *Builder, g *gin.Context, req *http.Request) // (Optionally) extend the final error meta values with additional data from the gin context (a few are automatically added, here more can be included) + ExtendContextMeta func(b *Builder, method Method, dctx context.Context) // (Optionally) extend the final error meta values with additional data from the context (a few are automatically added, here more can be included) } type ErrorPackageConfigInit struct { @@ -29,6 +34,8 @@ type ErrorPackageConfigInit struct { DisableErrorWrapping *bool ZeroLogErrGinOutput *bool ZeroLogAllGinOutput *bool + ExtendGinMeta func(ctx context.Context, b *Builder, g *gin.Context, req *http.Request) + ExtendContextMeta func(b *Builder, method Method, dctx context.Context) } var initialized = false @@ -44,6 +51,8 @@ var pkgconfig = ErrorPackageConfig{ DisableErrorWrapping: false, ZeroLogErrGinOutput: true, ZeroLogAllGinOutput: false, + ExtendGinMeta: func(ctx context.Context, b *Builder, g *gin.Context, req *http.Request) {}, + ExtendContextMeta: func(b *Builder, method Method, dctx context.Context) {}, } // Init initializes the exerr packages @@ -56,6 +65,8 @@ func Init(cfg ErrorPackageConfigInit) { ego := func(err *ExErr, json map[string]any) {} egdo := func(err *ExErr, depth int, json map[string]any) {} + egm := func(ctx context.Context, b *Builder, g *gin.Context, req *http.Request) {} + egcm := func(b *Builder, method Method, dctx context.Context) {} if cfg.ExtendGinOutput != nil { ego = cfg.ExtendGinOutput @@ -63,6 +74,12 @@ func Init(cfg ErrorPackageConfigInit) { if cfg.ExtendGinDataOutput != nil { egdo = cfg.ExtendGinDataOutput } + if cfg.ExtendGinMeta != nil { + egm = cfg.ExtendGinMeta + } + if cfg.ExtendContextMeta != nil { + egcm = cfg.ExtendContextMeta + } pkgconfig = ErrorPackageConfig{ ZeroLogErrTraces: langext.Coalesce(cfg.ZeroLogErrTraces, pkgconfig.ZeroLogErrTraces), @@ -75,6 +92,8 @@ func Init(cfg ErrorPackageConfigInit) { DisableErrorWrapping: langext.Coalesce(cfg.DisableErrorWrapping, pkgconfig.DisableErrorWrapping), ZeroLogAllGinOutput: langext.Coalesce(cfg.ZeroLogAllGinOutput, pkgconfig.ZeroLogAllGinOutput), ZeroLogErrGinOutput: langext.Coalesce(cfg.ZeroLogErrGinOutput, pkgconfig.ZeroLogErrGinOutput), + ExtendGinMeta: egm, + ExtendContextMeta: egcm, } initialized = true diff --git a/goextVersion.go b/goextVersion.go index f8e1577..a1895e8 100644 --- a/goextVersion.go +++ b/goextVersion.go @@ -1,5 +1,5 @@ package goext -const GoextVersion = "0.0.444" +const GoextVersion = "0.0.445" -const GoextVersionTimestamp = "2024-05-03T13:24:08+0200" +const GoextVersionTimestamp = "2024-05-03T15:28:53+0200"