Files
go-omni/logx/adapters.go

68 lines
1.7 KiB
Go

package logx
import (
"context"
"errors"
"log"
"log/slog"
"strings"
)
// Validate checks configuration without opening files or creating resources.
func (c Config) Validate() error {
c = normalizeConfig(c)
if _, err := parseLevel(c.Level); err != nil {
return errors.New("logx: invalid level")
}
if c.Format != "json" && c.Format != "text" {
return errors.New("logx: format must be json or text")
}
switch c.Output {
case "stdout", "stderr", "discard", "none":
default:
return errors.New("logx: invalid output")
}
return c.Rotation.validate(c)
}
type loggerContextKey struct{}
// WithLogger borrows a logger for a call tree; it does not alter the global
// default and does not transfer ownership. nil preserves the existing context.
func WithLogger(ctx context.Context, logger *Logger) context.Context {
ctx = normalizeContext(ctx)
if logger == nil {
return ctx
}
return context.WithValue(ctx, loggerContextKey{}, logger)
}
// FromContext returns a call-scoped logger, falling back to package logging.
func FromContext(ctx context.Context) *Logger {
if ctx != nil {
if l, ok := ctx.Value(loggerContextKey{}).(*Logger); ok && l != nil {
return l
}
}
return defaultLogger.Load()
}
// Standard adapts this instance to the standard logger (for http.Server etc).
// It borrows the writer and never closes it. Each Print call becomes one event.
func (l *Logger) Standard(level slog.Level) *log.Logger {
if l == nil {
l = defaultLogger.Load()
}
return log.New(standardWriter{logger: l, level: level}, "", 0)
}
type standardWriter struct {
logger *Logger
level slog.Level
}
func (w standardWriter) Write(p []byte) (int, error) {
w.logger.logger.Log(context.Background(), w.level, strings.TrimRight(string(p), "\r\n"))
return len(p), nil
}