Return sink write errors from every handler (closes #22)
The console and JSON handlers threw away the error from their write to stdout, so a lost log line looked delivered. They now return it, wrapped. The webhook handler also returns an error for a status outside 2xx. The multiplex handler passes the record to every handler and returns their errors joined with errors.Join instead of stopping at the first. Both stdout handlers gain an unexported writer, nil meaning os.Stdout at write time, so tests can supply a sink that fails. The README says what each handler returns and that the slog.Logger methods discard a handler's error. Model: opus-5-5
This commit is contained in:
+16
-4
@@ -4,12 +4,16 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
)
|
||||
|
||||
// JSONHandler writes each log record to stdout as a JSON document.
|
||||
type JSONHandler struct {
|
||||
// out is where records are written. Nil means os.Stdout, looked up on
|
||||
// every write so that a reassigned os.Stdout is followed.
|
||||
out io.Writer
|
||||
attrs handlerAttrs
|
||||
}
|
||||
|
||||
@@ -19,14 +23,22 @@ func NewJSONHandler() *JSONHandler {
|
||||
}
|
||||
|
||||
// Handle marshals the record, with its attributes, to one JSON object and
|
||||
// writes it to stdout.
|
||||
// writes it to stdout. A failed write is returned as an error.
|
||||
func (j *JSONHandler) Handle(_ context.Context, record slog.Record) error {
|
||||
jsonData, err := json.Marshal(recordToMap(record, j.attrs))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintln(os.Stdout, string(jsonData))
|
||||
out := j.out
|
||||
if out == nil {
|
||||
out = os.Stdout
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(out, string(jsonData))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing log record: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -44,7 +56,7 @@ func (j *JSONHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
return j
|
||||
}
|
||||
|
||||
return &JSONHandler{attrs: j.attrs.withAttrs(attrs)}
|
||||
return &JSONHandler{out: j.out, attrs: j.attrs.withAttrs(attrs)}
|
||||
}
|
||||
|
||||
// WithGroup returns a new handler that nests later attributes in an
|
||||
@@ -54,5 +66,5 @@ func (j *JSONHandler) WithGroup(name string) slog.Handler {
|
||||
return j
|
||||
}
|
||||
|
||||
return &JSONHandler{attrs: j.attrs.withGroup(name)}
|
||||
return &JSONHandler{out: j.out, attrs: j.attrs.withGroup(name)}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user