Skip to content

Commit d31f13b

Browse files
committed
Add SparseBucketsZeroThresholdZero and groom doc comments
Signed-off-by: beorn7 <[email protected]>
1 parent 58a8ca4 commit d31f13b

File tree

1 file changed

+65
-44
lines changed

1 file changed

+65
-44
lines changed

prometheus/histogram.go

Lines changed: 65 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -217,18 +217,22 @@ var sparseBounds = [][]float64{
217217
// }
218218

219219
// A Histogram counts individual observations from an event or sample stream in
220-
// configurable buckets. Similar to a summary, it also provides a sum of
220+
// configurable buckets. Similar to a Summary, it also provides a sum of
221221
// observations and an observation count.
222222
//
223223
// On the Prometheus server, quantiles can be calculated from a Histogram using
224-
// the histogram_quantile function in the query language.
224+
// the histogram_quantile PromQL function.
225225
//
226-
// Note that Histograms, in contrast to Summaries, can be aggregated with the
227-
// Prometheus query language (see the documentation for detailed
228-
// procedures). However, Histograms require the user to pre-define suitable
229-
// buckets, and they are in general less accurate. The Observe method of a
230-
// Histogram has a very low performance overhead in comparison with the Observe
231-
// method of a Summary.
226+
// Note that Histograms, in contrast to Summaries, can be aggregated in PromQL
227+
// (see the documentation for detailed procedures). However, Histograms require
228+
// the user to pre-define suitable buckets, and they are in general less
229+
// accurate. (Both problems are addressed by the experimental Native
230+
// Histograms. To use them, configure so-called sparse buckets in the
231+
// HistogramOpts. They also require a Prometheus server v2.40+ with the
232+
// corresponding feature flag enabled.)
233+
//
234+
// The Observe method of a Histogram has a very low performance overhead in
235+
// comparison with the Observe method of a Summary.
232236
//
233237
// To create Histogram instances, use NewHistogram.
234238
type Histogram interface {
@@ -238,7 +242,8 @@ type Histogram interface {
238242
// Observe adds a single observation to the histogram. Observations are
239243
// usually positive or zero. Negative observations are accepted but
240244
// prevent current versions of Prometheus from properly detecting
241-
// counter resets in the sum of observations. See
245+
// counter resets in the sum of observations. (The experimental Native
246+
// Histograms handle negative observations properly.) See
242247
// https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
243248
// for details.
244249
Observe(float64)
@@ -261,14 +266,19 @@ var DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
261266
// which is a bucket boundary at all possible resolutions.
262267
const DefSparseBucketsZeroThreshold = 2.938735877055719e-39
263268

269+
// SparseBucketsZeroThresholdZero can be used as SparseBucketsZeroThreshold in
270+
// the HistogramOpts to create a zero bucket of width zero, i.e. a zero bucket
271+
// that only receives observations of precisely zero.
272+
const SparseBucketsZeroThresholdZero = -1
273+
264274
var errBucketLabelNotAllowed = fmt.Errorf(
265275
"%q is not allowed as label name in histograms", bucketLabel,
266276
)
267277

268-
// LinearBuckets creates 'count' buckets, each 'width' wide, where the lowest
269-
// bucket has an upper bound of 'start'. The final +Inf bucket is not counted
270-
// and not included in the returned slice. The returned slice is meant to be
271-
// used for the Buckets field of HistogramOpts.
278+
// LinearBuckets creates 'count' regular buckets, each 'width' wide, where the
279+
// lowest bucket has an upper bound of 'start'. The final +Inf bucket is not
280+
// counted and not included in the returned slice. The returned slice is meant
281+
// to be used for the Buckets field of HistogramOpts.
272282
//
273283
// The function panics if 'count' is zero or negative.
274284
func LinearBuckets(start, width float64, count int) []float64 {
@@ -283,11 +293,11 @@ func LinearBuckets(start, width float64, count int) []float64 {
283293
return buckets
284294
}
285295

286-
// ExponentialBuckets creates 'count' buckets, where the lowest bucket has an
287-
// upper bound of 'start' and each following bucket's upper bound is 'factor'
288-
// times the previous bucket's upper bound. The final +Inf bucket is not counted
289-
// and not included in the returned slice. The returned slice is meant to be
290-
// used for the Buckets field of HistogramOpts.
296+
// ExponentialBuckets creates 'count' regular buckets, where the lowest bucket
297+
// has an upper bound of 'start' and each following bucket's upper bound is
298+
// 'factor' times the previous bucket's upper bound. The final +Inf bucket is
299+
// not counted and not included in the returned slice. The returned slice is
300+
// meant to be used for the Buckets field of HistogramOpts.
291301
//
292302
// The function panics if 'count' is 0 or negative, if 'start' is 0 or negative,
293303
// or if 'factor' is less than or equal 1.
@@ -382,20 +392,21 @@ type HistogramOpts struct {
382392
Buckets []float64
383393

384394
// If SparseBucketsFactor is greater than one, sparse buckets are used
385-
// (in addition to the regular buckets, if defined above). A histogram
386-
// with sparse buckets will be ingested as a native histogram by a
387-
// Prometheus server with that feature enable. Sparse buckets are
388-
// exponential buckets covering the whole float64 range (with the
389-
// exception of the “zero” bucket, see SparseBucketsZeroThreshold
390-
// below). From any one bucket to the next, the width of the bucket
391-
// grows by a constant factor. SparseBucketsFactor provides an upper
392-
// bound for this factor (exception see below). The smaller
393-
// SparseBucketsFactor, the more buckets will be used and thus the more
394-
// costly the histogram will become. A generally good trade-off between
395-
// cost and accuracy is a value of 1.1 (each bucket is at most 10% wider
396-
// than the previous one), which will result in each power of two
397-
// divided into 8 buckets (e.g. there will be 8 buckets between 1 and 2,
398-
// same as between 2 and 4, and 4 and 8, etc.).
395+
// (in addition to the regular buckets, if defined above). A Histogram
396+
// with sparse buckets will be ingested as a Native Histogram by a
397+
// Prometheus server with that feature enabled (requires Prometheus
398+
// v2.40+). Sparse buckets are exponential buckets covering the whole
399+
// float64 range (with the exception of the “zero” bucket, see
400+
// SparseBucketsZeroThreshold below). From any one bucket to the next,
401+
// the width of the bucket grows by a constant
402+
// factor. SparseBucketsFactor provides an upper bound for this factor
403+
// (exception see below). The smaller SparseBucketsFactor, the more
404+
// buckets will be used and thus the more costly the histogram will
405+
// become. A generally good trade-off between cost and accuracy is a
406+
// value of 1.1 (each bucket is at most 10% wider than the previous
407+
// one), which will result in each power of two divided into 8 buckets
408+
// (e.g. there will be 8 buckets between 1 and 2, same as between 2 and
409+
// 4, and 4 and 8, etc.).
399410
//
400411
// Details about the actually used factor: The factor is calculated as
401412
// 2^(2^n), where n is an integer number between (and including) -8 and
@@ -405,28 +416,38 @@ type HistogramOpts struct {
405416
// SparseBucketsFactor is greater than 1 but smaller than 2^(2^-8), then
406417
// the actually used factor is still 2^(2^-8) even though it is larger
407418
// than the provided SparseBucketsFactor.
419+
//
420+
// NOTE: Native Histograms are still an experimental feature. Their
421+
// behavior might still change without a major version
422+
// bump. Subsequently, all SparseBucket... options here might still
423+
// change their behavior or name (or might completely disappear) without
424+
// a major version bump.
408425
SparseBucketsFactor float64
409426
// All observations with an absolute value of less or equal
410427
// SparseBucketsZeroThreshold are accumulated into a “zero” bucket. For
411428
// best results, this should be close to a bucket boundary. This is
412429
// usually the case if picking a power of two. If
413430
// SparseBucketsZeroThreshold is left at zero,
414-
// DefSparseBucketsZeroThreshold is used as the threshold. If it is set
415-
// to a negative value, a threshold of zero is used, i.e. only
416-
// observations of precisely zero will go into the zero
417-
// bucket. (TODO(beorn7): That's obviously weird and just a consequence
418-
// of making the zero value of HistogramOpts meaningful. Has to be
419-
// solved more elegantly in the final version.)
431+
// DefSparseBucketsZeroThreshold is used as the threshold. To configure
432+
// a zero bucket with an actual threshold of zero (i.e. only
433+
// observations of precisely zero will go into the zero bucket), set
434+
// SparseBucketsZeroThreshold to the SparseBucketsZeroThresholdZero
435+
// constant (or any negative float value).
420436
SparseBucketsZeroThreshold float64
421437

422438
// The remaining fields define a strategy to limit the number of
423439
// populated sparse buckets. If SparseBucketsMaxNumber is left at zero,
424-
// the number of buckets is not limited. Otherwise, once the provided
425-
// number is exceeded, the following strategy is enacted: First, if the
426-
// last reset (or the creation) of the histogram is at least
427-
// SparseBucketsMinResetDuration ago, then the whole histogram is reset
428-
// to its initial state (including regular buckets). If less time has
429-
// passed, or if SparseBucketsMinResetDuration is zero, no reset is
440+
// the number of buckets is not limited. (Note that this might lead to
441+
// unbounded memory consumption if the values observed by the Histogram
442+
// are sufficiently wide-spread. In particular, this could be used as a
443+
// DoS attack vector. Where the observed values depend on external
444+
// inputs, it is highly recommended to set a SparseBucketsMaxNumber.)
445+
// Once the set SparseBucketsMaxNumber is exceeded, the following
446+
// strategy is enacted: First, if the last reset (or the creation) of
447+
// the histogram is at least SparseBucketsMinResetDuration ago, then the
448+
// whole histogram is reset to its initial state (including regular
449+
// buckets). If less time has passed, or if
450+
// SparseBucketsMinResetDuration is zero, no reset is
430451
// performed. Instead, the zero threshold is increased sufficiently to
431452
// reduce the number of buckets to or below SparseBucketsMaxNumber, but
432453
// not to more than SparseBucketsMaxZeroThreshold. Thus, if

0 commit comments

Comments
 (0)