2023-02-15 16:04:19 +01:00
package exerr
2023-07-24 10:42:39 +02:00
import (
2024-05-03 15:28:53 +02:00
"context"
2023-07-24 10:42:39 +02:00
"fmt"
2024-05-03 15:28:53 +02:00
"github.com/gin-gonic/gin"
2024-06-14 23:18:58 +02:00
"github.com/rs/zerolog"
2023-07-24 10:42:39 +02:00
"gogs.mikescher.com/BlackForestBytes/goext/langext"
2024-05-03 15:28:53 +02:00
"net/http"
2024-06-14 23:18:58 +02:00
"os"
2023-07-24 10:42:39 +02:00
)
2023-02-15 16:04:19 +01:00
type ErrorPackageConfig struct {
2024-05-03 15:28:53 +02:00
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)
2024-06-14 23:18:58 +02:00
ZeroLogger zerolog . Logger // The logger used to print exerr log messages
2023-02-15 16:04:19 +01:00
}
type ErrorPackageConfigInit struct {
2023-08-21 13:27:36 +02:00
ZeroLogErrTraces * bool
ZeroLogAllTraces * bool
RecursiveErrors * bool
ExtendedGinOutput * bool
IncludeMetaInGinOutput * bool
2023-08-09 10:39:14 +02:00
ExtendGinOutput func ( err * ExErr , json map [ string ] any )
ExtendGinDataOutput func ( err * ExErr , depth int , json map [ string ] any )
2024-01-13 14:10:25 +01:00
DisableErrorWrapping * bool
2024-04-15 10:25:30 +02:00
ZeroLogErrGinOutput * bool
ZeroLogAllGinOutput * bool
2024-05-03 15:28:53 +02:00
ExtendGinMeta func ( ctx context . Context , b * Builder , g * gin . Context , req * http . Request )
ExtendContextMeta func ( b * Builder , method Method , dctx context . Context )
2024-06-14 23:18:58 +02:00
ZeroLogger * zerolog . Logger
2023-02-15 16:04:19 +01:00
}
var initialized = false
var pkgconfig = ErrorPackageConfig {
2023-08-09 10:39:14 +02:00
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 ) { } ,
2024-01-13 14:10:25 +01:00
DisableErrorWrapping : false ,
2024-04-15 10:25:30 +02:00
ZeroLogErrGinOutput : true ,
ZeroLogAllGinOutput : false ,
2024-05-03 15:28:53 +02:00
ExtendGinMeta : func ( ctx context . Context , b * Builder , g * gin . Context , req * http . Request ) { } ,
ExtendContextMeta : func ( b * Builder , method Method , dctx context . Context ) { } ,
2023-02-15 16:04:19 +01:00
}
// 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" )
}
2023-07-24 11:42:52 +02:00
ego := func ( err * ExErr , json map [ string ] any ) { }
egdo := func ( err * ExErr , depth int , json map [ string ] any ) { }
2024-05-03 15:28:53 +02:00
egm := func ( ctx context . Context , b * Builder , g * gin . Context , req * http . Request ) { }
egcm := func ( b * Builder , method Method , dctx context . Context ) { }
2023-07-24 11:42:52 +02:00
if cfg . ExtendGinOutput != nil {
ego = cfg . ExtendGinOutput
}
if cfg . ExtendGinDataOutput != nil {
egdo = cfg . ExtendGinDataOutput
}
2024-05-03 15:28:53 +02:00
if cfg . ExtendGinMeta != nil {
egm = cfg . ExtendGinMeta
}
if cfg . ExtendContextMeta != nil {
egcm = cfg . ExtendContextMeta
}
2023-07-24 11:42:52 +02:00
2024-06-14 23:18:58 +02:00
var logger zerolog . Logger
if cfg . ZeroLogger != nil {
logger = * cfg . ZeroLogger
} else {
logger = newDefaultLogger ( )
}
2023-02-15 16:04:19 +01:00
pkgconfig = ErrorPackageConfig {
2023-08-21 13:27:36 +02:00
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 ) ,
2023-08-09 10:39:14 +02:00
ExtendGinOutput : ego ,
ExtendGinDataOutput : egdo ,
2024-01-13 14:10:25 +01:00
DisableErrorWrapping : langext . Coalesce ( cfg . DisableErrorWrapping , pkgconfig . DisableErrorWrapping ) ,
2024-04-15 10:25:30 +02:00
ZeroLogAllGinOutput : langext . Coalesce ( cfg . ZeroLogAllGinOutput , pkgconfig . ZeroLogAllGinOutput ) ,
ZeroLogErrGinOutput : langext . Coalesce ( cfg . ZeroLogErrGinOutput , pkgconfig . ZeroLogErrGinOutput ) ,
2024-05-03 15:28:53 +02:00
ExtendGinMeta : egm ,
ExtendContextMeta : egcm ,
2024-06-14 23:18:58 +02:00
ZeroLogger : logger ,
2023-02-15 16:04:19 +01:00
}
initialized = true
}
2023-07-24 10:42:39 +02:00
2024-06-14 23:18:58 +02:00
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 ( )
}
2023-11-27 14:14:58 +01:00
func Initialized ( ) bool {
return initialized
}
2023-07-24 10:42:39 +02:00
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" )
}
}