def test_finished_collection_stateless(self): meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(False) aggregator = CounterAggregator() metric = metrics.Counter( "available memory", "available memory", "bytes", int, meter, ("environment",), ) aggregator.update(1.0) labels = () _batch_map = {} _batch_map[(metric, labels)] = aggregator batcher._batch_map = _batch_map batcher.finished_collection() self.assertEqual(len(batcher._batch_map), 0)
def test_export(self,): record = MetricRecord( CounterAggregator(), self._test_labels, self._test_metric ) exporter = self._exporter with mock.patch( "azure_monitor.export.metrics.AzureMonitorMetricsExporter._transmit" ) as transmit: # noqa: E501 transmit.return_value = ExportResult.SUCCESS result = exporter.export([record]) self.assertEqual(result, MetricsExportResult.SUCCESS)
def test_export_exception(self, logger_mock): record = MetricRecord(CounterAggregator(), self._test_labels, self._test_metric) exporter = self._exporter with mock.patch( "azure_monitor.export.metrics.AzureMonitorMetricsExporter._transmit", throw(Exception), ): # noqa: E501 result = exporter.export([record]) self.assertEqual(result, MetricsExportResult.FAILED_NOT_RETRYABLE) self.assertEqual(logger_mock.exception.called, True)
def test_export(self): with self._registry_register_patch: record = MetricRecord( self._test_metric, self._labels_key, CounterAggregator(), ) exporter = PrometheusMetricsExporter() result = exporter.export([record]) # pylint: disable=protected-access self.assertEqual(len(exporter._collector._metrics_to_export), 1) self.assertIs(result, MetricsExportResult.SUCCESS)
def test_counter_to_prometheus(self): meter = get_meter_provider().get_meter(__name__) metric = meter.create_metric( "test@name", "testdesc", "unit", int, metrics.Counter, ["environment@", "os"], ) kvp = {"environment@": "staging", "os": "Windows"} label_set = meter.get_label_set(kvp) aggregator = CounterAggregator() aggregator.update(123) aggregator.take_checkpoint() record = MetricRecord(aggregator, label_set, metric) collector = CustomCollector("testprefix") collector.add_metrics_data([record]) for prometheus_metric in collector.collect(): self.assertEqual(type(prometheus_metric), CounterMetricFamily) self.assertEqual(prometheus_metric.name, "testprefix_test_name") self.assertEqual(prometheus_metric.documentation, "testdesc") self.assertTrue(len(prometheus_metric.samples) == 1) self.assertEqual(prometheus_metric.samples[0].value, 123) self.assertTrue(len(prometheus_metric.samples[0].labels) == 2) self.assertEqual( prometheus_metric.samples[0].labels["environment_"], "staging") self.assertEqual(prometheus_metric.samples[0].labels["os"], "Windows")
def test_checkpoint_set(self): meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( "available memory", "available memory", "bytes", int, meter, ("environment", ), ) aggregator.update(1.0) label_set = metrics.LabelSet() _batch_map = {} _batch_map[(metric, label_set)] = aggregator batcher._batch_map = _batch_map records = batcher.checkpoint_set() self.assertEqual(len(records), 1) self.assertEqual(records[0].metric, metric) self.assertEqual(records[0].label_set, label_set) self.assertEqual(records[0].aggregator, aggregator)
def test_export_failed_retryable(self): record = MetricRecord(CounterAggregator(), self._test_labels, self._test_metric) exporter = self._exporter with mock.patch( "azure_monitor.export.metrics.AzureMonitorMetricsExporter._transmit" ) as transmit: # noqa: E501 transmit.return_value = ExportResult.FAILED_RETRYABLE storage_mock = mock.Mock() exporter.storage.put = storage_mock result = exporter.export([record]) self.assertEqual(result, MetricsExportResult.FAILED_RETRYABLE) self.assertEqual(storage_mock.call_count, 1)
def test_ungrouped_batcher_process_not_stateful(self): meter = metrics.MeterProvider().get_meter(__name__) batcher = UngroupedBatcher(True) aggregator = CounterAggregator() metric = metrics.Counter( "available memory", "available memory", "bytes", int, meter, ("environment", ), ) labels = () _batch_map = {} aggregator.update(1.0) batcher._batch_map = _batch_map record = metrics.Record(metric, labels, aggregator) batcher.process(record) self.assertEqual(len(batcher._batch_map), 1) self.assertIsNotNone(batcher._batch_map.get((metric, labels))) self.assertEqual(batcher._batch_map.get((metric, labels)).current, 0) self.assertEqual( batcher._batch_map.get((metric, labels)).checkpoint, 1.0)
def test_concurrent_update_and_checkpoint(self): counter = CounterAggregator() checkpoint_total = 0 with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor: fut = executor.submit(self.call_update, counter) while not fut.done(): counter.take_checkpoint() checkpoint_total += counter.checkpoint counter.take_checkpoint() checkpoint_total += counter.checkpoint self.assertEqual(fut.result(), checkpoint_total)
def test_export(self): meter = metrics.MeterProvider().get_meter(__name__) exporter = ConsoleMetricsExporter() metric = metrics.Counter( "available memory", "available memory", "bytes", int, meter, ("environment",), ) labels = {"environment": "staging"} aggregator = CounterAggregator() record = MetricRecord(aggregator, labels, metric) result = '{}(data="{}", labels="{}", value={})'.format( ConsoleMetricsExporter.__name__, metric, labels, aggregator.checkpoint, ) with mock.patch("sys.stdout") as mock_stdout: exporter.export([record]) mock_stdout.write.assert_any_call(result)
def test_metric_to_envelope(self): aggregator = CounterAggregator() aggregator.update(123) aggregator.take_checkpoint() record = MetricRecord( aggregator, self._test_label_set, self._test_metric ) exporter = AzureMonitorMetricsExporter() envelope = exporter.metric_to_envelope(record) self.assertIsInstance(envelope, Envelope) self.assertEqual(envelope.ver, 1) self.assertEqual(envelope.name, "Microsoft.ApplicationInsights.Metric") self.assertEqual( envelope.time, ns_to_iso_str( record.metric.get_handle( record.label_set ).last_update_timestamp ), ) self.assertEqual(envelope.sample_rate, None) self.assertEqual(envelope.seq, None) self.assertEqual(envelope.ikey, "1234abcd-5678-4efa-8abc-1234567890ab") self.assertEqual(envelope.flags, None) self.assertIsInstance(envelope.data, Data) self.assertIsInstance(envelope.data.base_data, MetricData) self.assertEqual(envelope.data.base_data.ver, 2) self.assertEqual(len(envelope.data.base_data.metrics), 1) self.assertEqual(envelope.data.base_data.metrics[0].ns, "testname") self.assertEqual(envelope.data.base_data.metrics[0].name, "testdesc") self.assertEqual(envelope.data.base_data.metrics[0].value, 123) self.assertEqual( envelope.data.base_data.properties["environment"], "staging" ) self.assertIsNotNone(envelope.tags["ai.cloud.role"]) self.assertIsNotNone(envelope.tags["ai.cloud.roleInstance"]) self.assertIsNotNone(envelope.tags["ai.device.id"]) self.assertIsNotNone(envelope.tags["ai.device.locale"]) self.assertIsNotNone(envelope.tags["ai.device.osVersion"]) self.assertIsNotNone(envelope.tags["ai.device.type"]) self.assertIsNotNone(envelope.tags["ai.internal.sdkVersion"])
def test_export(self): client = mock.Mock() exporter = CloudMonitoringMetricsExporter( project_id=self.project_id, client=client ) exporter.project_name = self.project_name exporter.export( [ MetricRecord( MockMetric(), (("label1", "value1"),), UnsupportedAggregator(), ) ] ) client.create_time_series.assert_not_called() client.create_metric_descriptor.return_value = MetricDescriptor( **{ "name": None, "type": "custom.googleapis.com/OpenTelemetry/name", "display_name": "name", "description": "description", "labels": [ LabelDescriptor(key="label1", value_type="STRING"), LabelDescriptor(key="label2", value_type="INT64"), ], "metric_kind": "GAUGE", "value_type": "DOUBLE", } ) counter_one = CounterAggregator() counter_one.checkpoint = 1 counter_one.last_update_timestamp = (WRITE_INTERVAL + 1) * 1e9 exporter.export( [ MetricRecord( MockMetric(), (("label1", "value1"), ("label2", 1),), counter_one, ), MetricRecord( MockMetric(), (("label1", "value2"), ("label2", 2),), counter_one, ), ] ) series1 = TimeSeries() series1.metric.type = "custom.googleapis.com/OpenTelemetry/name" series1.metric.labels["label1"] = "value1" series1.metric.labels["label2"] = "1" point = series1.points.add() point.value.int64_value = 1 point.interval.end_time.seconds = WRITE_INTERVAL + 1 point.interval.end_time.nanos = 0 series2 = TimeSeries() series2.metric.type = "custom.googleapis.com/OpenTelemetry/name" series2.metric.labels["label1"] = "value2" series2.metric.labels["label2"] = "2" point = series2.points.add() point.value.int64_value = 1 point.interval.end_time.seconds = WRITE_INTERVAL + 1 point.interval.end_time.nanos = 0 client.create_time_series.assert_has_calls( [mock.call(self.project_name, [series1, series2])] ) # Attempting to export too soon after another export with the exact # same labels leads to it being dropped counter_two = CounterAggregator() counter_two.checkpoint = 1 counter_two.last_update_timestamp = (WRITE_INTERVAL + 2) * 1e9 exporter.export( [ MetricRecord( MockMetric(), (("label1", "value1"), ("label2", 1),), counter_two, ), MetricRecord( MockMetric(), (("label1", "value2"), ("label2", 2),), counter_two, ), ] ) self.assertEqual(client.create_time_series.call_count, 1) # But exporting with different labels is fine counter_two.checkpoint = 2 exporter.export( [ MetricRecord( MockMetric(), (("label1", "changed_label"), ("label2", 2),), counter_two, ), ] ) series3 = TimeSeries() series3.metric.type = "custom.googleapis.com/OpenTelemetry/name" series3.metric.labels["label1"] = "changed_label" series3.metric.labels["label2"] = "2" point = series3.points.add() point.value.int64_value = 2 point.interval.end_time.seconds = WRITE_INTERVAL + 2 point.interval.end_time.nanos = 0 client.create_time_series.assert_has_calls( [ mock.call(self.project_name, [series1, series2]), mock.call(self.project_name, [series3]), ] )
def test_get_metric_descriptor(self): client = mock.Mock() exporter = CloudMonitoringMetricsExporter( project_id=self.project_id, client=client ) exporter.project_name = self.project_name self.assertIsNone( exporter._get_metric_descriptor( MetricRecord(MockMetric(), (), UnsupportedAggregator()) ) ) record = MetricRecord( MockMetric(), (("label1", "value1"),), CounterAggregator(), ) metric_descriptor = exporter._get_metric_descriptor(record) client.create_metric_descriptor.assert_called_with( self.project_name, MetricDescriptor( **{ "name": None, "type": "custom.googleapis.com/OpenTelemetry/name", "display_name": "name", "description": "description", "labels": [ LabelDescriptor(key="label1", value_type="STRING") ], "metric_kind": "GAUGE", "value_type": "INT64", } ), ) # Getting a cached metric descriptor shouldn't use another call cached_metric_descriptor = exporter._get_metric_descriptor(record) self.assertEqual(client.create_metric_descriptor.call_count, 1) self.assertEqual(metric_descriptor, cached_metric_descriptor) # Drop labels with values that aren't string, int or bool exporter._get_metric_descriptor( MetricRecord( MockMetric(name="name2", value_type=float), ( ("label1", "value1"), ("label2", dict()), ("label3", 3), ("label4", False), ), CounterAggregator(), ) ) client.create_metric_descriptor.assert_called_with( self.project_name, MetricDescriptor( **{ "name": None, "type": "custom.googleapis.com/OpenTelemetry/name2", "display_name": "name2", "description": "description", "labels": [ LabelDescriptor(key="label1", value_type="STRING"), LabelDescriptor(key="label3", value_type="INT64"), LabelDescriptor(key="label4", value_type="BOOL"), ], "metric_kind": "GAUGE", "value_type": "DOUBLE", } ), )
def test_checkpoint(self): counter = CounterAggregator() counter.update(2.0) counter.take_checkpoint() self.assertEqual(counter.current, 0) self.assertEqual(counter.checkpoint, 2.0)
def test_update(self): counter = CounterAggregator() counter.update(1.0) counter.update(2.0) self.assertEqual(counter.current, 3.0)