v0.1.4 formatter race fix, fiber adapter added, default config changed, docs updated

This commit is contained in:
2025-11-17 16:33:08 -05:00
parent 4ed618abbb
commit 9b0a632b52
22 changed files with 797 additions and 56 deletions

254
compat/fiber.go Normal file
View File

@ -0,0 +1,254 @@
// FILE: lixenwraith/log/compat/fiber.go
package compat
import (
"fmt"
"os"
"time"
"github.com/lixenwraith/log"
)
// FiberAdapter wraps lixenwraith/log.Logger to implement Fiber's CommonLogger interface
// This provides compatibility with Fiber v2.54.x logging requirements
type FiberAdapter struct {
logger *log.Logger
fatalHandler func(msg string) // Customizable fatal behavior
panicHandler func(msg string) // Customizable panic behavior
}
// NewFiberAdapter creates a new Fiber-compatible logger adapter
func NewFiberAdapter(logger *log.Logger, opts ...FiberOption) *FiberAdapter {
adapter := &FiberAdapter{
logger: logger,
fatalHandler: func(msg string) {
os.Exit(1) // Default behavior
},
panicHandler: func(msg string) {
panic(msg) // Default behavior
},
}
for _, opt := range opts {
opt(adapter)
}
return adapter
}
// FiberOption allows customizing adapter behavior
type FiberOption func(*FiberAdapter)
// WithFiberFatalHandler sets a custom fatal handler
func WithFiberFatalHandler(handler func(string)) FiberOption {
return func(a *FiberAdapter) {
a.fatalHandler = handler
}
}
// WithFiberPanicHandler sets a custom panic handler
func WithFiberPanicHandler(handler func(string)) FiberOption {
return func(a *FiberAdapter) {
a.panicHandler = handler
}
}
// --- Logger interface implementation (7 methods) ---
// Trace logs at trace/debug level
func (a *FiberAdapter) Trace(v ...any) {
msg := fmt.Sprint(v...)
a.logger.Debug("msg", msg, "source", "fiber", "level", "trace")
}
// Debug logs at debug level
func (a *FiberAdapter) Debug(v ...any) {
msg := fmt.Sprint(v...)
a.logger.Debug("msg", msg, "source", "fiber")
}
// Info logs at info level
func (a *FiberAdapter) Info(v ...any) {
msg := fmt.Sprint(v...)
a.logger.Info("msg", msg, "source", "fiber")
}
// Warn logs at warn level
func (a *FiberAdapter) Warn(v ...any) {
msg := fmt.Sprint(v...)
a.logger.Warn("msg", msg, "source", "fiber")
}
// Error logs at error level
func (a *FiberAdapter) Error(v ...any) {
msg := fmt.Sprint(v...)
a.logger.Error("msg", msg, "source", "fiber")
}
// Fatal logs at error level and triggers fatal handler
func (a *FiberAdapter) Fatal(v ...any) {
msg := fmt.Sprint(v...)
a.logger.Error("msg", msg, "source", "fiber", "fatal", true)
// Ensure log is flushed before exit
_ = a.logger.Flush(100 * time.Millisecond)
if a.fatalHandler != nil {
a.fatalHandler(msg)
}
}
// Panic logs at error level and triggers panic handler
func (a *FiberAdapter) Panic(v ...any) {
msg := fmt.Sprint(v...)
a.logger.Error("msg", msg, "source", "fiber", "panic", true)
// Ensure log is flushed before panic
_ = a.logger.Flush(100 * time.Millisecond)
if a.panicHandler != nil {
a.panicHandler(msg)
}
}
// Write makes FiberAdapter implement io.Writer interface
// This allows it to be used with fiber.Config.ErrorHandler output redirection
func (a *FiberAdapter) Write(p []byte) (n int, err error) {
msg := string(p)
// Trim trailing newline if present
if len(msg) > 0 && msg[len(msg)-1] == '\n' {
msg = msg[:len(msg)-1]
}
a.logger.Info("msg", msg, "source", "fiber")
return len(p), nil
}
// --- FormatLogger interface implementation (7 methods) ---
// Tracef logs at trace/debug level with printf-style formatting
func (a *FiberAdapter) Tracef(format string, v ...any) {
msg := fmt.Sprintf(format, v...)
a.logger.Debug("msg", msg, "source", "fiber", "level", "trace")
}
// Debugf logs at debug level with printf-style formatting
func (a *FiberAdapter) Debugf(format string, v ...any) {
msg := fmt.Sprintf(format, v...)
a.logger.Debug("msg", msg, "source", "fiber")
}
// Infof logs at info level with printf-style formatting
func (a *FiberAdapter) Infof(format string, v ...any) {
msg := fmt.Sprintf(format, v...)
a.logger.Info("msg", msg, "source", "fiber")
}
// Warnf logs at warn level with printf-style formatting
func (a *FiberAdapter) Warnf(format string, v ...any) {
msg := fmt.Sprintf(format, v...)
a.logger.Warn("msg", msg, "source", "fiber")
}
// Errorf logs at error level with printf-style formatting
func (a *FiberAdapter) Errorf(format string, v ...any) {
msg := fmt.Sprintf(format, v...)
a.logger.Error("msg", msg, "source", "fiber")
}
// Fatalf logs at error level and triggers fatal handler
func (a *FiberAdapter) Fatalf(format string, v ...any) {
msg := fmt.Sprintf(format, v...)
a.logger.Error("msg", msg, "source", "fiber", "fatal", true)
// Ensure log is flushed before exit
_ = a.logger.Flush(100 * time.Millisecond)
if a.fatalHandler != nil {
a.fatalHandler(msg)
}
}
// Panicf logs at error level and triggers panic handler
func (a *FiberAdapter) Panicf(format string, v ...any) {
msg := fmt.Sprintf(format, v...)
a.logger.Error("msg", msg, "source", "fiber", "panic", true)
// Ensure log is flushed before panic
_ = a.logger.Flush(100 * time.Millisecond)
if a.panicHandler != nil {
a.panicHandler(msg)
}
}
// --- WithLogger interface implementation (7 methods) ---
// Tracew logs at trace/debug level with structured key-value pairs
func (a *FiberAdapter) Tracew(msg string, keysAndValues ...any) {
fields := make([]any, 0, len(keysAndValues)+6)
fields = append(fields, "msg", msg, "source", "fiber", "level", "trace")
fields = append(fields, keysAndValues...)
a.logger.Debug(fields...)
}
// Debugw logs at debug level with structured key-value pairs
func (a *FiberAdapter) Debugw(msg string, keysAndValues ...any) {
fields := make([]any, 0, len(keysAndValues)+4)
fields = append(fields, "msg", msg, "source", "fiber")
fields = append(fields, keysAndValues...)
a.logger.Debug(fields...)
}
// Infow logs at info level with structured key-value pairs
func (a *FiberAdapter) Infow(msg string, keysAndValues ...any) {
fields := make([]any, 0, len(keysAndValues)+4)
fields = append(fields, "msg", msg, "source", "fiber")
fields = append(fields, keysAndValues...)
a.logger.Info(fields...)
}
// Warnw logs at warn level with structured key-value pairs
func (a *FiberAdapter) Warnw(msg string, keysAndValues ...any) {
fields := make([]any, 0, len(keysAndValues)+4)
fields = append(fields, "msg", msg, "source", "fiber")
fields = append(fields, keysAndValues...)
a.logger.Warn(fields...)
}
// Errorw logs at error level with structured key-value pairs
func (a *FiberAdapter) Errorw(msg string, keysAndValues ...any) {
fields := make([]any, 0, len(keysAndValues)+4)
fields = append(fields, "msg", msg, "source", "fiber")
fields = append(fields, keysAndValues...)
a.logger.Error(fields...)
}
// Fatalw logs at error level with structured key-value pairs and triggers fatal handler
func (a *FiberAdapter) Fatalw(msg string, keysAndValues ...any) {
fields := make([]any, 0, len(keysAndValues)+6)
fields = append(fields, "msg", msg, "source", "fiber", "fatal", true)
fields = append(fields, keysAndValues...)
a.logger.Error(fields...)
// Ensure log is flushed before exit
_ = a.logger.Flush(100 * time.Millisecond)
if a.fatalHandler != nil {
a.fatalHandler(msg)
}
}
// Panicw logs at error level with structured key-value pairs and triggers panic handler
func (a *FiberAdapter) Panicw(msg string, keysAndValues ...any) {
fields := make([]any, 0, len(keysAndValues)+6)
fields = append(fields, "msg", msg, "source", "fiber", "panic", true)
fields = append(fields, keysAndValues...)
a.logger.Error(fields...)
// Ensure log is flushed before panic
_ = a.logger.Flush(100 * time.Millisecond)
if a.panicHandler != nil {
a.panicHandler(msg)
}
}