From 5f2845c3311a5e6997c897403bd061deed991f34 Mon Sep 17 00:00:00 2001 From: Steve Cliff Date: Sun, 3 May 2026 13:35:18 +0100 Subject: [PATCH] agent runner: drop status-event spam from log.stream restic --json emits a status frame ~every 16ms during a backup. The runner was forwarding every line to log.stream verbatim, which flooded the live log pane with duplicate status JSON for any short-running backup (visible immediately on a 1000-file, ~4MB test set: ~14 identical 'percent_done: 1' lines in 220ms). The progress widget already covers the same information at a sane sample rate (one per second via job.progress), so the raw status lines in log.stream are double-bookkeeping. Skip them and forward only non-status lines (file names, errors, summary). Throttling logic for job.progress is unchanged. --- internal/agent/runner/runner.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/internal/agent/runner/runner.go b/internal/agent/runner/runner.go index 62c17f4..e7b1e0b 100644 --- a/internal/agent/runner/runner.go +++ b/internal/agent/runner/runner.go @@ -74,19 +74,26 @@ func (r *Runner) RunBackup(ctx context.Context, jobID string, paths, excludes, t lastProgress := time.Now() handle := func(stream string, line string, ev any) { - // Forward every line to the server as log.stream. - now := time.Now().UTC() - logEnv, _ := api.Marshal(api.MsgLogStream, "", api.LogStreamLine{ - JobID: jobID, - Seq: seq.Add(1), - TS: now, - Stream: api.LogStream(stream), - Payload: line, - }) - _ = r.tx.Send(logEnv) + // Throttled progress events come from restic's `status` JSON. + // We deliberately do NOT forward the raw status line to + // log.stream — it's emitted ~every 16ms by restic --json and + // would drown the live log in dupes for any short backup. The + // progress widget already covers the same information at a + // sane sample rate. + status, isStatus := ev.(restic.BackupStatus) + if !isStatus { + now := time.Now().UTC() + logEnv, _ := api.Marshal(api.MsgLogStream, "", api.LogStreamLine{ + JobID: jobID, + Seq: seq.Add(1), + TS: now, + Stream: api.LogStream(stream), + Payload: line, + }) + _ = r.tx.Send(logEnv) + } - // Throttled progress events. - if status, ok := ev.(restic.BackupStatus); ok { + if isStatus { if time.Since(lastProgress) < r.progressMinPeriod { return }