var nativeHistogramBounds … type Histogram … const bucketLabel … var DefBuckets … const DefNativeHistogramZeroThreshold … const NativeHistogramZeroThresholdZero … var errBucketLabelNotAllowed … // LinearBuckets creates 'count' regular buckets, each 'width' wide, where the // lowest bucket has an upper bound of 'start'. The final +Inf bucket is not // counted and not included in the returned slice. The returned slice is meant // to be used for the Buckets field of HistogramOpts. // // The function panics if 'count' is zero or negative. func LinearBuckets(start, width float64, count int) []float64 { … } // ExponentialBuckets creates 'count' regular buckets, where the lowest bucket // has an upper bound of 'start' and each following bucket's upper bound is // 'factor' times the previous bucket's upper bound. The final +Inf bucket is // not counted and not included in the returned slice. The returned slice is // meant to be used for the Buckets field of HistogramOpts. // // The function panics if 'count' is 0 or negative, if 'start' is 0 or negative, // or if 'factor' is less than or equal 1. func ExponentialBuckets(start, factor float64, count int) []float64 { … } // ExponentialBucketsRange creates 'count' buckets, where the lowest bucket is // 'min' and the highest bucket is 'max'. The final +Inf bucket is not counted // and not included in the returned slice. The returned slice is meant to be // used for the Buckets field of HistogramOpts. // // The function panics if 'count' is 0 or negative, if 'min' is 0 or negative. func ExponentialBucketsRange(min, max float64, count int) []float64 { … } type HistogramOpts … type HistogramVecOpts … // NewHistogram creates a new Histogram based on the provided HistogramOpts. It // panics if the buckets in HistogramOpts are not in strictly increasing order. // // The returned implementation also implements ExemplarObserver. It is safe to // perform the corresponding type assertion. Exemplars are tracked separately // for each bucket. func NewHistogram(opts HistogramOpts) Histogram { … } func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram { … } type histogramCounts … // observe manages the parts of observe that only affects // histogramCounts. doSparse is true if sparse buckets should be done, // too. func (hc *histogramCounts) observe(v float64, bucket int, doSparse bool) { … } type histogram … func (h *histogram) Desc() *Desc { … } func (h *histogram) Observe(v float64) { … } func (h *histogram) ObserveWithExemplar(v float64, e Labels) { … } func (h *histogram) Write(out *dto.Metric) error { … } // findBucket returns the index of the bucket for the provided value, or // len(h.upperBounds) for the +Inf bucket. func (h *histogram) findBucket(v float64) int { … } // observe is the implementation for Observe without the findBucket part. func (h *histogram) observe(v float64, bucket int) { … } // limitBuckets applies a strategy to limit the number of populated sparse // buckets. It's generally best effort, and there are situations where the // number can go higher (if even the lowest resolution isn't enough to reduce // the number sufficiently, or if the provided counts aren't fully updated yet // by a concurrently happening Write call). func (h *histogram) limitBuckets(counts *histogramCounts, value float64, bucket int) { … } // maybeReset resets the whole histogram if at least // h.nativeHistogramMinResetDuration has been passed. It returns true if the // histogram has been reset. The caller must have locked h.mtx. func (h *histogram) maybeReset( hot, cold *histogramCounts, coldIdx uint64, value float64, bucket int, ) bool { … } // reset resets the whole histogram. It locks h.mtx itself, i.e. it has to be // called without having locked h.mtx. func (h *histogram) reset() { … } // maybeWidenZeroBucket widens the zero bucket until it includes the existing // buckets closest to the zero bucket (which could be two, if an equidistant // negative and a positive bucket exists, but usually it's only one bucket to be // merged into the new wider zero bucket). h.nativeHistogramMaxZeroThreshold // limits how far the zero bucket can be extended, and if that's not enough to // include an existing bucket, the method returns false. The caller must have // locked h.mtx. func (h *histogram) maybeWidenZeroBucket(hot, cold *histogramCounts) bool { … } // doubleBucketWidth doubles the bucket width (by decrementing the schema // number). Note that very sparse buckets could lead to a low reduction of the // bucket count (or even no reduction at all). The method does nothing if the // schema is already -4. func (h *histogram) doubleBucketWidth(hot, cold *histogramCounts) { … } func (h *histogram) resetCounts(counts *histogramCounts) { … } // updateExemplar replaces the exemplar for the provided bucket. With empty // labels, it's a no-op. It panics if any of the labels is invalid. func (h *histogram) updateExemplar(v float64, bucket int, l Labels) { … } type HistogramVec … // NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and // partitioned by the given label names. func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec { … } // NewHistogramVec creates a new HistogramVec based on the provided HistogramVecOpts. func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec { … } // GetMetricWithLabelValues returns the Histogram for the given slice of label // values (same order as the variable labels in Desc). If that combination of // label values is accessed for the first time, a new Histogram is created. // // It is possible to call this method without using the returned Histogram to only // create the new Histogram but leave it at its starting value, a Histogram without // any observations. // // Keeping the Histogram for later use is possible (and should be considered if // performance is critical), but keep in mind that Reset, DeleteLabelValues and // Delete can be used to delete the Histogram from the HistogramVec. In that case, the // Histogram will still exist, but it will not be exported anymore, even if a // Histogram with the same label values is created later. See also the CounterVec // example. // // An error is returned if the number of label values is not the same as the // number of variable labels in Desc (minus any curried labels). // // Note that for more than one label value, this method is prone to mistakes // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as // an alternative to avoid that type of mistake. For higher label numbers, the // latter has a much more readable (albeit more verbose) syntax, but it comes // with a performance overhead (for creating and processing the Labels map). // See also the GaugeVec example. func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) { … } // GetMetricWith returns the Histogram for the given Labels map (the label names // must match those of the variable labels in Desc). If that label map is // accessed for the first time, a new Histogram is created. Implications of // creating a Histogram without using it and keeping the Histogram for later use // are the same as for GetMetricWithLabelValues. // // An error is returned if the number and names of the Labels are inconsistent // with those of the variable labels in Desc (minus any curried labels). // // This method is used for the same purpose as // GetMetricWithLabelValues(...string). See there for pros and cons of the two // methods. func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { … } // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like // // myVec.WithLabelValues("404", "GET").Observe(42.21) func (v *HistogramVec) WithLabelValues(lvs ...string) Observer { … } // With works as GetMetricWith but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like // // myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) func (v *HistogramVec) With(labels Labels) Observer { … } // CurryWith returns a vector curried with the provided labels, i.e. the // returned vector has those labels pre-set for all labeled operations performed // on it. The cardinality of the curried vector is reduced accordingly. The // order of the remaining labels stays the same (just with the curried labels // taken out of the sequence – which is relevant for the // (GetMetric)WithLabelValues methods). It is possible to curry a curried // vector, but only with labels not yet used for currying before. // // The metrics contained in the HistogramVec are shared between the curried and // uncurried vectors. They are just accessed differently. Curried and uncurried // vectors behave identically in terms of collection. Only one must be // registered with a given registry (usually the uncurried version). The Reset // method deletes all metrics, even if called on a curried vector. func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) { … } // MustCurryWith works as CurryWith but panics where CurryWith would have // returned an error. func (v *HistogramVec) MustCurryWith(labels Labels) ObserverVec { … } type constHistogram … func (h *constHistogram) Desc() *Desc { … } func (h *constHistogram) Write(out *dto.Metric) error { … } // NewConstHistogram returns a metric representing a Prometheus histogram with // fixed values for the count, sum, and bucket counts. As those parameters // cannot be changed, the returned value does not implement the Histogram // interface (but only the Metric interface). Users of this package will not // have much use for it in regular operations. However, when implementing custom // Collectors, it is useful as a throw-away metric that is generated on the fly // to send it to Prometheus in the Collect method. // // buckets is a map of upper bounds to cumulative counts, excluding the +Inf // bucket. The +Inf bucket is implicit, and its value is equal to the provided count. // // NewConstHistogram returns an error if the length of labelValues is not // consistent with the variable labels in Desc or if Desc is invalid. func NewConstHistogram( desc *Desc, count uint64, sum float64, buckets map[float64]uint64, labelValues ...string, ) (Metric, error) { … } // MustNewConstHistogram is a version of NewConstHistogram that panics where // NewConstHistogram would have returned an error. func MustNewConstHistogram( desc *Desc, count uint64, sum float64, buckets map[float64]uint64, labelValues ...string, ) Metric { … } type buckSort … func (s buckSort) Len() int { … } func (s buckSort) Swap(i, j int) { … } func (s buckSort) Less(i, j int) bool { … } // pickSchema returns the largest number n between -4 and 8 such that // 2^(2^-n) is less or equal the provided bucketFactor. // // Special cases: // - bucketFactor <= 1: panics. // - bucketFactor < 2^(2^-8) (but > 1): still returns 8. func pickSchema(bucketFactor float64) int32 { … } func makeBuckets(buckets *sync.Map) ([]*dto.BucketSpan, []int64) { … } // addToBucket increments the sparse bucket at key by the provided amount. It // returns true if a new sparse bucket had to be created for that. func addToBucket(buckets *sync.Map, key int, increment int64) bool { … } // addAndReset returns a function to be used with sync.Map.Range of spare // buckets in coldCounts. It increments the buckets in the provided hotBuckets // according to the buckets ranged through. It then resets all buckets ranged // through to 0 (but leaves them in place so that they don't need to get // recreated on the next scrape). func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v interface{ … } func deleteSyncMap(m *sync.Map) { … } func findSmallestKey(m *sync.Map) int { … } func getLe(key int, schema int32) float64 { … } // waitForCooldown returns after the count field in the provided histogramCounts // has reached the provided count value. func waitForCooldown(count uint64, counts *histogramCounts) { … } // atomicAddFloat adds the provided float atomically to another float // represented by the bit pattern the bits pointer is pointing to. func atomicAddFloat(bits *uint64, v float64) { … } // atomicDecUint32 atomically decrements the uint32 p points to. See // https://pkg.go.dev/sync/atomic#AddUint32 to understand how this is done. func atomicDecUint32(p *uint32) { … } // addAndResetCounts adds certain fields (count, sum, conventional buckets, zero // bucket) from the cold counts to the corresponding fields in the hot // counts. Those fields are then reset to 0 in the cold counts. func addAndResetCounts(hot, cold *histogramCounts) { … }