diff --git a/internal/wanted/search.go b/internal/wanted/search.go index 3b5efb2e..e13b6e8a 100644 --- a/internal/wanted/search.go +++ b/internal/wanted/search.go @@ -89,6 +89,7 @@ type Report struct { func (s *Searcher) Run(ctx context.Context) { ticker := time.NewTicker(searchTick) defer ticker.Stop() + said := "" for { select { case <-ctx.Done(): @@ -96,14 +97,33 @@ func (s *Searcher) Run(ctx context.Context) { case <-ticker.C: } rep := s.Pass(ctx) - if rep.Looked > 0 || rep.Error != "" { - s.logger.Info("wanted: search pass", "looked", rep.Looked, "grabbed", rep.Grabbed, - "waiting", rep.Waiting, "nothing", rep.Nothing, "failed", rep.Failed, - "paced", rep.Paced, "error", rep.Error) + // A pass that searched is always logged; an idle one only when the + // schedule's state changes, so the log says once why it is quiet. + if state := rep.state(); rep.Looked > 0 || rep.Error != "" || state != said { + s.logger.Info("wanted: search pass", "state", state, "looked", rep.Looked, + "grabbed", rep.Grabbed, "waiting", rep.Waiting, "nothing", rep.Nothing, + "failed", rep.Failed, "paced", rep.Paced, "error", rep.Error) + said = state } } } +// state names why a pass did what it did: off, unconfigured, failed, +// idle (nothing was due) or searched. +func (r Report) state() string { + switch { + case r.Off: + return "off" + case r.Unconfigured: + return "unconfigured" + case r.Error != "": + return "failed" + case r.Looked == 0: + return "idle" + } + return "searched" +} + // Pass searches for the wants due, paced by the sources, until the window // closes, and records what it did. func (s *Searcher) Pass(ctx context.Context) Report { diff --git a/internal/wanted/search_test.go b/internal/wanted/search_test.go index a96ce3ea..7dc5649e 100644 --- a/internal/wanted/search_test.go +++ b/internal/wanted/search_test.go @@ -194,3 +194,20 @@ func TestGrabs_OneLivePerWant_Integration(t *testing.T) { t.Errorf("live = %+v %v %v", live, ok, err) } } + +func TestReport_StateNamesWhyAPassWasQuiet(t *testing.T) { + for _, c := range []struct { + rep Report + want string + }{ + {Report{Off: true}, "off"}, + {Report{Unconfigured: true}, "unconfigured"}, + {Report{Error: "boom"}, "failed"}, + {Report{}, "idle"}, + {Report{Looked: 2, Grabbed: 1}, "searched"}, + } { + if got := c.rep.state(); got != c.want { + t.Errorf("%+v: state = %q, want %q", c.rep, got, c.want) + } + } +}