57 lines
1.1 KiB
Go
57 lines
1.1 KiB
Go
|
package stati
|
||
|
|
||
|
import (
|
||
|
"math"
|
||
|
|
||
|
"golang.org/x/xerrors"
|
||
|
)
|
||
|
|
||
|
type Histogram struct {
|
||
|
Buckets []float64
|
||
|
Counts []uint64
|
||
|
}
|
||
|
|
||
|
// NewHistogram creates a histograme with buckets defined as:
|
||
|
// {x > -Inf, x >= buckets[0], x >= buckets[1], ..., x >= buckets[i]}
|
||
|
func NewHistogram(buckets []float64) (*Histogram, error) {
|
||
|
if len(buckets) == 0 {
|
||
|
return nil, xerrors.Errorf("empty buckets")
|
||
|
}
|
||
|
prev := buckets[0]
|
||
|
for i, v := range buckets[1:] {
|
||
|
if v < prev {
|
||
|
return nil, xerrors.Errorf("bucket at index %d is smaller than previous %f < %f", i+1, v, prev)
|
||
|
}
|
||
|
prev = v
|
||
|
}
|
||
|
h := &Histogram{
|
||
|
Buckets: append([]float64{math.Inf(-1)}, buckets...),
|
||
|
Counts: make([]uint64, len(buckets)+1),
|
||
|
}
|
||
|
return h, nil
|
||
|
}
|
||
|
|
||
|
func (h *Histogram) Observe(x float64) {
|
||
|
for i, b := range h.Buckets {
|
||
|
if x >= b {
|
||
|
h.Counts[i]++
|
||
|
} else {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (h *Histogram) Total() uint64 {
|
||
|
return h.Counts[0]
|
||
|
}
|
||
|
|
||
|
func (h *Histogram) Get(i int) uint64 {
|
||
|
if i >= len(h.Counts)-2 {
|
||
|
return h.Counts[i]
|
||
|
}
|
||
|
return h.Counts[i+1] - h.Counts[i+2]
|
||
|
}
|
||
|
func (h *Histogram) GetRatio(i int) float64 {
|
||
|
return float64(h.Get(i)) / float64(h.Total())
|
||
|
}
|