@@ -456,3 +456,93 @@ func TestHistogramExemplar(t *testing.T) {
456
456
}
457
457
}
458
458
}
459
+
460
+ func TestSparseHistogram (t * testing.T ) {
461
+
462
+ scenarios := []struct {
463
+ name string
464
+ observations []float64
465
+ factor float64
466
+ zeroThreshold float64
467
+ want string // String representation of protobuf.
468
+ }{
469
+ {
470
+ name : "no sparse buckets" ,
471
+ observations : []float64 {1 , 2 , 3 },
472
+ factor : 1 ,
473
+ want : `sample_count:3 sample_sum:6 bucket:<cumulative_count:0 upper_bound:0.005 > bucket:<cumulative_count:0 upper_bound:0.01 > bucket:<cumulative_count:0 upper_bound:0.025 > bucket:<cumulative_count:0 upper_bound:0.05 > bucket:<cumulative_count:0 upper_bound:0.1 > bucket:<cumulative_count:0 upper_bound:0.25 > bucket:<cumulative_count:0 upper_bound:0.5 > bucket:<cumulative_count:1 upper_bound:1 > bucket:<cumulative_count:2 upper_bound:2.5 > bucket:<cumulative_count:3 upper_bound:5 > bucket:<cumulative_count:3 upper_bound:10 > sb_schema:0 sb_zero_threshold:0 ` , // Has conventional buckets because there are no sparse buckets.
474
+ },
475
+ {
476
+ name : "factor 1.1 results in schema 3" ,
477
+ observations : []float64 {0 , 1 , 2 , 3 },
478
+ factor : 1.1 ,
479
+ want : `sample_count:4 sample_sum:6 sb_schema:3 sb_zero_threshold:2.938735877055719e-39 sb_zero_count:1 sb_positive:<span:<offset:0 length:1 > span:<offset:7 length:1 > span:<offset:4 length:1 > delta:1 delta:0 delta:0 > ` ,
480
+ },
481
+ {
482
+ name : "factor 1.2 results in schema 2" ,
483
+ observations : []float64 {0 , 1 , 1.2 , 1.4 , 1.8 , 2 },
484
+ factor : 1.2 ,
485
+ want : `sample_count:6 sample_sum:7.4 sb_schema:2 sb_zero_threshold:2.938735877055719e-39 sb_zero_count:1 sb_positive:<span:<offset:0 length:5 > delta:1 delta:-1 delta:2 delta:-2 delta:2 > ` ,
486
+ },
487
+ {
488
+ name : "negative buckets" ,
489
+ observations : []float64 {0 , - 1 , - 1.2 , - 1.4 , - 1.8 , - 2 },
490
+ factor : 1.2 ,
491
+ want : `sample_count:6 sample_sum:-7.4 sb_schema:2 sb_zero_threshold:2.938735877055719e-39 sb_zero_count:1 sb_negative:<span:<offset:0 length:5 > delta:1 delta:-1 delta:2 delta:-2 delta:2 > ` ,
492
+ },
493
+ {
494
+ name : "negative and positive buckets" ,
495
+ observations : []float64 {0 , - 1 , - 1.2 , - 1.4 , - 1.8 , - 2 , 1 , 1.2 , 1.4 , 1.8 , 2 },
496
+ factor : 1.2 ,
497
+ want : `sample_count:11 sample_sum:0 sb_schema:2 sb_zero_threshold:2.938735877055719e-39 sb_zero_count:1 sb_negative:<span:<offset:0 length:5 > delta:1 delta:-1 delta:2 delta:-2 delta:2 > sb_positive:<span:<offset:0 length:5 > delta:1 delta:-1 delta:2 delta:-2 delta:2 > ` ,
498
+ },
499
+ {
500
+ name : "wide zero bucket" ,
501
+ observations : []float64 {0 , - 1 , - 1.2 , - 1.4 , - 1.8 , - 2 , 1 , 1.2 , 1.4 , 1.8 , 2 },
502
+ factor : 1.2 ,
503
+ zeroThreshold : 1.4 ,
504
+ want : `sample_count:11 sample_sum:0 sb_schema:2 sb_zero_threshold:1.4 sb_zero_count:7 sb_negative:<span:<offset:4 length:1 > delta:2 > sb_positive:<span:<offset:4 length:1 > delta:2 > ` ,
505
+ },
506
+ {
507
+ name : "NaN observation" ,
508
+ observations : []float64 {0 , 1 , 1.2 , 1.4 , 1.8 , 2 , math .NaN ()},
509
+ factor : 1.2 ,
510
+ want : `sample_count:7 sample_sum:nan sb_schema:2 sb_zero_threshold:2.938735877055719e-39 sb_zero_count:1 sb_positive:<span:<offset:0 length:5 > delta:1 delta:-1 delta:2 delta:-2 delta:2 > ` ,
511
+ },
512
+ {
513
+ name : "+Inf observation" ,
514
+ observations : []float64 {0 , 1 , 1.2 , 1.4 , 1.8 , 2 , math .Inf (+ 1 )},
515
+ factor : 1.2 ,
516
+ want : `sample_count:7 sample_sum:inf sb_schema:2 sb_zero_threshold:2.938735877055719e-39 sb_zero_count:1 sb_positive:<span:<offset:0 length:5 > span:<offset:2147483642 length:1 > delta:1 delta:-1 delta:2 delta:-2 delta:2 delta:-1 > ` ,
517
+ },
518
+ {
519
+ name : "-Inf observation" ,
520
+ observations : []float64 {0 , 1 , 1.2 , 1.4 , 1.8 , 2 , math .Inf (- 1 )},
521
+ factor : 1.2 ,
522
+ want : `sample_count:7 sample_sum:-inf sb_schema:2 sb_zero_threshold:2.938735877055719e-39 sb_zero_count:1 sb_negative:<span:<offset:2147483647 length:1 > delta:1 > sb_positive:<span:<offset:0 length:5 > delta:1 delta:-1 delta:2 delta:-2 delta:2 > ` ,
523
+ },
524
+ }
525
+
526
+ for _ , s := range scenarios {
527
+ t .Run (s .name , func (t * testing.T ) {
528
+ his := NewHistogram (HistogramOpts {
529
+ Name : "name" ,
530
+ Help : "help" ,
531
+ SparseBucketsFactor : s .factor ,
532
+ SparseBucketsZeroThreshold : s .zeroThreshold ,
533
+ })
534
+ for _ , o := range s .observations {
535
+ his .Observe (o )
536
+ }
537
+ m := & dto.Metric {}
538
+ if err := his .Write (m ); err != nil {
539
+ t .Fatal ("unexpected error writing metric" , err )
540
+ }
541
+ got := m .Histogram .String ()
542
+ if s .want != got {
543
+ t .Errorf ("want histogram %q, got %q" , s .want , got )
544
+ }
545
+ })
546
+ }
547
+
548
+ }
0 commit comments