From bb495788924537c09d2346b88713eb12e52ec160 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sat, 20 Jun 2026 21:11:57 +0900 Subject: [PATCH] bt: filter anacrolix logs to errors so warnings don't corrupt the readout webseed/peer/tracker warnings (the 403/429 chatter) go through slog, the rest through the legacy analog logger; both default to Warning, which interleaves with and corrupts the live progress block. Filter both to Error and above so only genuine errors reach stderr. quietSlogger is a small testable helper; anacrolix/log becomes a direct dependency. --- bt/bt.go | 17 +++++++++++++++++ bt/bt_test.go | 28 ++++++++++++++++++++++++++++ go.mod | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/bt/bt.go b/bt/bt.go index dc42c9d..b3f8f49 100644 --- a/bt/bt.go +++ b/bt/bt.go @@ -9,12 +9,16 @@ package bt import ( "context" "fmt" + "io" + "log/slog" + "os" "path/filepath" "strconv" "strings" "sync/atomic" "time" + alog "github.com/anacrolix/log" missinggo "github.com/anacrolix/missinggo/v2" "github.com/anacrolix/torrent" "github.com/anacrolix/torrent/metainfo" @@ -73,6 +77,14 @@ func ParsePorts(spec string) []int { return ports } +// quietSlogger filters anacrolix's structured logging down to Error and above, +// so the routine webseed/peer/tracker warning chatter (the 403/429 noise) no +// longer interleaves with — and corrupts — the live progress display. Genuine +// errors still reach w. +func quietSlogger(w io.Writer) *slog.Logger { + return slog.New(slog.NewTextHandler(w, &slog.HandlerOptions{Level: slog.LevelError})) +} + // NewClient builds the shared anacrolix client from the run-wide config. When a // listen-port spec is given it tries each candidate port in turn, advancing past // any that is already in use, and falls back to an OS-chosen port if none bind, @@ -91,6 +103,11 @@ func ParsePorts(spec string) []int { // prevention must come from a run-wide setting (e.g. --enable-dht=false). func NewClient(cfg ClientConfig) (*torrent.Client, error) { c := torrent.NewDefaultClientConfig() + // Keep the library's own logging out of the readout. Webseed/peer warnings go + // through slog, the rest through the legacy analog logger, so filter both to + // Error and above (the analog default is Warning, which is what leaks today). + c.Slogger = quietSlogger(os.Stderr) + c.Logger = alog.Default.FilterLevel(alog.Error) c.DataDir = cfg.Dir if c.DataDir == "" { c.DataDir = "." diff --git a/bt/bt_test.go b/bt/bt_test.go index a386df5..6d81c88 100644 --- a/bt/bt_test.go +++ b/bt/bt_test.go @@ -1,10 +1,38 @@ package bt import ( + "bytes" + "context" + "log/slog" "reflect" + "strings" "testing" ) +// TestQuietSloggerDropsWarnings: the library's warning chatter (the webseed +// 403/429 noise) is filtered out so it can't corrupt the live display, while a +// genuine error still gets through. +func TestQuietSloggerDropsWarnings(t *testing.T) { + var buf bytes.Buffer + lg := quietSlogger(&buf) + + lg.Warn("webseed request error", "err", "429 Too Many Requests") + if buf.Len() != 0 { + t.Errorf("warning leaked into output: %q", buf.String()) + } + // anacrolix's webseed code logs via Log(ctx, level, ...); confirm that path is + // filtered too, not just the Warn helper. + lg.Log(context.Background(), slog.LevelWarn, "another warning") + if buf.Len() != 0 { + t.Errorf("Log-at-Warn leaked: %q", buf.String()) + } + + lg.Error("real failure") + if !strings.Contains(buf.String(), "real failure") { + t.Errorf("error was suppressed, want it kept: %q", buf.String()) + } +} + func TestParsePorts(t *testing.T) { tests := []struct { spec string diff --git a/go.mod b/go.mod index 214284d..6577641 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/hanbok/got go 1.25 require ( + github.com/anacrolix/log v0.17.1-0.20251118025802-918f1157b7bb github.com/anacrolix/missinggo/v2 v2.10.0 github.com/anacrolix/torrent v1.61.0 golang.org/x/sys v0.38.0 @@ -19,7 +20,6 @@ require ( github.com/anacrolix/envpprof v1.4.0 // indirect github.com/anacrolix/generics v0.1.1-0.20251125230353-15d98d46693b // indirect github.com/anacrolix/go-libutp v1.3.2 // indirect - github.com/anacrolix/log v0.17.1-0.20251118025802-918f1157b7bb // indirect github.com/anacrolix/missinggo v1.3.0 // indirect github.com/anacrolix/missinggo/perf v1.0.0 // indirect github.com/anacrolix/mmsg v1.0.1 // indirect