package internal import ( "sync/atomic" "time" "github.com/tal-tech/go-zero/core/logx" ) const statInterval = time.Minute type CacheStat struct { name string // export the fields to let the unit tests working, // reside in internal package, doesn't matter. Total uint64 Hit uint64 Miss uint64 DbFails uint64 } func NewCacheStat(name string) *CacheStat { ret := &CacheStat{ name: name, } go ret.statLoop() return ret } func (cs *CacheStat) IncrementTotal() { atomic.AddUint64(&cs.Total, 1) } func (cs *CacheStat) IncrementHit() { atomic.AddUint64(&cs.Hit, 1) } func (cs *CacheStat) IncrementMiss() { atomic.AddUint64(&cs.Miss, 1) } func (cs *CacheStat) IncrementDbFails() { atomic.AddUint64(&cs.DbFails, 1) } func (cs *CacheStat) statLoop() { ticker := time.NewTicker(statInterval) defer ticker.Stop() for { select { case <-ticker.C: total := atomic.SwapUint64(&cs.Total, 0) if total == 0 { continue } hit := atomic.SwapUint64(&cs.Hit, 0) percent := 100 * float32(hit) / float32(total) miss := atomic.SwapUint64(&cs.Miss, 0) dbf := atomic.SwapUint64(&cs.DbFails, 0) logx.Statf("dbcache(%s) - qpm: %d, hit_ratio: %.1f%%, hit: %d, miss: %d, db_fails: %d", cs.name, total, percent, hit, miss, dbf) } } }