package main import ( "fmt" "sync" "time" ) type Stats struct { mu sync.Mutex day string jobs int refused int failed int tunnels int up int64 down int64 sentUp int64 sentDown int64 } func NewStats(now time.Time) *Stats { return &Stats{day: now.Format("2006-01-02")} } func (s *Stats) Job(up, down int64) { s.mu.Lock() s.jobs++ s.up += up s.down += down s.mu.Unlock() } func (s *Stats) Refused() { s.mu.Lock() s.refused++ s.mu.Unlock() } func (s *Stats) Failed() { s.mu.Lock() s.failed++ s.mu.Unlock() } func (s *Stats) Tunnel() { s.mu.Lock() s.tunnels++ s.mu.Unlock() } func (s *Stats) Bytes(up, down int64) { s.mu.Lock() s.up += up s.down += down s.mu.Unlock() } func (s *Stats) Take() (up, down int64) { s.mu.Lock() defer s.mu.Unlock() up, down = s.up-s.sentUp, s.down-s.sentDown s.sentUp, s.sentDown = s.up, s.down return } func (s *Stats) line() string { return fmt.Sprintf("totals day=%s jobs=%d refused=%d failed=%d tunnels=%d bytes_up=%d bytes_down=%d", s.day, s.jobs, s.refused, s.failed, s.tunnels, s.up, s.down) } func (s *Stats) Line() string { s.mu.Lock() defer s.mu.Unlock() return s.line() } func (s *Stats) Roll(now time.Time) string { s.mu.Lock() defer s.mu.Unlock() today := now.Format("2006-01-02") if today == s.day { return "" } line := s.line() s.day = today s.jobs, s.refused, s.failed, s.tunnels = 0, 0, 0, 0 s.up, s.down, s.sentUp, s.sentDown = 0, 0, 0, 0 return line }