func (h *Histogram) Buckets() []int64 {
	buckets := make([]int64, len(h.buckets))
	for i := range h.buckets {
		buckets[i] = h.buckets[i].Get()
	}
	return buckets
}
Buckets returns a snapshot of the current values in all buckets.
package stats
import (
	"bytes"
	"fmt"
	"xbase/sync2"
)
type Histogram struct {
	cutoffs    []int64
	labels     []string
	countLabel string
	totalLabel string
	hook       func(int64)
	buckets []sync2.AtomicInt64
	total   sync2.AtomicInt64
}
func NewHistogram(name string, cutoffs []int64) *Histogram {
	labels := make([]string, len(cutoffs)+1)
	for i, v := range cutoffs {
		labels[i] = fmt.Sprintf("%d", v)
	}
	labels[len(labels)-1] = "inf"
	return NewGenericHistogram(name, cutoffs, labels, "Count", "Total")
}
func NewGenericHistogram(name string, cutoffs []int64, labels []string, countLabel, totalLabel string) *Histogram {
	if len(cutoffs) != len(labels)-1 {
		panic("mismatched cutoff and label lengths")
	}
	h := &Histogram{
		cutoffs:    cutoffs,
		labels:     labels,
		countLabel: countLabel,
		totalLabel: totalLabel,
		buckets:    make([]sync2.AtomicInt64, len(labels)),
	}
	if name != "" {
		publish(name, h)
	}
	return h
}
func (h *Histogram) Add(value int64) {
	for i := range h.labels {
		if i == len(h.labels)-1 || value <= h.cutoffs[i] {
			h.buckets[i].Add(1)
			h.total.Add(value)
			break
		}
	}
	if h.hook != nil {
		h.hook(value)
	}
}
func (h *Histogram) String() string {
	b, _ := h.MarshalJSON()
	return string(b)
}
func (h *Histogram) MarshalJSON() ([]byte, error) {
	b := bytes.NewBuffer(make([]byte, 0, 4096))
	fmt.Fprintf(b, "{")
	totalCount := int64(0)
	for i, label := range h.labels {
		totalCount += h.buckets[i].Get()
		fmt.Fprintf(b, "\"%v\": %v, ", label, totalCount)
	}
	fmt.Fprintf(b, "\"%s\": %v, ", h.countLabel, totalCount)
	fmt.Fprintf(b, "\"%s\": %v", h.totalLabel, h.total.Get())
	fmt.Fprintf(b, "}")
	return b.Bytes(), nil
}
func (h *Histogram) Counts() map[string]int64 {
	counts := make(map[string]int64, len(h.labels))
	for i, label := range h.labels {
		counts[label] = h.buckets[i].Get()
	}
	return counts
}
func (h *Histogram) CountLabel() string {
	return h.countLabel
}
func (h *Histogram) Count() (count int64) {
	for i := range h.buckets {
		count += h.buckets[i].Get()
	}
	return
}
func (h *Histogram) TotalLabel() string {
	return h.totalLabel
}
func (h *Histogram) Total() (total int64) {
	return h.total.Get()
}
func (h *Histogram) Labels() []string {
	return h.labels
}
func (h *Histogram) Cutoffs() []int64 {
	return h.cutoffs
}