mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-09 09:33:42 +00:00
5095efd628
Histogram buckets should include counts for all values under the bucket ceiling, not just those between the ceiling and the next lower ceiling. See https://prometheus.io/docs/tutorials/understanding_metric_types/\#histogram Updates tailscale/corp#24522 Signed-off-by: Percy Wegmann <percy@tailscale.com>
50 lines
1.2 KiB
Go
50 lines
1.2 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package prober
|
|
|
|
import (
|
|
"slices"
|
|
"sync"
|
|
)
|
|
|
|
// histogram serves as an adapter to the Prometheus histogram datatype.
|
|
// The prober framework passes labels at custom metric collection time that
|
|
// it expects to be coupled with the returned metrics. See ProbeClass.Metrics
|
|
// and its call sites. Native prometheus histograms cannot be collected while
|
|
// injecting more labels. Instead we use this type and pass observations +
|
|
// collection labels to prometheus.MustNewConstHistogram() at prometheus
|
|
// metric collection time.
|
|
type histogram struct {
|
|
count uint64
|
|
sum float64
|
|
buckets []float64
|
|
bucketedCounts map[float64]uint64
|
|
mx sync.Mutex
|
|
}
|
|
|
|
// newHistogram constructs a histogram that buckets data based on the given
|
|
// slice of upper bounds.
|
|
func newHistogram(buckets []float64) *histogram {
|
|
slices.Sort(buckets)
|
|
return &histogram{
|
|
buckets: buckets,
|
|
bucketedCounts: make(map[float64]uint64, len(buckets)),
|
|
}
|
|
}
|
|
|
|
func (h *histogram) add(v float64) {
|
|
h.mx.Lock()
|
|
defer h.mx.Unlock()
|
|
|
|
h.count++
|
|
h.sum += v
|
|
|
|
for _, b := range h.buckets {
|
|
if v > b {
|
|
continue
|
|
}
|
|
h.bucketedCounts[b] += 1
|
|
}
|
|
}
|