controller: fix-3 dead-app alerting + fix-6 ring cap/spill/spam (WIP, pre-build)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
This commit is contained in:
2026-07-12 10:07:47 +02:00
parent a6da64da15
commit d8f6069b46
10 changed files with 581 additions and 10 deletions
+10 -1
View File
@@ -64,6 +64,13 @@ func (s *Scheduler) dbg(format string, args ...interface{}) {
}
}
// trace logs a periodic-job routine line at [TRACE] — below the debug ring's capture threshold, so
// the every-cycle "job finished" noise never eats the post-incident window (fix-6, CAMPAIGN-3). Job
// FAILURES are logged at [ERROR] (never here), so this never hides a problem.
func (s *Scheduler) trace(format string, args ...interface{}) {
s.logger.Printf("[TRACE] [scheduler] "+format, args...)
}
// New creates a new Scheduler.
func New(logger *log.Logger) *Scheduler {
return &Scheduler{
@@ -295,7 +302,9 @@ func (s *Scheduler) executeJob(job *Job, quiet bool) {
} else if !quiet {
s.logger.Printf("[INFO] [scheduler] Job %s completed (took %s)", job.Name, elapsed.Round(time.Millisecond))
}
s.dbg("job %s: finished in %s (err=%v)", job.Name, elapsed.Round(time.Millisecond), err)
// Routine per-cycle timing line → TRACE (dropped from the ring; the completed/failed lines above
// carry the outcome). This was the biggest ring filler under load (fix-6).
s.trace("job %s: finished in %s (err=%v)", job.Name, elapsed.Round(time.Millisecond), err)
}
// parseDailyTime parses "HH:MM" and returns hour and minute.