@@ -607,6 +607,104 @@ mod tests {
607
607
assert_eq ! ( data_point. value, 30 ) ;
608
608
}
609
609
610
+ // "multi_thread" tokio flavor must be used else flush won't
611
+ // be able to make progress!
612
+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
613
+ async fn counter_aggregation_attribute_order ( ) {
614
+ // Run this test with stdout enabled to see output.
615
+ // cargo test counter_aggregation_attribute_order --features=metrics,testing -- --nocapture
616
+
617
+ // Arrange
618
+ let exporter = InMemoryMetricsExporter :: default ( ) ;
619
+ let reader = PeriodicReader :: builder ( exporter. clone ( ) , runtime:: Tokio ) . build ( ) ;
620
+ let meter_provider = SdkMeterProvider :: builder ( ) . with_reader ( reader) . build ( ) ;
621
+
622
+ // Act
623
+ let meter = meter_provider. meter ( "test" ) ;
624
+ let counter = meter. u64_counter ( "my_counter" ) . init ( ) ;
625
+ // Add the same set of attributes in different order. (they are expected
626
+ // to be treated as same attributes)
627
+ counter. add (
628
+ 1 ,
629
+ & [
630
+ KeyValue :: new ( "A" , "a" ) ,
631
+ KeyValue :: new ( "B" , "b" ) ,
632
+ KeyValue :: new ( "C" , "c" ) ,
633
+ ] ,
634
+ ) ;
635
+ counter. add (
636
+ 1 ,
637
+ & [
638
+ KeyValue :: new ( "A" , "a" ) ,
639
+ KeyValue :: new ( "C" , "c" ) ,
640
+ KeyValue :: new ( "B" , "b" ) ,
641
+ ] ,
642
+ ) ;
643
+ counter. add (
644
+ 1 ,
645
+ & [
646
+ KeyValue :: new ( "B" , "b" ) ,
647
+ KeyValue :: new ( "A" , "a" ) ,
648
+ KeyValue :: new ( "C" , "c" ) ,
649
+ ] ,
650
+ ) ;
651
+ counter. add (
652
+ 1 ,
653
+ & [
654
+ KeyValue :: new ( "B" , "b" ) ,
655
+ KeyValue :: new ( "C" , "c" ) ,
656
+ KeyValue :: new ( "A" , "a" ) ,
657
+ ] ,
658
+ ) ;
659
+ counter. add (
660
+ 1 ,
661
+ & [
662
+ KeyValue :: new ( "C" , "c" ) ,
663
+ KeyValue :: new ( "B" , "b" ) ,
664
+ KeyValue :: new ( "A" , "a" ) ,
665
+ ] ,
666
+ ) ;
667
+ counter. add (
668
+ 1 ,
669
+ & [
670
+ KeyValue :: new ( "C" , "c" ) ,
671
+ KeyValue :: new ( "A" , "a" ) ,
672
+ KeyValue :: new ( "B" , "b" ) ,
673
+ ] ,
674
+ ) ;
675
+
676
+ meter_provider. force_flush ( ) . unwrap ( ) ;
677
+
678
+ // Assert
679
+ let resource_metrics = exporter
680
+ . get_finished_metrics ( )
681
+ . expect ( "metrics are expected to be exported." ) ;
682
+ assert ! ( !resource_metrics. is_empty( ) ) ;
683
+ let metric = & resource_metrics[ 0 ] . scope_metrics [ 0 ] . metrics [ 0 ] ;
684
+ assert_eq ! ( metric. name, "my_counter" ) ;
685
+ let sum = metric
686
+ . data
687
+ . as_any ( )
688
+ . downcast_ref :: < data:: Sum < u64 > > ( )
689
+ . expect ( "Sum aggregation expected for Counter instruments by default" ) ;
690
+
691
+ // Expecting 1 time-series.
692
+ assert_eq ! (
693
+ sum. data_points. len( ) ,
694
+ 1 ,
695
+ "Expected only one data point as attributes are same, but just reordered."
696
+ ) ;
697
+ assert_eq ! (
698
+ sum. temporality,
699
+ data:: Temporality :: Cumulative ,
700
+ "Should produce cumulative by default."
701
+ ) ;
702
+
703
+ // validate the sole datapoint
704
+ let data_point1 = & sum. data_points [ 0 ] ;
705
+ assert_eq ! ( data_point1. value, 6 ) ;
706
+ }
707
+
610
708
#[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
611
709
async fn no_attr_cumulative_counter ( ) {
612
710
let mut test_context = TestContext :: new ( Some ( Temporality :: Cumulative ) ) ;
0 commit comments