func (w *Window) Total() (total int64) {
	w.m.RLock()
	defer w.m.RUnlock()
	w.ring.Do(func(i interface{}) {
		if b, ok := i.(*bucket); ok {
			total += b.Total()
		}
	})
	return total
}
Return the total number of access (failures, success and short-circuit).
package circuitry
import (
	"container/ring"
	"errors"
	"sync"
	"sync/atomic"
	"time"
)
var ErrBucketSize = errors.New("bucket duration and size must divide equally")
type bucket struct {
	failures      int64
	successes     int64
	shortcircuits int64
}
func (b *bucket) MarkShortCircuited() {
	atomic.AddInt64(&b.shortcircuits, 1)
}
func (b *bucket) MarkSuccess() {
	atomic.AddInt64(&b.successes, 1)
}
func (b *bucket) MarkFailure() {
	atomic.AddInt64(&b.failures, 1)
}
func (b *bucket) Total() int64 {
	return b.Failures() + b.Successes() + b.ShortCircuited()
}
func (b *bucket) Errors() int64 {
	return b.Failures() + b.ShortCircuited()
}
func (b *bucket) Successes() int64 {
	return atomic.LoadInt64(&b.successes)
}
func (b *bucket) Failures() int64 {
	return atomic.LoadInt64(&b.failures)
}
func (b *bucket) ShortCircuited() int64 {
	return atomic.LoadInt64(&b.shortcircuits)
}
func (b *bucket) Reset() {
	atomic.StoreInt64(&b.failures, 0)
	atomic.StoreInt64(&b.successes, 0)
	atomic.StoreInt64(&b.shortcircuits, 0)
}
type Window struct {
	size int
	ring *ring.Ring
	m    sync.RWMutex
}
func NewWindow(n int, d time.Duration) (*Window, error) {
	if int(d.Nanoseconds())%n != 0 {
		return nil, ErrBucketSize
	}
	w := &Window{
		size: n,
		ring: seed(ring.New(n)),
	}
	go w.tick(time.Duration(int(d) / n))
	return w, nil
}
func (w *Window) tick(d time.Duration) {
	for _ = range time.Tick(d) {
		w.m.Lock()
		w.ring = rollup(w.ring)
		w.m.Unlock()
	}
}
func rollup(r *ring.Ring) *ring.Ring {
	n := r.Next()
	return seed(n)
}
func seed(r *ring.Ring) *ring.Ring {
	if r.Value == nil {
		r.Value = new(bucket)
	} else {
		r.Value.(*bucket).Reset()
	}
	return r
}
func (w *Window) markShortCircuited() {
	w.m.RLock()
	defer w.m.RUnlock()
	bucket := w.ring.Value.(*bucket)
	bucket.MarkShortCircuited()
}
func (w *Window) markSuccess() {
	w.m.RLock()
	defer w.m.RUnlock()
	bucket := w.ring.Value.(*bucket)
	bucket.MarkSuccess()
}
func (w *Window) markFailure() {
	w.m.RLock()
	defer w.m.RUnlock()
	bucket := w.ring.Value.(*bucket)
	bucket.MarkFailure()
}