package counters import ( "database/sql" "runtime" "sync" "time" c "github.com/Azareal/Gosora/common" qgen "github.com/Azareal/Gosora/query_gen" "github.com/pkg/errors" ) var MemoryCounter *DefaultMemoryCounter type DefaultMemoryCounter struct { insert *sql.Stmt totMem uint64 totCount uint64 stackMem uint64 stackCount uint64 heapMem uint64 heapCount uint64 sync.Mutex } func NewMemoryCounter(acc *qgen.Accumulator) (*DefaultMemoryCounter, error) { co := &DefaultMemoryCounter{ insert: acc.Insert("memchunks").Columns("count,stack,heap,createdAt").Fields("?,?,?,UTC_TIMESTAMP()").Prepare(), } c.AddScheduledFifteenMinuteTask(co.Tick) //c.AddScheduledSecondTask(co.Tick) c.AddShutdownTask(co.Tick) ticker := time.NewTicker(time.Minute) go func() { for { select { case <-ticker.C: var m runtime.MemStats runtime.ReadMemStats(&m) co.Lock() co.totCount++ co.totMem += m.Sys co.stackCount++ co.stackMem += m.StackInuse co.heapCount++ co.heapMem += m.HeapAlloc co.Unlock() } } }() return co, acc.FirstError() } func (co *DefaultMemoryCounter) Tick() (err error) { var m runtime.MemStats runtime.ReadMemStats(&m) var rTotMem, rTotCount, rStackMem, rStackCount, rHeapMem, rHeapCount uint64 co.Lock() rTotMem = co.totMem rTotCount = co.totCount rStackMem = co.stackMem rStackCount = co.stackCount rHeapMem = co.heapMem rHeapCount = co.heapCount co.totMem = 0 co.totCount = 0 co.stackMem = 0 co.stackCount = 0 co.heapMem = 0 co.heapCount = 0 co.Unlock() var avgMem, avgStack, avgHeap uint64 avgMem = (rTotMem + m.Sys) / (rTotCount + 1) avgStack = (rStackMem + m.StackInuse) / (rStackCount + 1) avgHeap = (rHeapMem + m.HeapAlloc) / (rHeapCount + 1) c.DebugLogf("Inserting a memchunk with a value of %d - %d - %d", avgMem, avgStack, avgHeap) _, err = co.insert.Exec(avgMem, avgStack, avgHeap) if err != nil { return errors.Wrap(errors.WithStack(err), "mem counter") } return nil }