@@ -369,8 +369,13 @@ type HistogramOpts struct {
369
369
// SparseBucketsZeroThreshold are accumulated into a “zero” bucket. For
370
370
// best results, this should be close to a bucket boundary. This is
371
371
// usually the case if picking a power of two. If
372
- // SparseBucketsZeroThreshold is left at zero (or set to a negative
373
- // value), DefSparseBucketsZeroThreshold is used as the threshold.
372
+ // SparseBucketsZeroThreshold is left at zero,
373
+ // DefSparseBucketsZeroThreshold is used as the threshold. If it is set
374
+ // to a negative value, a threshold of zero is used, i.e. only
375
+ // observations of precisely zero will go into the zero
376
+ // bucket. (TODO(beorn7): That's obviously weird and just a consequence
377
+ // of making the zero value of HistogramOpts meaningful. Has to be
378
+ // solved more elegantly in the final version.)
374
379
SparseBucketsZeroThreshold float64
375
380
// TODO(beorn7): Need a setting to limit total bucket count and to
376
381
// configure a strategy to enforce the limit, e.g. if minimum duration
@@ -413,22 +418,24 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
413
418
}
414
419
415
420
h := & histogram {
416
- desc : desc ,
417
- upperBounds : opts .Buckets ,
418
- sparseThreshold : opts .SparseBucketsZeroThreshold ,
419
- labelPairs : MakeLabelPairs (desc , labelValues ),
420
- counts : [2 ]* histogramCounts {{}, {}},
421
- now : time .Now ,
421
+ desc : desc ,
422
+ upperBounds : opts .Buckets ,
423
+ labelPairs : MakeLabelPairs (desc , labelValues ),
424
+ counts : [2 ]* histogramCounts {{}, {}},
425
+ now : time .Now ,
422
426
}
423
427
if len (h .upperBounds ) == 0 && opts .SparseBucketsFactor <= 1 {
424
428
h .upperBounds = DefBuckets
425
429
}
426
- if h .sparseThreshold <= 0 {
427
- h .sparseThreshold = DefSparseBucketsZeroThreshold
428
- }
429
430
if opts .SparseBucketsFactor <= 1 {
430
- h .sparseThreshold = 0 // To mark that there are no sparse buckets.
431
+ h .sparseSchema = math . MinInt32 // To mark that there are no sparse buckets.
431
432
} else {
433
+ switch {
434
+ case opts .SparseBucketsZeroThreshold > 0 :
435
+ h .sparseThreshold = opts .SparseBucketsZeroThreshold
436
+ case opts .SparseBucketsZeroThreshold == 0 :
437
+ h .sparseThreshold = DefSparseBucketsZeroThreshold
438
+ } // Leave h.sparseThreshold at 0 otherwise.
432
439
h .sparseSchema = pickSparseSchema (opts .SparseBucketsFactor )
433
440
}
434
441
for i , upperBound := range h .upperBounds {
@@ -559,8 +566,8 @@ type histogram struct {
559
566
upperBounds []float64
560
567
labelPairs []* dto.LabelPair
561
568
exemplars []atomic.Value // One more than buckets (to include +Inf), each a *dto.Exemplar.
562
- sparseSchema int32
563
- sparseThreshold float64 // This is zero iff no sparse buckets are used.
569
+ sparseSchema int32 // Set to math.MinInt32 if no sparse buckets are used.
570
+ sparseThreshold float64
564
571
565
572
now func () time.Time // To mock out time.Now() for testing.
566
573
}
@@ -604,11 +611,9 @@ func (h *histogram) Write(out *dto.Metric) error {
604
611
}
605
612
606
613
his := & dto.Histogram {
607
- Bucket : make ([]* dto.Bucket , len (h .upperBounds )),
608
- SampleCount : proto .Uint64 (count ),
609
- SampleSum : proto .Float64 (math .Float64frombits (atomic .LoadUint64 (& coldCounts .sumBits ))),
610
- SbSchema : & h .sparseSchema ,
611
- SbZeroThreshold : & h .sparseThreshold ,
614
+ Bucket : make ([]* dto.Bucket , len (h .upperBounds )),
615
+ SampleCount : proto .Uint64 (count ),
616
+ SampleSum : proto .Float64 (math .Float64frombits (atomic .LoadUint64 (& coldCounts .sumBits ))),
612
617
}
613
618
out .Histogram = his
614
619
out .Label = h .labelPairs
@@ -648,7 +653,9 @@ func (h *histogram) Write(out *dto.Metric) error {
648
653
atomic .AddUint64 (& hotCounts .buckets [i ], atomic .LoadUint64 (& coldCounts .buckets [i ]))
649
654
atomic .StoreUint64 (& coldCounts .buckets [i ], 0 )
650
655
}
651
- if h .sparseThreshold != 0 {
656
+ if h .sparseSchema > math .MinInt32 {
657
+ his .SbZeroThreshold = & h .sparseThreshold
658
+ his .SbSchema = & h .sparseSchema
652
659
zeroBucket := atomic .LoadUint64 (& coldCounts .sparseZeroBucket )
653
660
654
661
defer func () {
@@ -749,7 +756,7 @@ func (h *histogram) findBucket(v float64) int {
749
756
// observe is the implementation for Observe without the findBucket part.
750
757
func (h * histogram ) observe (v float64 , bucket int ) {
751
758
// Do not add to sparse buckets for NaN observations.
752
- doSparse := h .sparseThreshold != 0 && ! math .IsNaN (v )
759
+ doSparse := h .sparseSchema > math . MinInt32 && ! math .IsNaN (v )
753
760
var whichSparse , sparseKey int
754
761
if doSparse {
755
762
switch {
0 commit comments