75 lines
1.9 KiB
Go
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 }
|