def test_record_batch(self): meter = metrics.MeterProvider().get_meter(__name__) labels = {"key1": "value1", "key2": "value2", "key3": "value3"} counter = metrics.Counter("name", "desc", "unit", float, meter) valuerecorder = metrics.ValueRecorder( "name", "desc", "unit", float, meter ) counter_v = View(counter, SumAggregator) measure_v = View(valuerecorder, MinMaxSumCountAggregator) meter.register_view(counter_v) meter.register_view(measure_v) record_tuples = [(counter, 1.0), (valuerecorder, 3.0)] meter.record_batch(labels, record_tuples) labels_key = metrics.get_dict_as_key(labels) self.assertEqual( counter.bound_instruments[labels_key] .view_datas.pop() .aggregator.current, 1.0, ) self.assertEqual( valuerecorder.bound_instruments[labels_key] .view_datas.pop() .aggregator.current, (3.0, 3.0, 3.0, 1), )
def test_multiple_views(self): test_counter = self.meter.create_metric( name="test_counter", description="description", unit="By", value_type=int, metric_type=Counter, ) counter_view = View( test_counter, SumAggregator, label_keys=["environment"], view_config=ViewConfig.UNGROUPED, ) mmsc_view = View( test_counter, MinMaxSumCountAggregator, label_keys=["environment"], view_config=ViewConfig.LABEL_KEYS, ) self.meter.register_view(counter_view) self.meter.register_view(mmsc_view) test_counter.add(6, {"environment": "production", "customer_id": 123}) test_counter.add(5, {"environment": "production", "customer_id": 247}) self.controller.tick() metric_data = self.exporter.get_exported_metrics() sum_set = set() mmsc_set = set() for data in metric_data: if isinstance(data.aggregator, SumAggregator): tup = (data.labels, data.aggregator.checkpoint) sum_set.add(tup) elif isinstance(data.aggregator, MinMaxSumCountAggregator): mmsc_set.add(data) self.assertEqual(data.labels, (("environment", "production"), )) self.assertEqual(data.aggregator.checkpoint.sum, 11) # we have to assert this way because order is unknown self.assertEqual(len(sum_set), 2) self.assertEqual(len(mmsc_set), 1) label1 = (("customer_id", 123), ("environment", "production")) label2 = (("customer_id", 247), ("environment", "production")) self.assertTrue((label1, 6) in sum_set) self.assertTrue((label2, 5) in sum_set)
def test_label_keys(self): test_counter = self.meter.create_metric( name="test_counter", description="description", unit="By", value_type=int, metric_type=Counter, ) counter_view = View( test_counter, SumAggregator, label_keys=["environment"], view_config=ViewConfig.LABEL_KEYS, ) self.meter.register_view(counter_view) test_counter.add(6, {"environment": "production", "customer_id": 123}) test_counter.add(5, {"environment": "production", "customer_id": 247}) self.controller.tick() metric_data = self.exporter.get_exported_metrics() self.assertEqual(len(metric_data), 1) self.assertEqual(metric_data[0].labels, (("environment", "production"), )) self.assertEqual(metric_data[0].aggregator.checkpoint, 11)
def test_ungrouped(self): test_counter = self.meter.create_metric( name="test_counter", description="description", unit="By", value_type=int, metric_type=Counter, ) counter_view = View( test_counter, SumAggregator, label_keys=["environment"], view_config=ViewConfig.UNGROUPED, ) self.meter.register_view(counter_view) test_counter.add(6, {"environment": "production", "customer_id": 123}) test_counter.add(5, {"environment": "production", "customer_id": 247}) self.controller.tick() metric_data = self.exporter.get_exported_metrics() data_set = set() for data in metric_data: data_set.add((data.labels, data.aggregator.checkpoint)) self.assertEqual(len(metric_data), 2) label1 = (("customer_id", 123), ("environment", "production")) label2 = (("customer_id", 247), ("environment", "production")) self.assertTrue((label1, 6) in data_set) self.assertTrue((label2, 5) in data_set)
def test_add(self): meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.UpDownCounter("name", "desc", "unit", int, meter) labels = {"key": "value"} bound_counter = metric.bind(labels) counter_v = View(metric, SumAggregator) meter.register_view(counter_v) metric.add(3, labels) metric.add(2, labels) self.assertEqual(bound_counter.view_datas.pop().aggregator.current, 5)
def test_collect_disabled_metric(self): meter = metrics.MeterProvider().get_meter(__name__) processor_mock = Mock() meter.processor = processor_mock counter = metrics.Counter("name", "desc", "unit", float, meter, False) labels = {"key1": "value1"} meter.register_view(View(counter, SumAggregator)) counter.add(1.0, labels) meter.collect() self.assertFalse(processor_mock.process.called)
def test_histogram_stateless(self): # Use the meter type provided by the SDK package meter = metrics.MeterProvider(stateful=False).get_meter(__name__) exporter = InMemoryMetricsExporter() controller = PushController(meter, exporter, 30) requests_size = meter.create_metric( name="requests_size", description="size of requests", unit="1", value_type=int, metric_type=ValueRecorder, ) size_view = View( requests_size, HistogramAggregator, aggregator_config={"bounds": [20, 40, 60, 80, 100]}, label_keys=["environment"], view_config=ViewConfig.LABEL_KEYS, ) meter.register_view(size_view) # Since this is using the HistogramAggregator, the bucket counts will be reflected # with each record requests_size.record(25, {"environment": "staging", "test": "value"}) requests_size.record(1, {"environment": "staging", "test": "value2"}) requests_size.record(200, {"environment": "staging", "test": "value3"}) controller.tick() metrics_list = exporter.get_exported_metrics() self.assertEqual(len(metrics_list), 1) checkpoint = metrics_list[0].aggregator.checkpoint self.assertEqual( tuple(checkpoint.items()), ((20, 1), (40, 1), (60, 0), (80, 0), (100, 0), (inf, 1)), ) exporter.clear() requests_size.record(25, {"environment": "staging", "test": "value"}) requests_size.record(1, {"environment": "staging", "test": "value2"}) requests_size.record(200, {"environment": "staging", "test": "value3"}) controller.tick() metrics_list = exporter.get_exported_metrics() self.assertEqual(len(metrics_list), 1) checkpoint = metrics_list[0].aggregator.checkpoint self.assertEqual( tuple(checkpoint.items()), ((20, 1), (40, 1), (60, 0), (80, 0), (100, 0), (inf, 1)), )
def test_collect_metrics(self): meter = metrics.MeterProvider().get_meter(__name__) batcher_mock = mock.Mock() meter.batcher = batcher_mock counter = meter.create_metric("name", "desc", "unit", float, metrics.Counter) labels = {"key1": "value1"} meter.register_view(View(counter, SumAggregator)) counter.add(1.0, labels) meter.collect() self.assertTrue(batcher_mock.process.called)
def test_add_non_decreasing_int_error(self, logger_mock): meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.Counter("name", "desc", "unit", int, meter) labels = {"key": "value"} counter_v = View(metric, SumAggregator) meter.register_view(counter_v) bound_counter = metric.bind(labels) metric.add(3, labels) metric.add(0, labels) metric.add(-1, labels) self.assertEqual(bound_counter.view_datas.pop().aggregator.current, 3) self.assertEqual(logger_mock.warning.call_count, 1)
def test_record(self): meter = metrics.MeterProvider().get_meter(__name__) metric = metrics.ValueRecorder("name", "desc", "unit", int, meter) labels = {"key": "value"} measure_v = View(metric, MinMaxSumCountAggregator) bound_valuerecorder = metric.bind(labels) meter.register_view(measure_v) values = (37, 42, 7) for val in values: metric.record(val, labels) self.assertEqual( bound_valuerecorder.view_datas.pop().aggregator.current, (min(values), max(values), sum(values), len(values)), )
requests_size = meter.create_valuerecorder( name="requests_size", description="size of requests", unit="1", value_type=int, ) # Views are used to define an aggregation type and label keys to aggregate by # for a given metric # Two views with the same metric and aggregation type but different label keys # With ViewConfig.LABEL_KEYS, all labels but the ones defined in label_keys are # dropped from the aggregation counter_view1 = View( requests_counter, SumAggregator, label_keys=["environment"], view_config=ViewConfig.LABEL_KEYS, ) counter_view2 = View( requests_counter, MinMaxSumCountAggregator, label_keys=["os_type"], view_config=ViewConfig.LABEL_KEYS, ) # This view has ViewConfig set to UNGROUPED, meaning all recorded metrics take # the labels directly without and consideration for label_keys counter_view3 = View( requests_counter, LastValueAggregator, label_keys=["environment"], # is not used due to ViewConfig.UNGROUPED view_config=ViewConfig.UNGROUPED,
description="ram usage", unit="1", value_type=float, ) meter.register_valueobserver( callback=get_cpu_usage_callback, name="cpu_percent", description="per-cpu usage", unit="1", value_type=float, ) counter_view1 = View( requests_counter, SumAggregator, label_keys=["environment"], view_config=ViewConfig.LABEL_KEYS, ) counter_view2 = View( request_min_max, MinMaxSumCountAggregator, label_keys=["os_type"], view_config=ViewConfig.LABEL_KEYS, ) counter_view3 = View( request_last_value, LastValueAggregator, label_keys=["environment"], view_config=ViewConfig.UNGROUPED, )