package metrics import ( "sync" "time" ) // minuteCounter counts events in each clock minute and reports the count of // the last full minute. It is safe for concurrent use. type minuteCounter struct { mu sync.Mutex now func() time.Time // minute is the start of the minute that count belongs to. minute time.Time count int // lastMinuteCount is the count of the minute just before minute. lastMinuteCount int } // add counts one event in the current minute. func (c *minuteCounter) add() { c.mu.Lock() defer c.mu.Unlock() c.moveToCurrentMinute() c.count++ } // lastFullMinute returns the number of events in the minute that ended most // recently. func (c *minuteCounter) lastFullMinute() int { c.mu.Lock() defer c.mu.Unlock() c.moveToCurrentMinute() return c.lastMinuteCount } // moveToCurrentMinute starts a new count when the clock has moved into // another minute. The count it ends becomes the last full minute's count when // its minute is the one just before the current minute. Otherwise the last // full minute had no events. The caller holds mu. func (c *minuteCounter) moveToCurrentMinute() { minute := c.now().Truncate(time.Minute) if minute.Equal(c.minute) { return } if minute.Sub(c.minute) == time.Minute { c.lastMinuteCount = c.count } else { c.lastMinuteCount = 0 } c.minute = minute c.count = 0 }