13
13
# limitations under the License.
14
14
15
15
import unittest
16
+ from unittest import mock
16
17
17
18
from opentelemetry .exporter .prometheus_remote_write import (
18
19
PrometheusRemoteWriteMetricsExporter ,
19
20
)
21
+ from opentelemetry .exporter .prometheus_remote_write .gen .types_pb2 import (
22
+ TimeSeries ,
23
+ )
24
+ from opentelemetry .sdk .metrics import Counter
25
+ from opentelemetry .sdk .metrics .export import ExportRecord , MetricsExportResult
26
+ from opentelemetry .sdk .metrics .export .aggregate import (
27
+ HistogramAggregator ,
28
+ LastValueAggregator ,
29
+ MinMaxSumCountAggregator ,
30
+ SumAggregator ,
31
+ ValueObserverAggregator ,
32
+ )
33
+ from opentelemetry .sdk .resources import Resource
34
+ from opentelemetry .sdk .util import get_dict_as_key
20
35
21
36
22
37
class TestValidation (unittest .TestCase ):
@@ -111,35 +126,151 @@ def test_invalid_tls_config_key_only_param(self):
111
126
class TestConversion (unittest .TestCase ):
112
127
# Initializes test data that is reused across tests
113
128
def setUp (self ):
114
- pass
129
+ self ._test_metric = Counter (
130
+ "testname" , "testdesc" , "testunit" , int , None
131
+ )
132
+ self ._exporter = PrometheusRemoteWriteMetricsExporter (
133
+ endpoint = "/prom/test_endpoint"
134
+ )
135
+
136
+ def generate_record (aggregator_type ):
137
+ return ExportRecord (
138
+ self ._test_metric , None , aggregator_type (), Resource ({}),
139
+ )
140
+
141
+ self ._generate_record = generate_record
142
+
143
+ def converter_method (record , name , value ):
144
+ return (type (record .aggregator ), name , value )
145
+
146
+ self ._converter_mock = mock .MagicMock (return_value = converter_method )
115
147
116
148
# Ensures conversion to timeseries function works with valid aggregation types
117
149
def test_valid_convert_to_timeseries (self ):
118
- pass
150
+ timeseries_mock_method = mock .Mock (return_value = ["test_value" ])
151
+ self ._exporter .convert_from_sum = timeseries_mock_method
152
+ self ._exporter .convert_from_min_max_sum_count = timeseries_mock_method
153
+ self ._exporter .convert_from_histogram = timeseries_mock_method
154
+ self ._exporter .convert_from_last_value = timeseries_mock_method
155
+ self ._exporter .convert_from_value_observer = timeseries_mock_method
156
+ test_records = [
157
+ self ._generate_record (SumAggregator ),
158
+ self ._generate_record (MinMaxSumCountAggregator ),
159
+ self ._generate_record (HistogramAggregator ),
160
+ self ._generate_record (LastValueAggregator ),
161
+ self ._generate_record (ValueObserverAggregator ),
162
+ ]
163
+ data = self ._exporter .convert_to_timeseries (test_records )
164
+ self .assertEqual (len (data ), 5 )
165
+ for timeseries in data :
166
+ self .assertEqual (timeseries , "test_value" )
167
+
168
+ no_type_records = [self ._generate_record (lambda : None )]
169
+ with self .assertRaises (ValueError ):
170
+ self ._exporter .convert_to_timeseries (no_type_records )
119
171
120
172
# Ensures conversion to timeseries fails for unsupported aggregation types
121
173
def test_invalid_convert_to_timeseries (self ):
122
- pass
174
+ no_type_records = [self ._generate_record (lambda : None )]
175
+ with self .assertRaises (ValueError ):
176
+ self ._exporter .convert_to_timeseries (no_type_records )
123
177
124
178
# Ensures sum aggregator is correctly converted to timeseries
125
179
def test_convert_from_sum (self ):
126
- pass
180
+ sum_record = self ._generate_record (SumAggregator )
181
+ sum_record .aggregator .update (3 )
182
+ sum_record .aggregator .update (2 )
183
+ sum_record .aggregator .take_checkpoint ()
184
+
185
+ self ._exporter .create_timeseries = self ._converter_mock ()
186
+ timeseries = self ._exporter .convert_from_sum (sum_record )
187
+ self .assertEqual (timeseries [0 ], (SumAggregator , "testname" , 5 ))
127
188
128
189
# Ensures sum min_max_count aggregator is correctly converted to timeseries
129
190
def test_convert_from_min_max_sum_count (self ):
130
- pass
191
+ min_max_sum_count_record = self ._generate_record (
192
+ MinMaxSumCountAggregator
193
+ )
194
+ min_max_sum_count_record .aggregator .update (5 )
195
+ min_max_sum_count_record .aggregator .update (1 )
196
+ min_max_sum_count_record .aggregator .take_checkpoint ()
197
+
198
+ self ._exporter .create_timeseries = self ._converter_mock ()
199
+ timeseries = self ._exporter .convert_from_min_max_sum_count (
200
+ min_max_sum_count_record
201
+ )
202
+ self .assertEqual (
203
+ timeseries [0 ], (MinMaxSumCountAggregator , "testname_min" , 1 )
204
+ )
205
+ self .assertEqual (
206
+ timeseries [1 ], (MinMaxSumCountAggregator , "testname_max" , 5 )
207
+ )
208
+ self .assertEqual (
209
+ timeseries [2 ], (MinMaxSumCountAggregator , "testname_sum" , 6 )
210
+ )
211
+ self .assertEqual (
212
+ timeseries [3 ], (MinMaxSumCountAggregator , "testname_count" , 2 )
213
+ )
131
214
132
215
# Ensures histogram aggregator is correctly converted to timeseries
133
216
def test_convert_from_histogram (self ):
134
- pass
217
+ histogram_record = self ._generate_record (HistogramAggregator )
218
+ histogram_record .aggregator .update (5 )
219
+ histogram_record .aggregator .update (2 )
220
+ histogram_record .aggregator .update (- 1 )
221
+ histogram_record .aggregator .take_checkpoint ()
222
+
223
+ self ._exporter .create_timeseries = self ._converter_mock ()
224
+ timeseries = self ._exporter .convert_from_histogram (histogram_record )
225
+ self .assertEqual (
226
+ timeseries [0 ], (HistogramAggregator , 'testname_bucket{le="0"}' , 1 )
227
+ )
228
+ self .assertEqual (
229
+ timeseries [1 ],
230
+ (HistogramAggregator , 'testname_bucket{le="+Inf"}' , 2 ),
231
+ )
232
+ self .assertEqual (
233
+ timeseries [2 ], (HistogramAggregator , "testname_count" , 3 )
234
+ )
135
235
136
236
# Ensures last value aggregator is correctly converted to timeseries
137
237
def test_convert_from_last_value (self ):
138
- pass
238
+ last_value_record = self ._generate_record (LastValueAggregator )
239
+ last_value_record .aggregator .update (1 )
240
+ last_value_record .aggregator .update (5 )
241
+ last_value_record .aggregator .take_checkpoint ()
242
+
243
+ self ._exporter .create_timeseries = self ._converter_mock ()
244
+ timeseries = self ._exporter .convert_from_last_value (last_value_record )
245
+ self .assertEqual (timeseries [0 ], (LastValueAggregator , "testname" , 5 ))
139
246
140
247
# Ensures value observer aggregator is correctly converted to timeseries
141
248
def test_convert_from_value_observer (self ):
142
- pass
249
+ value_observer_record = self ._generate_record (ValueObserverAggregator )
250
+ value_observer_record .aggregator .update (5 )
251
+ value_observer_record .aggregator .update (1 )
252
+ value_observer_record .aggregator .update (2 )
253
+ value_observer_record .aggregator .take_checkpoint ()
254
+
255
+ self ._exporter .create_timeseries = self ._converter_mock ()
256
+ timeseries = self ._exporter .convert_from_value_observer (
257
+ value_observer_record
258
+ )
259
+ self .assertEqual (
260
+ timeseries [0 ], (ValueObserverAggregator , "testname_min" , 1 )
261
+ )
262
+ self .assertEqual (
263
+ timeseries [1 ], (ValueObserverAggregator , "testname_max" , 5 )
264
+ )
265
+ self .assertEqual (
266
+ timeseries [2 ], (ValueObserverAggregator , "testname_sum" , 8 )
267
+ )
268
+ self .assertEqual (
269
+ timeseries [3 ], (ValueObserverAggregator , "testname_count" , 3 )
270
+ )
271
+ self .assertEqual (
272
+ timeseries [4 ], (ValueObserverAggregator , "testname_last" , 2 )
273
+ )
143
274
144
275
# Ensures quantile aggregator is correctly converted to timeseries
145
276
# TODO: Add test once method is implemented
@@ -148,7 +279,34 @@ def test_convert_from_quantile(self):
148
279
149
280
# Ensures timeseries produced contains appropriate sample and labels
150
281
def test_create_timeseries (self ):
151
- pass
282
+ sum_aggregator = SumAggregator ()
283
+ sum_aggregator .update (5 )
284
+ sum_aggregator .take_checkpoint ()
285
+ sum_aggregator .last_update_timestamp = 10
286
+ export_record = ExportRecord (
287
+ self ._test_metric ,
288
+ get_dict_as_key ({"record_name" : "record_value" }),
289
+ sum_aggregator ,
290
+ Resource ({"resource_name" : "resource_value" }),
291
+ )
292
+
293
+ expected_timeseries = TimeSeries ()
294
+ expected_timeseries .labels .append (
295
+ self ._exporter .create_label ("__name__" , "testname" )
296
+ )
297
+ expected_timeseries .labels .append (
298
+ self ._exporter .create_label ("resource_name" , "resource_value" )
299
+ )
300
+ expected_timeseries .labels .append (
301
+ self ._exporter .create_label ("record_name" , "record_value" )
302
+ )
303
+ expected_timeseries .samples .append (
304
+ self ._exporter .create_sample (10 , 5.0 ),
305
+ )
306
+ timeseries = self ._exporter .create_timeseries (
307
+ export_record , "testname" , 5.0 ,
308
+ )
309
+ self .assertEqual (timeseries , expected_timeseries )
152
310
153
311
154
312
class TestExport (unittest .TestCase ):
0 commit comments