@@ -72,6 +72,7 @@ mod tests {
72
72
KeyValue ,
73
73
} ;
74
74
use std:: borrow:: Cow ;
75
+ use std:: sync:: { Arc , Mutex } ;
75
76
76
77
// "multi_thread" tokio flavor must be used else flush won't
77
78
// be able to make progress!
@@ -980,4 +981,190 @@ mod tests {
980
981
. expect ( "Failed to cast aggregation to expected type" )
981
982
}
982
983
}
984
+
985
+ /// Observable counter in delta aggregation.
986
+ ///
987
+ /// ObservableCounter provides the current (i.e cumulative) value of the counter at the time of observation,
988
+ /// and the SDK is expected to remember the previous value, so that it can do cumulative to
989
+ /// delta conversion.
990
+ #[ tokio:: test( flavor = "multi_thread" ) ]
991
+ async fn observable_counter_delta ( ) {
992
+ // cargo test observable_counter_delta --features=metrics,testing -- --nocapture
993
+
994
+ // Arrange
995
+ let test_context = TestContext :: new ( Some ( Temporality :: Delta ) ) ;
996
+ let meter_provider = test_context. meter_provider ;
997
+ let exporter = test_context. exporter ;
998
+ let meter = meter_provider. meter ( "test" ) ;
999
+ let observable_counter = meter. u64_observable_counter ( "my_observable_counter" ) . init ( ) ;
1000
+
1001
+ // Act
1002
+ // The Observable counter reports 100, 200, 300 and so on.
1003
+ let i = Arc :: new ( Mutex :: new ( 0 ) ) ;
1004
+ meter
1005
+ . register_callback ( & [ observable_counter. as_any ( ) ] , move |observer| {
1006
+ let mut num = i. lock ( ) . unwrap ( ) ;
1007
+ * num += 1 ;
1008
+
1009
+ println ! ( "Observable Counter is reporting: {}" , * num * 100 ) ;
1010
+
1011
+ observer. observe_u64 (
1012
+ & observable_counter,
1013
+ * num * 100 ,
1014
+ [
1015
+ KeyValue :: new ( "statusCode" , "200" ) ,
1016
+ KeyValue :: new ( "verb" , "get" ) ,
1017
+ ]
1018
+ . as_ref ( ) ,
1019
+ ) ;
1020
+ } )
1021
+ . expect ( "Expected to register callback" ) ;
1022
+
1023
+ meter_provider. force_flush ( ) . unwrap ( ) ;
1024
+
1025
+ // Assert
1026
+ let resource_metrics = exporter
1027
+ . get_finished_metrics ( )
1028
+ . expect ( "metrics are expected to be exported." ) ;
1029
+ assert ! ( !resource_metrics. is_empty( ) ) ;
1030
+ let metric = & resource_metrics[ 0 ] . scope_metrics [ 0 ] . metrics [ 0 ] ;
1031
+ assert_eq ! ( metric. name, "my_observable_counter" ) ;
1032
+
1033
+ let sum = metric
1034
+ . data
1035
+ . as_any ( )
1036
+ . downcast_ref :: < data:: Sum < u64 > > ( )
1037
+ . expect ( "Sum aggregation expected for ObservableCounter instruments by default" ) ;
1038
+
1039
+ assert_eq ! (
1040
+ sum. temporality,
1041
+ data:: Temporality :: Delta ,
1042
+ "Should produce Delta as configured."
1043
+ ) ;
1044
+
1045
+ assert_eq ! ( sum. data_points. len( ) , 1 ) ;
1046
+
1047
+ // find and validate the single datapoint
1048
+ let data_point = & sum. data_points [ 0 ] ;
1049
+ assert_eq ! ( data_point. value, 100 ) ;
1050
+
1051
+ // Flush again, to trigger next collection.
1052
+ exporter. reset ( ) ;
1053
+ meter_provider. force_flush ( ) . unwrap ( ) ;
1054
+
1055
+ // Assert
1056
+ let resource_metrics = exporter
1057
+ . get_finished_metrics ( )
1058
+ . expect ( "metrics are expected to be exported." ) ;
1059
+ assert ! ( !resource_metrics. is_empty( ) ) ;
1060
+ let metric = & resource_metrics[ 0 ] . scope_metrics [ 0 ] . metrics [ 0 ] ;
1061
+ assert_eq ! ( metric. name, "my_observable_counter" ) ;
1062
+
1063
+ let sum = metric
1064
+ . data
1065
+ . as_any ( )
1066
+ . downcast_ref :: < data:: Sum < u64 > > ( )
1067
+ . expect ( "Sum aggregation expected for ObservableCounter instruments by default" ) ;
1068
+
1069
+ assert_eq ! ( sum. data_points. len( ) , 1 ) ;
1070
+
1071
+ // find and validate the single datapoint
1072
+ let data_point = & sum. data_points [ 0 ] ;
1073
+
1074
+ // The second observation should be 100 as well, as temporality is delta
1075
+ assert_eq ! ( data_point. value, 100 ) ;
1076
+ }
1077
+
1078
+ /// Tests Observable counter in cumulative aggregation.
1079
+ ///
1080
+ /// ObservableCounter provides the current (i.e Cumulative) value of the counter at the time of observation,
1081
+ /// and the SDK is expected to aggregate the value as-is.
1082
+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
1083
+ async fn observable_counter_cumulative ( ) {
1084
+ // cargo test observable_counter_cumulative --features=metrics,testing -- --nocapture
1085
+
1086
+ // Arrange
1087
+ let test_context = TestContext :: new ( Some ( Temporality :: Cumulative ) ) ;
1088
+ let meter_provider = test_context. meter_provider ;
1089
+ let exporter = test_context. exporter ;
1090
+ let meter = meter_provider. meter ( "test" ) ;
1091
+ let observable_counter = meter. u64_observable_counter ( "my_observable_counter" ) . init ( ) ;
1092
+
1093
+ // Act
1094
+ // The Observable counter reports 100, 200, 300 and so on.
1095
+ let i = Arc :: new ( Mutex :: new ( 0 ) ) ;
1096
+ meter
1097
+ . register_callback ( & [ observable_counter. as_any ( ) ] , move |observer| {
1098
+ let mut num = i. lock ( ) . unwrap ( ) ;
1099
+ * num += 1 ;
1100
+
1101
+ println ! ( "Observable Counter is reporting: {}" , * num * 100 ) ;
1102
+
1103
+ observer. observe_u64 (
1104
+ & observable_counter,
1105
+ * num * 100 ,
1106
+ [
1107
+ KeyValue :: new ( "statusCode" , "200" ) ,
1108
+ KeyValue :: new ( "verb" , "get" ) ,
1109
+ ]
1110
+ . as_ref ( ) ,
1111
+ ) ;
1112
+ } )
1113
+ . expect ( "Expected to register callback" ) ;
1114
+
1115
+ meter_provider. force_flush ( ) . unwrap ( ) ;
1116
+
1117
+ // Assert
1118
+ let resource_metrics = exporter
1119
+ . get_finished_metrics ( )
1120
+ . expect ( "metrics are expected to be exported." ) ;
1121
+ assert ! ( !resource_metrics. is_empty( ) ) ;
1122
+ let metric = & resource_metrics[ 0 ] . scope_metrics [ 0 ] . metrics [ 0 ] ;
1123
+ assert_eq ! ( metric. name, "my_observable_counter" ) ;
1124
+
1125
+ let sum = metric
1126
+ . data
1127
+ . as_any ( )
1128
+ . downcast_ref :: < data:: Sum < u64 > > ( )
1129
+ . expect ( "Sum aggregation expected for ObservableCounter instruments by default" ) ;
1130
+
1131
+ assert_eq ! (
1132
+ sum. temporality,
1133
+ data:: Temporality :: Cumulative ,
1134
+ "Should produce Cumulative by default."
1135
+ ) ;
1136
+
1137
+ assert_eq ! ( sum. data_points. len( ) , 1 ) ;
1138
+
1139
+ // find and validate the single datapoint
1140
+ let data_point = & sum. data_points [ 0 ] ;
1141
+ // 100 is the first observation.
1142
+ assert_eq ! ( data_point. value, 100 ) ;
1143
+
1144
+ // Flush again, to trigger next collection.
1145
+ exporter. reset ( ) ;
1146
+ meter_provider. force_flush ( ) . unwrap ( ) ;
1147
+
1148
+ // Assert
1149
+ let resource_metrics = exporter
1150
+ . get_finished_metrics ( )
1151
+ . expect ( "metrics are expected to be exported." ) ;
1152
+
1153
+ assert ! ( !resource_metrics. is_empty( ) ) ;
1154
+ let metric = & resource_metrics[ 0 ] . scope_metrics [ 0 ] . metrics [ 0 ] ;
1155
+ assert_eq ! ( metric. name, "my_observable_counter" ) ;
1156
+
1157
+ let sum = metric
1158
+ . data
1159
+ . as_any ( )
1160
+ . downcast_ref :: < data:: Sum < u64 > > ( )
1161
+ . expect ( "Sum aggregation expected for ObservableCounter instruments by default" ) ;
1162
+
1163
+ assert_eq ! ( sum. data_points. len( ) , 1 ) ;
1164
+
1165
+ // find and validate the single datapoint
1166
+ let data_point = & sum. data_points [ 0 ] ;
1167
+ // The second observation should be 200
1168
+ assert_eq ! ( data_point. value, 200 ) ;
1169
+ }
983
1170
}
0 commit comments