Mike Schwörer
d2f2a0558a
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m27s
139 lines
6.2 KiB
Go
139 lines
6.2 KiB
Go
package exerr
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/rs/zerolog"
|
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
|
"net/http"
|
|
"os"
|
|
)
|
|
|
|
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)
|
|
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)
|
|
ZeroLogger zerolog.Logger // The logger used to print exerr log messages
|
|
}
|
|
|
|
type ErrorPackageConfigInit struct {
|
|
ZeroLogErrTraces *bool
|
|
ZeroLogAllTraces *bool
|
|
RecursiveErrors *bool
|
|
ExtendedGinOutput *bool
|
|
IncludeMetaInGinOutput *bool
|
|
ExtendGinOutput func(err *ExErr, json map[string]any)
|
|
ExtendGinDataOutput func(err *ExErr, depth int, json map[string]any)
|
|
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)
|
|
ZeroLogger *zerolog.Logger
|
|
}
|
|
|
|
var initialized = false
|
|
|
|
var pkgconfig = ErrorPackageConfig{
|
|
ZeroLogErrTraces: true,
|
|
ZeroLogAllTraces: false,
|
|
RecursiveErrors: true,
|
|
ExtendedGinOutput: false,
|
|
IncludeMetaInGinOutput: true,
|
|
ExtendGinOutput: func(err *ExErr, json map[string]any) {},
|
|
ExtendGinDataOutput: func(err *ExErr, depth int, json map[string]any) {},
|
|
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
|
|
// Must be called at the program start, before (!) any errors
|
|
// Is not thread-safe
|
|
func Init(cfg ErrorPackageConfigInit) {
|
|
if initialized {
|
|
panic("Cannot re-init error package")
|
|
}
|
|
|
|
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
|
|
}
|
|
if cfg.ExtendGinDataOutput != nil {
|
|
egdo = cfg.ExtendGinDataOutput
|
|
}
|
|
if cfg.ExtendGinMeta != nil {
|
|
egm = cfg.ExtendGinMeta
|
|
}
|
|
if cfg.ExtendContextMeta != nil {
|
|
egcm = cfg.ExtendContextMeta
|
|
}
|
|
|
|
var logger zerolog.Logger
|
|
if cfg.ZeroLogger != nil {
|
|
logger = *cfg.ZeroLogger
|
|
} else {
|
|
logger = newDefaultLogger()
|
|
}
|
|
|
|
pkgconfig = ErrorPackageConfig{
|
|
ZeroLogErrTraces: langext.Coalesce(cfg.ZeroLogErrTraces, pkgconfig.ZeroLogErrTraces),
|
|
ZeroLogAllTraces: langext.Coalesce(cfg.ZeroLogAllTraces, pkgconfig.ZeroLogAllTraces),
|
|
RecursiveErrors: langext.Coalesce(cfg.RecursiveErrors, pkgconfig.RecursiveErrors),
|
|
ExtendedGinOutput: langext.Coalesce(cfg.ExtendedGinOutput, pkgconfig.ExtendedGinOutput),
|
|
IncludeMetaInGinOutput: langext.Coalesce(cfg.IncludeMetaInGinOutput, pkgconfig.IncludeMetaInGinOutput),
|
|
ExtendGinOutput: ego,
|
|
ExtendGinDataOutput: egdo,
|
|
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,
|
|
ZeroLogger: logger,
|
|
}
|
|
|
|
initialized = true
|
|
}
|
|
|
|
func newDefaultLogger() zerolog.Logger {
|
|
cw := zerolog.ConsoleWriter{
|
|
Out: os.Stdout,
|
|
TimeFormat: "2006-01-02 15:04:05 Z07:00",
|
|
}
|
|
|
|
multi := zerolog.MultiLevelWriter(cw)
|
|
|
|
return zerolog.New(multi).With().Timestamp().CallerWithSkipFrameCount(4).Logger()
|
|
}
|
|
|
|
func Initialized() bool {
|
|
return initialized
|
|
}
|
|
|
|
func warnOnPkgConfigNotInitialized() {
|
|
if !initialized {
|
|
fmt.Printf("\n")
|
|
fmt.Printf("%s\n", langext.StrRepeat("=", 80))
|
|
fmt.Printf("%s\n", "[WARNING] exerr package used without initializiation")
|
|
fmt.Printf("%s\n", " call exerr.Init() in your main() function")
|
|
fmt.Printf("%s\n", langext.StrRepeat("=", 80))
|
|
fmt.Printf("\n")
|
|
}
|
|
}
|