@@ -29,10 +29,12 @@ import (
2929 "github.com/pkg/errors"
3030 "github.com/prometheus/client_golang/prometheus"
3131 "github.com/prometheus/client_golang/prometheus/testutil"
32+ dto "github.com/prometheus/client_model/go"
3233 "github.com/prometheus/common/promslog"
3334 "github.com/stretchr/testify/assert"
3435 "github.com/stretchr/testify/require"
3536 "go.mongodb.org/mongo-driver/bson"
37+ "go.mongodb.org/mongo-driver/bson/primitive"
3638 "go.mongodb.org/mongo-driver/mongo"
3739
3840 "github.com/percona/mongodb_exporter/internal/tu"
@@ -422,6 +424,95 @@ func addTestData(ctx context.Context, client *mongo.Client, count int) error {
422424 return nil
423425}
424426
427+ func TestHistogramProcessing (t * testing.T ) {
428+ ctx , cancel := context .WithTimeout (context .Background (), 3 * time .Second )
429+ defer cancel ()
430+
431+ client := tu .DefaultTestClient (ctx , t )
432+ logger := promslog .New (& promslog.Config {})
433+ ti := labelsGetterMock {}
434+
435+ dbBuildInfo , err := retrieveMongoDBBuildInfo (ctx , client , logger .With ("component" , "test" ))
436+ require .NoError (t , err )
437+
438+ c := newDiagnosticDataCollector (ctx , client , logger , true , ti , dbBuildInfo )
439+
440+ metrics := helpers .CollectMetrics (c )
441+ metricFamilies := helpers .ReadMetrics (metrics )
442+
443+ // Check that histogram metrics are created instead of individual lowerBound/count metrics
444+ histogramFound := false
445+ duplicateMetrics := make (map [string ]int )
446+
447+ for _ , mf := range metricFamilies {
448+ metricName := mf .String ()
449+
450+ duplicateMetrics [metricName ]++
451+
452+ if strings .Contains (metricName , "multiPlanner_histograms" ) &&
453+ mf .Type == dto .MetricType_HISTOGRAM {
454+ histogramFound = true
455+ }
456+
457+ // Ensure no duplicate lowerBound/count metrics exist
458+ if strings .Contains (metricName , "lowerBound" ) ||
459+ (strings .Contains (metricName , "count" ) && strings .Contains (metricName , "histograms" )) {
460+ t .Errorf ("Found individual histogram component metric: %s" , metricName )
461+ }
462+ }
463+
464+ // Verify no duplicate metrics exist
465+ for name , count := range duplicateMetrics {
466+ if count > 0 {
467+ t .Errorf ("Duplicate metric found: %s (count: %d)" , name , count )
468+ }
469+ }
470+
471+ // At least one histogram should be found if multiPlanner data exists
472+ if histogramFound {
473+ t .Logf ("Successfully found histogram metrics" )
474+ }
475+ }
476+
477+ func TestHistogramWithMockData (t * testing.T ) {
478+ // Test with controlled mock data to verify histogram creation
479+ mockData := bson.M {
480+ "multiPlanner" : bson.M {
481+ "classicMicros" : bson.M {
482+ "low" : int64 (5000 ),
483+ "high" : int64 (0 ),
484+ "unsigned" : false ,
485+ },
486+ "histograms" : bson.M {
487+ "classicMicros" : primitive.A {
488+ bson.M {
489+ "lowerBound" : bson.M {"low" : int64 (0 ), "high" : int64 (0 ), "unsigned" : false },
490+ "count" : bson.M {"low" : int64 (2 ), "high" : int64 (0 ), "unsigned" : false },
491+ },
492+ bson.M {
493+ "lowerBound" : bson.M {"low" : int64 (1024 ), "high" : int64 (0 ), "unsigned" : false },
494+ "count" : bson.M {"low" : int64 (1 ), "high" : int64 (0 ), "unsigned" : false },
495+ },
496+ },
497+ },
498+ },
499+ }
500+
501+ labels := map [string ]string {}
502+ metrics := makeMetrics ("" , mockData , labels , true )
503+
504+ // Should have one histogram metric, not individual metrics
505+ histogramCount := 0
506+ for _ , metric := range metrics {
507+ desc := metric .Desc ()
508+ if strings .Contains (desc .String (), "multiPlanner_histograms_classicMicros" ) {
509+ histogramCount ++
510+ }
511+ }
512+
513+ require .Equal (t , 1 , histogramCount , "Should create exactly one histogram metric" )
514+ }
515+
425516func cleanTestData (ctx context.Context , client * mongo.Client , count int ) error {
426517 session , err := client .StartSession ()
427518 if err != nil {
0 commit comments