Files
query-orchestration/internal/backgroundtask/stats.go
T
2025-08-12 06:37:16 -07:00

174 lines
5.2 KiB
Go

package backgroundtask
import (
"fmt"
"io"
"sync"
"sync/atomic"
"time"
)
// Stats provides observability into the runner's operation.
// All methods are thread-safe and can be called concurrently.
type Stats struct {
mu sync.RWMutex
workCycles atomic.Int64 // Total number of work cycles completed
lastStart time.Time // Time when the last work cycle started
lastFinish time.Time // Time when the last work cycle finished
lastErr error // Last error returned from work function
maxConcurrent atomic.Int32 // Maximum concurrent work attempts (should always be 1)
currentConcurrent atomic.Int32 // Current concurrent work executions
}
// WorkCycles returns the total number of work cycles completed.
func (s *Stats) WorkCycles() int64 {
return s.workCycles.Load()
}
// LastStart returns the time when the last work cycle started.
func (s *Stats) LastStart() time.Time {
s.mu.RLock()
defer s.mu.RUnlock()
return s.lastStart
}
// LastFinish returns the time when the last work cycle finished.
func (s *Stats) LastFinish() time.Time {
s.mu.RLock()
defer s.mu.RUnlock()
return s.lastFinish
}
// LastErr returns the last error returned from the work function.
func (s *Stats) LastErr() error {
s.mu.RLock()
defer s.mu.RUnlock()
return s.lastErr
}
// MaxConcurrent returns the maximum number of concurrent work executions observed.
// This should always be 1 if the runner is working correctly.
func (s *Stats) MaxConcurrent() int32 {
return s.maxConcurrent.Load()
}
// CurrentConcurrent returns the current number of concurrent work executions.
// This should be 0 or 1.
func (s *Stats) CurrentConcurrent() int32 {
return s.currentConcurrent.Load()
}
// incrementWorkCycles increments the work cycle counter.
func (s *Stats) incrementWorkCycles() {
s.workCycles.Add(1)
}
// setLastStart updates the last start time.
func (s *Stats) setLastStart(t time.Time) {
s.mu.Lock()
defer s.mu.Unlock()
s.lastStart = t
}
// setLastFinish updates the last finish time.
func (s *Stats) setLastFinish(t time.Time) {
s.mu.Lock()
defer s.mu.Unlock()
s.lastFinish = t
}
// setLastErr updates the last error.
func (s *Stats) setLastErr(err error) {
s.mu.Lock()
defer s.mu.Unlock()
s.lastErr = err
}
// enterWork marks the beginning of a work cycle and tracks concurrency.
func (s *Stats) enterWork() {
current := s.currentConcurrent.Add(1)
// Update max concurrent if needed
for {
max := s.maxConcurrent.Load()
if current <= max {
break
}
if s.maxConcurrent.CompareAndSwap(max, current) {
break
}
}
}
// exitWork marks the end of a work cycle.
func (s *Stats) exitWork() {
s.currentConcurrent.Add(-1)
}
// Reset clears all statistics. Used primarily for testing.
func (s *Stats) Reset() {
s.mu.Lock()
defer s.mu.Unlock()
s.workCycles.Store(0)
s.lastStart = time.Time{}
s.lastFinish = time.Time{}
s.lastErr = nil
s.maxConcurrent.Store(0)
s.currentConcurrent.Store(0)
}
// Print writes a formatted representation of all statistics to the provided writer.
// The output includes work cycles, timing information, error status, and concurrency metrics.
func (s *Stats) Print(w io.Writer) {
s.mu.RLock()
lastStart := s.lastStart
lastFinish := s.lastFinish
lastErr := s.lastErr
s.mu.RUnlock()
workCycles := s.workCycles.Load()
maxConcurrent := s.maxConcurrent.Load()
currentConcurrent := s.currentConcurrent.Load()
fmt.Fprintf(w, "╭─────────────────────────────────────────────╮\n")
fmt.Fprintf(w, "│ Background Task Runner Stats │\n")
fmt.Fprintf(w, "├─────────────────────────────────────────────┤\n")
fmt.Fprintf(w, "│ Work Cycles: %-23d │\n", workCycles)
fmt.Fprintf(w, "│ Current Concurrent: %-23d │\n", currentConcurrent)
fmt.Fprintf(w, "│ Max Concurrent: %-23d │\n", maxConcurrent)
fmt.Fprintf(w, "├─────────────────────────────────────────────┤\n")
// Format timing information
if !lastStart.IsZero() {
fmt.Fprintf(w, "│ Last Start: %-30s │\n", lastStart.Format("2006-01-02 15:04:05.000"))
} else {
fmt.Fprintf(w, "│ Last Start: %-30s │\n", "Never")
}
if !lastFinish.IsZero() {
fmt.Fprintf(w, "│ Last Finish: %-30s │\n", lastFinish.Format("2006-01-02 15:04:05.000"))
if !lastStart.IsZero() {
duration := lastFinish.Sub(lastStart)
fmt.Fprintf(w, "│ Duration: %-30s │\n", duration.String())
}
} else {
fmt.Fprintf(w, "│ Last Finish: %-30s │\n", "Never")
}
fmt.Fprintf(w, "├─────────────────────────────────────────────┤\n")
// Format error information
if lastErr != nil {
errStr := lastErr.Error()
if len(errStr) > 30 {
errStr = errStr[:27] + "..."
}
fmt.Fprintf(w, "│ Last Error: %-30s │\n", errStr)
} else {
fmt.Fprintf(w, "│ Last Error: %-30s │\n", "None")
}
fmt.Fprintf(w, "╰─────────────────────────────────────────────╯\n")
}