splinter/console_stream.go
2026-04-25 20:35:03 +00:00

75 lines
1.9 KiB
Go

package splinter
import (
"context"
"io"
"log/slog"
"os"
)
// ConsoleFormat selects the output style for ConsoleStream.
type ConsoleFormat int
const (
// ConsoleJSON writes structured JSON lines.
ConsoleJSON ConsoleFormat = iota
// ConsolePretty writes human-readable text (slog.TextHandler).
ConsolePretty
)
// ConsoleStream writes log records to an io.Writer (default os.Stderr) using
// the standard library's slog handlers.
type ConsoleStream struct {
logger *slog.Logger
level Level
}
// ConsoleOption configures a ConsoleStream.
type ConsoleOption func(*consoleConfig)
type consoleConfig struct {
writer io.Writer
}
// ConsoleWriter overrides the output destination (default: os.Stderr).
func ConsoleWriter(w io.Writer) ConsoleOption {
return func(c *consoleConfig) { c.writer = w }
}
// NewConsoleStream creates a console stream.
func NewConsoleStream(format ConsoleFormat, level Level, opts ...ConsoleOption) *ConsoleStream {
cfg := &consoleConfig{writer: os.Stderr}
for _, o := range opts {
o(cfg)
}
handlerOpts := &slog.HandlerOptions{Level: level}
var handler slog.Handler
switch format {
case ConsolePretty:
handler = slog.NewTextHandler(cfg.writer, handlerOpts)
default:
handler = slog.NewJSONHandler(cfg.writer, handlerOpts)
}
return &ConsoleStream{logger: slog.New(handler), level: level}
}
// Name implements Stream.
func (s *ConsoleStream) Name() string { return "console" }
// Write implements Stream.
func (s *ConsoleStream) Write(ctx context.Context, rec Record) error {
args := make([]any, 0, len(rec.Attrs)*2)
for k, v := range rec.Attrs {
args = append(args, k, v)
}
s.logger.Log(ctx, rec.Level, rec.Message, args...)
return nil
}
// Enabled implements Stream.
func (s *ConsoleStream) Enabled(level Level) bool { return level >= s.level }
// Close implements Stream. No-op for console output.
func (s *ConsoleStream) Close() error { return nil }