@@ -590,6 +590,115 @@ mod tests {
590
590
) ;
591
591
}
592
592
593
+ // "multi_thread" tokio flavor must be used else flush won't
594
+ // be able to make progress!
595
+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
596
+ #[ ignore = "Known bug: https://github.com/open-telemetry/opentelemetry-rust/issues/1598" ]
597
+ async fn delta_memory_efficiency_test ( ) {
598
+ // Run this test with stdout enabled to see output.
599
+ // cargo test delta_memory_efficiency_test --features=metrics,testing -- --nocapture
600
+
601
+ // Arrange
602
+ let exporter = InMemoryMetricsExporterBuilder :: new ( )
603
+ . with_temporality_selector ( DeltaTemporalitySelector ( ) )
604
+ . build ( ) ;
605
+ let reader = PeriodicReader :: builder ( exporter. clone ( ) , runtime:: Tokio ) . build ( ) ;
606
+ let meter_provider = SdkMeterProvider :: builder ( ) . with_reader ( reader) . build ( ) ;
607
+
608
+ // Act
609
+ let meter = meter_provider. meter ( "test" ) ;
610
+ let counter = meter
611
+ . u64_counter ( "my_counter" )
612
+ . with_unit ( Unit :: new ( "my_unit" ) )
613
+ . init ( ) ;
614
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value1" ) ] ) ;
615
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value1" ) ] ) ;
616
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value1" ) ] ) ;
617
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value1" ) ] ) ;
618
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value1" ) ] ) ;
619
+
620
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value2" ) ] ) ;
621
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value2" ) ] ) ;
622
+ counter. add ( 1 , & [ KeyValue :: new ( "key1" , "value2" ) ] ) ;
623
+
624
+ meter_provider. force_flush ( ) . unwrap ( ) ;
625
+
626
+ // Assert
627
+ let resource_metrics = exporter
628
+ . get_finished_metrics ( )
629
+ . expect ( "metrics are expected to be exported." ) ;
630
+ assert ! ( !resource_metrics. is_empty( ) ) ;
631
+ let metric = & resource_metrics[ 0 ] . scope_metrics [ 0 ] . metrics [ 0 ] ;
632
+ assert_eq ! ( metric. name, "my_counter" ) ;
633
+ assert_eq ! ( metric. unit. as_str( ) , "my_unit" ) ;
634
+ let sum = metric
635
+ . data
636
+ . as_any ( )
637
+ . downcast_ref :: < data:: Sum < u64 > > ( )
638
+ . expect ( "Sum aggregation expected for Counter instruments by default" ) ;
639
+
640
+ // Expecting 2 time-series.
641
+ assert_eq ! ( sum. data_points. len( ) , 2 ) ;
642
+ assert ! ( sum. is_monotonic, "Counter should produce monotonic." ) ;
643
+ assert_eq ! (
644
+ sum. temporality,
645
+ data:: Temporality :: Delta ,
646
+ "Should produce Delta as configured"
647
+ ) ;
648
+
649
+ // find and validate key1=value1 datapoint
650
+ let mut data_point1 = None ;
651
+ for datapoint in & sum. data_points {
652
+ if datapoint
653
+ . attributes
654
+ . iter ( )
655
+ . any ( |( k, v) | k. as_str ( ) == "key1" && v. as_str ( ) == "value1" )
656
+ {
657
+ data_point1 = Some ( datapoint) ;
658
+ }
659
+ }
660
+ assert_eq ! (
661
+ data_point1
662
+ . expect( "datapoint with key1=value1 expected" )
663
+ . value,
664
+ 5
665
+ ) ;
666
+
667
+ // find and validate key1=value2 datapoint
668
+ let mut data_point1 = None ;
669
+ for datapoint in & sum. data_points {
670
+ if datapoint
671
+ . attributes
672
+ . iter ( )
673
+ . any ( |( k, v) | k. as_str ( ) == "key1" && v. as_str ( ) == "value2" )
674
+ {
675
+ data_point1 = Some ( datapoint) ;
676
+ }
677
+ }
678
+ assert_eq ! (
679
+ data_point1
680
+ . expect( "datapoint with key1=value2 expected" )
681
+ . value,
682
+ 3
683
+ ) ;
684
+
685
+ // flush again, and validate that nothing is flushed
686
+ // as delta temporality.
687
+ meter_provider. force_flush ( ) . unwrap ( ) ;
688
+ let resource_metrics = exporter
689
+ . get_finished_metrics ( )
690
+ . expect ( "metrics are expected to be exported." ) ;
691
+ println ! ( "resource_metrics: {:?}" , resource_metrics) ;
692
+ assert ! ( resource_metrics. is_empty( ) , "No metrics should be exported as no new measurements were recorded since last collect." ) ;
693
+ }
694
+
695
+ struct DeltaTemporalitySelector ( ) ;
696
+ impl TemporalitySelector for DeltaTemporalitySelector {
697
+ fn temporality ( & self , _kind : InstrumentKind ) -> Temporality {
698
+ Temporality :: Delta
699
+ }
700
+ }
701
+
593
702
struct TestContext {
594
703
exporter : InMemoryMetricsExporter ,
595
704
meter_provider : SdkMeterProvider ,
0 commit comments