v0.1.12 SetConsoleWriter routes console output to a host writer
Test / test (push) Canceled after 0s
Test / fuzz (./compat, FuzzParseFormat) (push) Canceled after 0s
Test / fuzz (./formatter, FuzzFormatJSON) (push) Canceled after 0s
Test / fuzz (./formatter, FuzzFormatTextPolicy) (push) Canceled after 0s
Test / fuzz (./sanitizer, FuzzSanitize) (push) Canceled after 0s
Test / fuzz (./sanitizer, FuzzSerializerJSON) (push) Canceled after 0s
Test / test (push) Canceled after 0s
Test / fuzz (./compat, FuzzParseFormat) (push) Canceled after 0s
Test / fuzz (./formatter, FuzzFormatJSON) (push) Canceled after 0s
Test / fuzz (./formatter, FuzzFormatTextPolicy) (push) Canceled after 0s
Test / fuzz (./sanitizer, FuzzSanitize) (push) Canceled after 0s
Test / fuzz (./sanitizer, FuzzSerializerJSON) (push) Canceled after 0s
A host that draws on the terminal (a TUI) cannot let the logger write to stdout or stderr, yet the records are worth showing inside the host. SetErrorHandler already covers internal diagnostics; SetConsoleWriter is its sibling for console output. - SetConsoleWriter(w) sends console output of every console_target to w, split's warn-and-above records included; nil restores stdout/stderr. It holds across ApplyConfig and is safe while logging. - One stored value: ApplyConfig and SetConsoleWriter publish the console writers through storeConsole; the processor's split branch now reads the stored warn writer instead of writing os.Stderr directly. - TestLoggerConsoleTargets becomes TestConsoleWriterTakesEveryTarget, which asserts where each target's records land; a second test checks that nil restores the configured writers. - README names both hooks for terminal hosts; the API doc's callback contract covers console writers. Verified: go build ./... ok; gofmt -l on changed files clean; go vet ./... ok; go test ./... ok (all four packages, under 1 s); go test -race on the new tests ok; mutation run 6 of 6 caught. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SyaMAhyEzAp3ULLWJZG4jQ
This commit is contained in:
1 parent
2417e51da1
commit
fe711ed2a5
7 files changed
+72
-20
No files matched your search
+33
-7
@@ -1,6 +1,8 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -202,29 +204,53 @@ func TestLoggerConcurrency(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoggerConsoleTargets verifies console-only operation for each target.
|
||||
func TestLoggerConsoleTargets(t *testing.T) {
|
||||
// TestConsoleWriterTakesEveryTarget verifies each console target, split's warn
|
||||
// records included, writes to a console writer set before ApplyConfig.
|
||||
func TestConsoleWriterTakesEveryTarget(t *testing.T) {
|
||||
for _, target := range []string{"stdout", "stderr", "split"} {
|
||||
t.Run(target, func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
logger := NewLogger()
|
||||
logger.SetConsoleWriter(&out)
|
||||
cfg := DefaultConfig()
|
||||
cfg.Directory = t.TempDir()
|
||||
cfg.EnableConsole = true
|
||||
cfg.EnableFile = false
|
||||
cfg.ConsoleTarget = target
|
||||
|
||||
mustNoErr(t, logger.ApplyConfig(cfg), "ApplyConfig")
|
||||
mustNoErr(t, logger.Start(), "Start")
|
||||
t.Cleanup(func() { _ = logger.Shutdown() })
|
||||
|
||||
// split routes >=WARN to stderr; exercise both branches
|
||||
logger.Info("console info")
|
||||
logger.Error("console error")
|
||||
noErr(t, logger.Flush(time.Second), "Flush")
|
||||
mustNoErr(t, logger.Shutdown(time.Second), "Shutdown")
|
||||
contains(t, out.String(), "console info", "info record")
|
||||
contains(t, out.String(), "console error", "error record")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestConsoleWriterNilRestoresTarget verifies nil returns a running logger's
|
||||
// console output to the configured stdout and stderr.
|
||||
func TestConsoleWriterNilRestoresTarget(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
logger := NewLogger()
|
||||
cfg := DefaultConfig()
|
||||
cfg.EnableFile = false
|
||||
cfg.ConsoleTarget = "split"
|
||||
mustNoErr(t, logger.ApplyConfig(cfg), "ApplyConfig")
|
||||
mustNoErr(t, logger.Start(), "Start")
|
||||
t.Cleanup(func() { _ = logger.Shutdown() })
|
||||
|
||||
logger.SetConsoleWriter(&out)
|
||||
logger.Info("redirected")
|
||||
mustNoErr(t, logger.Flush(time.Second), "Flush")
|
||||
contains(t, out.String(), "redirected", "record after SetConsoleWriter")
|
||||
|
||||
logger.SetConsoleWriter(nil)
|
||||
got := logger.state.StdoutWriter.Load().(*sink)
|
||||
equal(t, got.w, io.Writer(os.Stdout), "below warn")
|
||||
equal(t, got.warn, io.Writer(os.Stderr), "warn and above")
|
||||
}
|
||||
|
||||
// TestLoggerWrite verifies Write emits raw bytes with no formatting, framing, or sanitization.
|
||||
func TestLoggerWrite(t *testing.T) {
|
||||
logger, tmpDir := newTestLogger(t)
|
||||
|
||||
Reference in new issue
Block a user