diff --git a/internal/log/log.go b/internal/log/log.go index 5b719fb25a..26eaadfa93 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -78,6 +78,16 @@ func (sl *StdLogger) ErrorContext(ctx context.Context, msg string, keysAndValues sl.errLogger.ErrorContext(ctx, msg, keysAndValues...) } +// SlogLogger returns a single standard *slog.Logger that routes +// records to the outLogger or errLogger based on the log level. +func (sl *StdLogger) SlogLogger() *slog.Logger { + splitHandler := &SplitHandler{ + OutHandler: sl.outLogger.Handler(), + ErrHandler: sl.errLogger.Handler(), + } + return slog.New(splitHandler) +} + const ( Debug = "DEBUG" Info = "INFO" @@ -195,3 +205,46 @@ func (sl *StructuredLogger) WarnContext(ctx context.Context, msg string, keysAnd func (sl *StructuredLogger) ErrorContext(ctx context.Context, msg string, keysAndValues ...any) { sl.errLogger.ErrorContext(ctx, msg, keysAndValues...) } + +// SlogLogger returns a single standard *slog.Logger that routes +// records to the outLogger or errLogger based on the log level. +func (sl *StructuredLogger) SlogLogger() *slog.Logger { + splitHandler := &SplitHandler{ + OutHandler: sl.outLogger.Handler(), + ErrHandler: sl.errLogger.Handler(), + } + return slog.New(splitHandler) +} + +type SplitHandler struct { + OutHandler slog.Handler + ErrHandler slog.Handler +} + +func (h *SplitHandler) Enabled(ctx context.Context, level slog.Level) bool { + if level >= slog.LevelError { + return h.ErrHandler.Enabled(ctx, level) + } + return h.OutHandler.Enabled(ctx, level) +} + +func (h *SplitHandler) Handle(ctx context.Context, r slog.Record) error { + if r.Level >= slog.LevelError { + return h.ErrHandler.Handle(ctx, r) + } + return h.OutHandler.Handle(ctx, r) +} + +func (h *SplitHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + return &SplitHandler{ + OutHandler: h.OutHandler.WithAttrs(attrs), + ErrHandler: h.ErrHandler.WithAttrs(attrs), + } +} + +func (h *SplitHandler) WithGroup(name string) slog.Handler { + return &SplitHandler{ + OutHandler: h.OutHandler.WithGroup(name), + ErrHandler: h.ErrHandler.WithGroup(name), + } +} diff --git a/internal/log/logger.go b/internal/log/logger.go index 14da0bfdfb..5953ce556a 100644 --- a/internal/log/logger.go +++ b/internal/log/logger.go @@ -16,6 +16,7 @@ package log import ( "context" + "log/slog" ) // Logger is the interface used throughout the project for logging. @@ -28,4 +29,7 @@ type Logger interface { WarnContext(ctx context.Context, format string, args ...any) // ErrorContext is for reporting errors. ErrorContext(ctx context.Context, format string, args ...any) + // Single standard slog.Logger that routes records to the outLogger or + // errLogger based on log levels + SlogLogger() *slog.Logger } diff --git a/internal/server/server.go b/internal/server/server.go index d126cf2ffa..c53fb7840c 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -18,7 +18,6 @@ import ( "context" "fmt" "io" - "log/slog" "net" "net/http" "slices" @@ -356,7 +355,7 @@ func NewServer(ctx context.Context, cfg ServerConfig) (*Server, error) { Level: logLevel, Schema: schema, } - logger := l.(*slog.Logger) + logger := l.SlogLogger() r.Use(httplog.RequestLogger(logger, httpOpts)) sourcesMap, authServicesMap, embeddingModelsMap, toolsMap, toolsetsMap, promptsMap, promptsetsMap, err := InitializeConfigs(ctx, cfg)