categraf/inputs/mtail/internal/metrics/datum/buckets.go

118 lines
1.8 KiB
Go

// Copyright 2017 Google Inc. All Rights Reserved.
// This file is available under the Apache license.
package datum
import (
"encoding/json"
"fmt"
"strconv"
"sync"
"sync/atomic"
"time"
)
type Range struct {
Min float64
Max float64
}
type BucketCount struct {
Range Range
Count uint64
}
func (r *Range) Contains(v float64) bool {
return r.Min < v && v <= r.Max
}
// Buckets describes a floating point value at a given timestamp.
type Buckets struct {
BaseDatum
sync.RWMutex
Buckets []BucketCount
Count uint64
Sum float64
}
func (d *Buckets) ValueString() string {
return fmt.Sprintf("%g", d.GetSum())
}
func (d *Buckets) Observe(v float64, ts time.Time) {
d.Lock()
defer d.Unlock()
for i, b := range d.Buckets {
if b.Range.Contains(v) {
d.Buckets[i].Count++
break
}
}
d.Count++
d.Sum += v
d.stamp(ts)
}
func (d *Buckets) GetCount() uint64 {
d.RLock()
defer d.RUnlock()
return d.Count
}
func (d *Buckets) GetSum() float64 {
d.RLock()
defer d.RUnlock()
return d.Sum
}
func (d *Buckets) AddBucket(r Range) {
d.Lock()
defer d.Unlock()
d.Buckets = append(d.Buckets, BucketCount{r, 0})
}
func (d *Buckets) GetBuckets() map[Range]uint64 {
d.RLock()
defer d.RUnlock()
b := make(map[Range]uint64)
for _, bc := range d.Buckets {
b[bc.Range] = bc.Count
}
return b
}
func (d *Buckets) MarshalJSON() ([]byte, error) {
d.RLock()
defer d.RUnlock()
bs := make(map[string]uint64)
for _, b := range d.Buckets {
bs[strconv.FormatFloat(b.Range.Max, 'g', -1, 64)] = b.Count
}
j := struct {
Buckets map[string]uint64
Count uint64
Sum float64
Time int64
}{bs, d.Count, d.Sum, atomic.LoadInt64(&d.Time)}
return json.Marshal(j)
}
func (r *Range) MarshalJSON() ([]byte, error) {
j := struct {
Min string
Max string
}{fmt.Sprintf("%v", r.Min), fmt.Sprintf("%v", r.Max)}
return json.Marshal(j)
}