Skip to content
This repository has been archived by the owner on Aug 23, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1706 from grafana/stats-with-tags
Browse files Browse the repository at this point in the history
Additional stats refactoring to support tags
  • Loading branch information
Dieterbe authored Mar 5, 2020
2 parents b7de5a9 + e7eb223 commit 9f7d34b
Show file tree
Hide file tree
Showing 16 changed files with 153 additions and 100 deletions.
12 changes: 8 additions & 4 deletions stats/bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import (
)

type Bool struct {
val uint32
val uint32
name []byte
tags []byte
}

func NewBool(name string) *Bool {
return registry.getOrAdd(name, &Bool{}).(*Bool)
return registry.getOrAdd(name, &Bool{
name: []byte(name),
}).(*Bool)
}

func (b *Bool) SetTrue() {
Expand All @@ -36,8 +40,8 @@ func (b *Bool) Peek() bool {
return true
}

func (b *Bool) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (b *Bool) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
val := atomic.LoadUint32(&b.val)
buf = WriteUint32(buf, prefix, []byte("gauge1"), val, now)
buf = WriteUint32(buf, prefix, b.name, []byte(".gauge1"), b.tags, val, now)
return buf
}
12 changes: 8 additions & 4 deletions stats/counter32.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import (
)

type Counter32 struct {
val uint32
val uint32
name []byte
tags []byte
}

func NewCounter32(name string) *Counter32 {
return registry.getOrAdd(name, &Counter32{}).(*Counter32)
return registry.getOrAdd(name, &Counter32{
name: []byte(name),
}).(*Counter32)
}

func (c *Counter32) SetUint32(val uint32) {
Expand All @@ -33,8 +37,8 @@ func (c *Counter32) Peek() uint32 {
return atomic.LoadUint32(&c.val)
}

func (c *Counter32) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (c *Counter32) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
val := atomic.LoadUint32(&c.val)
buf = WriteUint32(buf, prefix, []byte("counter32"), val, now)
buf = WriteUint32(buf, prefix, c.name, []byte(".counter32"), c.tags, val, now)
return buf
}
12 changes: 8 additions & 4 deletions stats/counter64.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import (
)

type Counter64 struct {
val uint64
val uint64
name []byte
tags []byte
}

func NewCounter64(name string) *Counter64 {
return registry.getOrAdd(name, &Counter64{}).(*Counter64)
return registry.getOrAdd(name, &Counter64{
name: []byte(name),
}).(*Counter64)
}

func (c *Counter64) SetUint64(val uint64) {
Expand All @@ -25,8 +29,8 @@ func (c *Counter64) AddUint64(val uint64) {
atomic.AddUint64(&c.val, val)
}

func (c *Counter64) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (c *Counter64) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
val := atomic.LoadUint64(&c.val)
buf = WriteUint64(buf, prefix, []byte("counter64"), val, now)
buf = WriteUint64(buf, prefix, c.name, []byte(".counter64"), c.tags, val, now)
return buf
}
9 changes: 6 additions & 3 deletions stats/counterrate32.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ type CounterRate32 struct {
prev uint32
val uint32
since time.Time
name []byte
tags []byte
}

func NewCounterRate32(name string) *CounterRate32 {
c := CounterRate32{
since: time.Now(),
name: []byte(name),
}
return registry.getOrAdd(name, &c).(*CounterRate32)
}
Expand All @@ -39,10 +42,10 @@ func (c *CounterRate32) Peek() uint32 {
return atomic.LoadUint32(&c.val)
}

func (c *CounterRate32) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (c *CounterRate32) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
val := atomic.LoadUint32(&c.val)
buf = WriteUint32(buf, prefix, []byte("counter32"), val, now)
buf = WriteFloat64(buf, prefix, []byte("rate32"), float64(val-c.prev)/now.Sub(c.since).Seconds(), now)
buf = WriteUint32(buf, prefix, c.name, []byte(".counter32"), c.tags, val, now)
buf = WriteFloat64(buf, prefix, c.name, []byte(".rate32"), c.tags, float64(val-c.prev)/now.Sub(c.since).Seconds(), now)

c.prev = val
c.since = now
Expand Down
12 changes: 8 additions & 4 deletions stats/gauge32.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import (
)

type Gauge32 struct {
val uint32
val uint32
name []byte
tags []byte
}

func NewGauge32(name string) *Gauge32 {
return registry.getOrAdd(name, &Gauge32{}).(*Gauge32)
return registry.getOrAdd(name, &Gauge32{
name: []byte(name),
}).(*Gauge32)
}

func (g *Gauge32) Inc() {
Expand Down Expand Up @@ -49,8 +53,8 @@ func (g *Gauge32) SetUint32(val uint32) {
atomic.StoreUint32(&g.val, val)
}

func (g *Gauge32) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (g *Gauge32) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
val := atomic.LoadUint32(&g.val)
buf = WriteUint32(buf, prefix, []byte("gauge32"), val, now)
buf = WriteUint32(buf, prefix, g.name, []byte(".gauge32"), g.tags, val, now)
return buf
}
31 changes: 18 additions & 13 deletions stats/gauge64.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,32 @@ import (
"time"
)

type Gauge64 uint64
type Gauge64 struct {
val uint64
name []byte
tags []byte
}

func NewGauge64(name string) *Gauge64 {
u := Gauge64(0)
return registry.getOrAdd(name, &u).(*Gauge64)
return registry.getOrAdd(name, &Gauge64{
name: []byte(name),
}).(*Gauge64)
}

func (g *Gauge64) Inc() {
atomic.AddUint64((*uint64)(g), 1)
atomic.AddUint64(&g.val, 1)
}

func (g *Gauge64) Dec() {
atomic.AddUint64((*uint64)(g), ^uint64(0))
atomic.AddUint64(&g.val, ^uint64(0))
}

func (g *Gauge64) AddUint64(val uint64) {
atomic.AddUint64((*uint64)(g), val)
atomic.AddUint64(&g.val, val)
}

func (g *Gauge64) DecUint64(val uint64) {
atomic.AddUint64((*uint64)(g), ^uint64(val-1))
atomic.AddUint64(&g.val, ^uint64(val-1))
}

func (g *Gauge64) Add(val int) {
Expand All @@ -41,19 +46,19 @@ func (g *Gauge64) Add(val int) {
}

func (g *Gauge64) Set(val int) {
atomic.StoreUint64((*uint64)(g), uint64(val))
atomic.StoreUint64(&g.val, uint64(val))
}

func (g *Gauge64) SetUint64(val uint64) {
atomic.StoreUint64((*uint64)(g), val)
atomic.StoreUint64(&g.val, val)
}

func (g *Gauge64) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
val := atomic.LoadUint64((*uint64)(g))
buf = WriteUint64(buf, prefix, []byte("gauge64"), val, now)
func (g *Gauge64) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
val := atomic.LoadUint64(&g.val)
buf = WriteUint64(buf, prefix, g.name, []byte(".gauge64"), g.tags, val, now)
return buf
}

func (g *Gauge64) Peek() uint64 {
return atomic.LoadUint64((*uint64)(g))
return atomic.LoadUint64(&g.val)
}
21 changes: 12 additions & 9 deletions stats/latencyhistogram12h32.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ import (
type LatencyHistogram12h32 struct {
hist hist12h.Hist12h
since time.Time
name []byte
tags []byte
}

func NewLatencyHistogram12h32(name string) *LatencyHistogram12h32 {
return registry.getOrAdd(name, &LatencyHistogram12h32{
hist: hist12h.New(),
since: time.Now(),
name: []byte(name),
},
).(*LatencyHistogram12h32)
}
Expand All @@ -24,21 +27,21 @@ func (l *LatencyHistogram12h32) Value(t time.Duration) {
l.hist.AddDuration(t)
}

func (l *LatencyHistogram12h32) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (l *LatencyHistogram12h32) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
snap := l.hist.Snapshot()
// TODO: once we can actually do cool stuff (e.g. visualize) histogram bucket data, report it
// for now, only report the summaries :(
r, ok := l.hist.Report(snap)
if ok {
buf = WriteUint32(buf, prefix, []byte("latency.min.gauge32"), r.Min/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.mean.gauge32"), r.Mean/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.median.gauge32"), r.Median/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.p75.gauge32"), r.P75/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.p90.gauge32"), r.P90/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.max.gauge32"), r.Max/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.min.gauge32"), l.tags, r.Min/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.mean.gauge32"), l.tags, r.Mean/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.median.gauge32"), l.tags, r.Median/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.p75.gauge32"), l.tags, r.P75/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.p90.gauge32"), l.tags, r.P90/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.max.gauge32"), l.tags, r.Max/1000, now)
}
buf = WriteUint32(buf, prefix, []byte("values.count32"), r.Count, now)
buf = WriteFloat64(buf, prefix, []byte("values.rate32"), float64(r.Count)/now.Sub(l.since).Seconds(), now)
buf = WriteUint32(buf, prefix, l.name, []byte(".values.count32"), l.tags, r.Count, now)
buf = WriteFloat64(buf, prefix, l.name, []byte(".values.rate32"), l.tags, float64(r.Count)/now.Sub(l.since).Seconds(), now)
l.since = now
return buf
}
21 changes: 12 additions & 9 deletions stats/latencyhistogram15s32.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ type LatencyHistogram15s32 struct {
hist hist15s.Hist15s
since time.Time
sum uint64 // in micros. to generate more accurate mean
name []byte
tags []byte
}

func NewLatencyHistogram15s32(name string) *LatencyHistogram15s32 {
return registry.getOrAdd(name, &LatencyHistogram15s32{
hist: hist15s.New(),
since: time.Now(),
name: []byte(name),
},
).(*LatencyHistogram15s32)
}
Expand All @@ -27,22 +30,22 @@ func (l *LatencyHistogram15s32) Value(t time.Duration) {
l.hist.AddDuration(t)
}

func (l *LatencyHistogram15s32) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (l *LatencyHistogram15s32) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
snap := l.hist.Snapshot()
// TODO: once we can actually do cool stuff (e.g. visualize) histogram bucket data, report it
// for now, only report the summaries :(
r, ok := l.hist.Report(snap)
if ok {
sum := atomic.SwapUint64(&l.sum, 0)
buf = WriteUint32(buf, prefix, []byte("latency.min.gauge32"), r.Min/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.mean.gauge32"), uint32((sum / uint64(r.Count) / 1000)), now)
buf = WriteUint32(buf, prefix, []byte("latency.median.gauge32"), r.Median/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.p75.gauge32"), r.P75/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.p90.gauge32"), r.P90/1000, now)
buf = WriteUint32(buf, prefix, []byte("latency.max.gauge32"), r.Max/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.min.gauge32"), l.tags, r.Min/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.mean.gauge32"), l.tags, uint32((sum / uint64(r.Count) / 1000)), now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.median.gauge32"), l.tags, r.Median/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.p75.gauge32"), l.tags, r.P75/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.p90.gauge32"), l.tags, r.P90/1000, now)
buf = WriteUint32(buf, prefix, l.name, []byte(".latency.max.gauge32"), l.tags, r.Max/1000, now)
}
buf = WriteUint32(buf, prefix, []byte("values.count32"), r.Count, now)
buf = WriteFloat64(buf, prefix, []byte("values.rate32"), float64(r.Count)/now.Sub(l.since).Seconds(), now)
buf = WriteUint32(buf, prefix, l.name, []byte(".values.count32"), l.tags, r.Count, now)
buf = WriteFloat64(buf, prefix, l.name, []byte(".values.rate32"), l.tags, float64(r.Count)/now.Sub(l.since).Seconds(), now)

l.since = now
return buf
Expand Down
18 changes: 9 additions & 9 deletions stats/memory_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,37 +45,37 @@ func getGcPercent() int {
return val
}

func (m *MemoryReporter) ReportGraphite(buf, prefix []byte, now time.Time) []byte {
func (m *MemoryReporter) WriteGraphiteLine(buf, prefix []byte, now time.Time) []byte {
m.mem = m.timeBoundGetMemStats().(runtime.MemStats)
gcPercent := getGcPercent()

// metric memory.total_bytes_allocated is a counter of total number of bytes allocated during process lifetime
buf = WriteUint64(buf, prefix, []byte("total_bytes_allocated.counter64"), m.mem.TotalAlloc, now)
buf = WriteUint64(buf, prefix, []byte("total_bytes_allocated.counter64"), nil, nil, m.mem.TotalAlloc, now)

// metric memory.bytes_allocated_on_heap is a gauge of currently allocated (within the runtime) memory.
buf = WriteUint64(buf, prefix, []byte("bytes.allocated_in_heap.gauge64"), m.mem.Alloc, now)
buf = WriteUint64(buf, prefix, []byte("bytes.allocated_in_heap.gauge64"), nil, nil, m.mem.Alloc, now)

// metric memory.bytes.obtained_from_sys is the number of bytes currently obtained from the system by the process. This is what the profiletrigger looks at.
buf = WriteUint64(buf, prefix, []byte("bytes.obtained_from_sys.gauge64"), m.mem.Sys, now)
buf = WriteUint64(buf, prefix, []byte("bytes.obtained_from_sys.gauge64"), nil, nil, m.mem.Sys, now)

// metric memory.total_gc_cycles is a counter of the number of GC cycles since process start
buf = WriteUint32(buf, prefix, []byte("total_gc_cycles.counter64"), m.mem.NumGC, now)
buf = WriteUint32(buf, prefix, []byte("total_gc_cycles.counter64"), nil, nil, m.mem.NumGC, now)

// metric memory.gc.cpu_fraction is how much cpu is consumed by the GC across process lifetime, in pro-mille
buf = WriteUint32(buf, prefix, []byte("gc.cpu_fraction.gauge32"), uint32(1000*m.mem.GCCPUFraction), now)
buf = WriteUint32(buf, prefix, []byte("gc.cpu_fraction.gauge32"), nil, nil, uint32(1000*m.mem.GCCPUFraction), now)

// metric memory.gc.heap_objects is how many objects are allocated on the heap, it's a key indicator for GC workload
buf = WriteUint64(buf, prefix, []byte("gc.heap_objects.gauge64"), m.mem.HeapObjects, now)
buf = WriteUint64(buf, prefix, []byte("gc.heap_objects.gauge64"), nil, nil, m.mem.HeapObjects, now)

// there was no new GC run, we should only report points to represent actual runs
if m.gcCyclesTotal != m.mem.NumGC {
// metric memory.gc.last_duration is the duration of the last GC STW pause in nanoseconds
buf = WriteUint64(buf, prefix, []byte("gc.last_duration.gauge64"), m.mem.PauseNs[(m.mem.NumGC+255)%256], now)
buf = WriteUint64(buf, prefix, []byte("gc.last_duration.gauge64"), nil, nil, m.mem.PauseNs[(m.mem.NumGC+255)%256], now)
m.gcCyclesTotal = m.mem.NumGC
}

// metric memory.gc.gogc is the current GOGC value (derived from the GOGC environment variable)
buf = WriteInt32(buf, prefix, []byte("gc.gogc.sgauge32"), int32(gcPercent), now)
buf = WriteInt32(buf, prefix, []byte("gc.gogc.sgauge32"), nil, nil, int32(gcPercent), now)

return buf
}
Loading

0 comments on commit 9f7d34b

Please sign in to comment.