123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package metrics
- import (
- "sort"
- "time"
- )
- var (
- _ DurationBuckets = (*durationBuckets)(nil)
- _ Buckets = (*buckets)(nil)
- )
- const (
- errBucketsCountNeedsGreaterThanZero = "n needs to be > 0"
- errBucketsStartNeedsGreaterThanZero = "start needs to be > 0"
- errBucketsFactorNeedsGreaterThanOne = "factor needs to be > 1"
- )
- type durationBuckets struct {
- buckets []time.Duration
- }
- // NewDurationBuckets returns new DurationBuckets implementation.
- func NewDurationBuckets(bk ...time.Duration) DurationBuckets {
- sort.Slice(bk, func(i, j int) bool {
- return bk[i] < bk[j]
- })
- return durationBuckets{buckets: bk}
- }
- func (d durationBuckets) Size() int {
- return len(d.buckets)
- }
- func (d durationBuckets) MapDuration(dv time.Duration) (idx int) {
- for _, bound := range d.buckets {
- if dv < bound {
- break
- }
- idx++
- }
- return
- }
- func (d durationBuckets) UpperBound(idx int) time.Duration {
- if idx > d.Size()-1 {
- panic("idx is out of bounds")
- }
- return d.buckets[idx]
- }
- type buckets struct {
- buckets []float64
- }
- // NewBuckets returns new Buckets implementation.
- func NewBuckets(bk ...float64) Buckets {
- sort.Slice(bk, func(i, j int) bool {
- return bk[i] < bk[j]
- })
- return buckets{buckets: bk}
- }
- func (d buckets) Size() int {
- return len(d.buckets)
- }
- func (d buckets) MapValue(v float64) (idx int) {
- for _, bound := range d.buckets {
- if v < bound {
- break
- }
- idx++
- }
- return
- }
- func (d buckets) UpperBound(idx int) float64 {
- if idx > d.Size()-1 {
- panic("idx is out of bounds")
- }
- return d.buckets[idx]
- }
- // MakeLinearBuckets creates a set of linear value buckets.
- func MakeLinearBuckets(start, width float64, n int) Buckets {
- if n <= 0 {
- panic(errBucketsCountNeedsGreaterThanZero)
- }
- bounds := make([]float64, n)
- for i := range bounds {
- bounds[i] = start + (float64(i) * width)
- }
- return NewBuckets(bounds...)
- }
- // MakeLinearDurationBuckets creates a set of linear duration buckets.
- func MakeLinearDurationBuckets(start, width time.Duration, n int) DurationBuckets {
- if n <= 0 {
- panic(errBucketsCountNeedsGreaterThanZero)
- }
- buckets := make([]time.Duration, n)
- for i := range buckets {
- buckets[i] = start + (time.Duration(i) * width)
- }
- return NewDurationBuckets(buckets...)
- }
- // MakeExponentialBuckets creates a set of exponential value buckets.
- func MakeExponentialBuckets(start, factor float64, n int) Buckets {
- if n <= 0 {
- panic(errBucketsCountNeedsGreaterThanZero)
- }
- if start <= 0 {
- panic(errBucketsStartNeedsGreaterThanZero)
- }
- if factor <= 1 {
- panic(errBucketsFactorNeedsGreaterThanOne)
- }
- buckets := make([]float64, n)
- curr := start
- for i := range buckets {
- buckets[i] = curr
- curr *= factor
- }
- return NewBuckets(buckets...)
- }
- // MakeExponentialDurationBuckets creates a set of exponential duration buckets.
- func MakeExponentialDurationBuckets(start time.Duration, factor float64, n int) DurationBuckets {
- if n <= 0 {
- panic(errBucketsCountNeedsGreaterThanZero)
- }
- if start <= 0 {
- panic(errBucketsStartNeedsGreaterThanZero)
- }
- if factor <= 1 {
- panic(errBucketsFactorNeedsGreaterThanOne)
- }
- buckets := make([]time.Duration, n)
- curr := start
- for i := range buckets {
- buckets[i] = curr
- curr = time.Duration(float64(curr) * factor)
- }
- return NewDurationBuckets(buckets...)
- }
|