feat: comprehensive INFO/WARN/ERROR logging across all controller modules
Add structured operational logging at INFO, WARN, and ERROR levels to every controller module. Standardize custom prefixes ([GEO], [SCHED], [SYNC]) to use [INFO/WARN/ERROR] [module] format. Fix misleveled logs (WARN->ERROR for data loss scenarios, WARN->INFO for routine operations). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -75,7 +75,7 @@ func New(logger *log.Logger) *Scheduler {
|
||||
// If the scheduler is already started, the job's goroutine is launched immediately.
|
||||
func (s *Scheduler) Every(name string, interval time.Duration, fn JobFunc) {
|
||||
if interval <= 0 {
|
||||
s.logger.Printf("[ERROR] Periodic job %s has invalid interval %s — job not registered", name, interval)
|
||||
s.logger.Printf("[ERROR] [scheduler] Periodic job %s has invalid interval %s — job not registered", name, interval)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func (s *Scheduler) Every(name string, interval time.Duration, fn JobFunc) {
|
||||
Interval: interval,
|
||||
}
|
||||
s.jobs = append(s.jobs, job)
|
||||
s.logger.Printf("[SCHED] Registered periodic job: %s (every %s)", name, interval)
|
||||
s.logger.Printf("[INFO] [scheduler] Registered periodic job: %s (every %s)", name, interval)
|
||||
s.dbg("periodic job registered: name=%q interval=%s totalJobs=%d", name, interval, len(s.jobs))
|
||||
|
||||
if s.started {
|
||||
@@ -105,7 +105,7 @@ func (s *Scheduler) Daily(name string, timeStr string, fn JobFunc) {
|
||||
|
||||
// Validate time format
|
||||
if _, _, err := parseDailyTime(timeStr); err != nil {
|
||||
s.logger.Printf("[ERROR] Daily job %s has invalid schedule %q: %v — job not started", name, timeStr, err)
|
||||
s.logger.Printf("[ERROR] [scheduler] Daily job %s has invalid schedule %q: %v — job not started", name, timeStr, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ func (s *Scheduler) Daily(name string, timeStr string, fn JobFunc) {
|
||||
s.jobs = append(s.jobs, job)
|
||||
|
||||
nextRun := nextDailyRun(timeStr)
|
||||
s.logger.Printf("[SCHED] Daily job %s scheduled for %s", name, nextRun.Format("2006-01-02 15:04 MST"))
|
||||
s.logger.Printf("[INFO] [scheduler] Daily job %s scheduled for %s", name, nextRun.Format("2006-01-02 15:04 MST"))
|
||||
s.dbg("daily job registered: name=%q schedule=%q nextRun=%s totalJobs=%d", name, timeStr, nextRun.Format(time.RFC3339), len(s.jobs))
|
||||
|
||||
if s.started {
|
||||
@@ -131,7 +131,7 @@ func (s *Scheduler) Start(ctx context.Context) {
|
||||
s.mu.Lock()
|
||||
if s.cancel != nil {
|
||||
s.mu.Unlock()
|
||||
s.logger.Println("[WARN] Scheduler already started — ignoring duplicate Start()")
|
||||
s.logger.Println("[WARN] [scheduler] Scheduler already started — ignoring duplicate Start()")
|
||||
return
|
||||
}
|
||||
s.ctx, s.cancel = context.WithCancel(ctx)
|
||||
@@ -147,7 +147,7 @@ func (s *Scheduler) Start(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
s.logger.Printf("[SCHED] Scheduler started with %d jobs", len(s.jobs))
|
||||
s.logger.Printf("[INFO] [scheduler] Starting scheduler with %d jobs", len(s.jobs))
|
||||
s.dbg("scheduler started: periodic=%d daily=%d", func() int {
|
||||
n := 0
|
||||
for _, j := range s.jobs {
|
||||
@@ -173,6 +173,7 @@ func (s *Scheduler) Stop() {
|
||||
s.mu.Lock()
|
||||
cancel := s.cancel
|
||||
s.mu.Unlock()
|
||||
s.logger.Printf("[INFO] [scheduler] Stopping scheduler")
|
||||
if cancel != nil {
|
||||
cancel()
|
||||
}
|
||||
@@ -185,9 +186,9 @@ func (s *Scheduler) Stop() {
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
s.logger.Println("[SCHED] All jobs stopped")
|
||||
s.logger.Println("[INFO] [scheduler] All jobs stopped")
|
||||
case <-time.After(30 * time.Second):
|
||||
s.logger.Println("[WARN] Scheduler stop timed out after 30s — some jobs may still be running")
|
||||
s.logger.Println("[WARN] [scheduler] Scheduler stop timed out after 30s — some jobs may still be running")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +252,7 @@ func (s *Scheduler) executeJob(job *Job, quiet bool) {
|
||||
s.mu.Lock()
|
||||
if job.Running {
|
||||
s.mu.Unlock()
|
||||
s.logger.Printf("[WARN] Job %s still running, skipping", job.Name)
|
||||
s.logger.Printf("[WARN] [scheduler] Job %s still running, skipping", job.Name)
|
||||
return
|
||||
}
|
||||
job.Running = true
|
||||
@@ -270,12 +271,12 @@ func (s *Scheduler) executeJob(job *Job, quiet bool) {
|
||||
job.LastErr = fmt.Errorf("panic: %v", r)
|
||||
job.LastRun = time.Now()
|
||||
s.mu.Unlock()
|
||||
s.logger.Printf("[ERROR] Job %s panicked: %v", job.Name, r)
|
||||
s.logger.Printf("[ERROR] [scheduler] Job %s panicked: %v", job.Name, r)
|
||||
}
|
||||
}()
|
||||
|
||||
if !quiet {
|
||||
s.logger.Printf("[SCHED] Running job: %s", job.Name)
|
||||
s.logger.Printf("[INFO] [scheduler] Running job: %s", job.Name)
|
||||
}
|
||||
s.dbg("job %s: execution starting", job.Name)
|
||||
|
||||
@@ -289,10 +290,10 @@ func (s *Scheduler) executeJob(job *Job, quiet bool) {
|
||||
s.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
s.logger.Printf("[WARN] Job %s failed: %v (took %s)", job.Name, err, elapsed.Round(time.Millisecond))
|
||||
s.logger.Printf("[ERROR] [scheduler] Job %s failed: %v (took %s)", job.Name, err, elapsed.Round(time.Millisecond))
|
||||
s.dbg("job %s: failed after %s: %v", job.Name, elapsed.Round(time.Millisecond), err)
|
||||
} else if !quiet {
|
||||
s.logger.Printf("[SCHED] Job %s completed (took %s)", job.Name, elapsed.Round(time.Millisecond))
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user