コード例 #1
0
class MetricsCollectorTests(unittest.TestCase):
    """
    Tests for the MetricCollector collect and sync
    """
    @classmethod
    def setUpClass(cls):
        cls.queue_size = 5

    def setUp(self):
        ServiceRegistry.add_service('test', '0.0.0.0', 0)
        ServiceRegistry._PROXY_CONFIG = {
            'local_port': 1234,
            'cloud_address': 'test',
            'proxy_cloud_connections': True
        }

        self._services = ['test']
        self.gateway_id = "2876171d-bf38-4254-b4da-71a713952904"
        self.timeout = 1
        self._collector = MetricsCollector(self._services,
                                           5,
                                           10,
                                           self.timeout,
                                           grpc_max_msg_size_mb=4,
                                           loop=asyncio.new_event_loop())

    @unittest.mock.patch('magma.magmad.metrics_collector.MetricsControllerStub'
                         )
    def test_sync(self, controller_mock):
        """
        Test if the collector syncs our sample.
        """
        # Mock out Collect.future
        mock = unittest.mock.Mock()
        mock.Collect.future.side_effect = [
            unittest.mock.Mock(),
            unittest.mock.Mock(),
            unittest.mock.Mock()
        ]
        controller_mock.side_effect = [mock, mock, mock]

        # Call with no samples
        service_name = "test"
        self._collector.sync(service_name)
        controller_mock.Collect.future.assert_not_called()
        self._collector._loop.stop()

        # Call with new samples to send
        samples = [MetricFamily(name="1234")]
        self._collector._samples_for_service[service_name].extend(samples)
        with unittest.mock.patch('snowflake.snowflake') as mock_snowflake:
            mock_snowflake.side_effect = lambda: self.gateway_id
            self._collector.sync(service_name)
        mock.Collect.future.assert_called_once_with(
            MetricsContainer(gatewayId=self.gateway_id, family=samples),
            self.timeout)
        self.assertCountEqual(
            self._collector._samples_for_service[service_name], [])

        # Reduce max msg size to trigger msg chunking
        self._collector.grpc_max_msg_size_bytes = 1500
        samples = self._generate_samples(140)
        self._collector._samples_for_service[service_name].extend(samples)
        chunk1 = samples[:70]
        chunk2 = samples[70:140]

        with unittest.mock.patch('snowflake.snowflake') as mock_snowflake:
            mock_snowflake.side_effect = lambda: self.gateway_id
            self._collector.sync(service_name)
        mock.Collect.future.assert_any_call(
            MetricsContainer(gatewayId=self.gateway_id, family=chunk1),
            self.timeout)
        mock.Collect.future.assert_any_call(
            MetricsContainer(gatewayId=self.gateway_id, family=chunk2),
            self.timeout)
        self.assertCountEqual(
            self._collector._samples_for_service[service_name], [])

    def test_collect(self):
        """
        Test if the collector syncs our sample.
        """
        mock = unittest.mock.MagicMock()
        service_name = "test"
        samples = [MetricFamily(name="2345")]
        self._collector._samples_for_service[service_name].clear()
        self._collector._samples_for_service[service_name].extend(samples)
        mock.result.side_effect = [MetricsContainer(family=samples)]
        mock.exception.side_effect = [False]

        self._collector.collect_done('test', mock)
        # Should dequeue sample from the left, and enqueue on right
        # collector should add one more metric for collection success/failure
        self.assertEqual(
            len(self._collector._samples_for_service[service_name]),
            len(samples * 2) + 1)

    def test_collect_start_time(self):
        """
        Test if the collector syncs our sample.
        """
        mock = unittest.mock.MagicMock()
        start_metric = Metric()
        start_metric.gauge.value = calendar.timegm(time.gmtime()) - 1
        start_time = MetricFamily(
            name=str(metricsd_pb2.process_start_time_seconds),
            metric=[start_metric],
        )
        samples = [start_time]
        service_name = "test"
        self._collector._samples_for_service[service_name].clear()
        mock.result.side_effect = [MetricsContainer(family=samples)]
        mock.exception.side_effect = [False]

        self._collector.collect_done('test', mock)

        # should have uptime, start time, and collection success
        self.assertEqual(
            len(self._collector._samples_for_service[service_name]), 3)
        uptime_list = [
            fam for fam in self._collector._samples_for_service[service_name]
            if fam.name == str(metricsd_pb2.process_uptime_seconds)
        ]
        self.assertEqual(len(uptime_list), 1)
        self.assertEqual(len(uptime_list[0].metric), 1)
        self.assertGreater(uptime_list[0].metric[0].gauge.value, 0)

        # ensure no exceptions with empty metric
        empty = MetricFamily(name=str(metricsd_pb2.process_start_time_seconds))
        samples = [empty]
        self._collector._samples_for_service[service_name].clear()
        mock.result.side_effect = [MetricsContainer(family=samples)]
        mock.exception.side_effect = [False]
        try:
            self._collector.collect_done('test', mock)
        except Exception:  # pylint: disable=broad-except
            self.fail("Collection with empty metric should not have failed")

    def test_counter_to_proto(self):
        test_counter = prometheus_client.core.CounterMetricFamily(
            "test",
            "",
            labels=["testLabel"],
        )
        test_counter.add_metric(["val"], 1.23)
        test_counter.add_metric(["val2"], 2.34)

        proto = _counter_to_proto(test_counter)
        self.assertEqual(proto.name, test_counter.name)
        self.assertEqual(proto.type, metrics_pb2.COUNTER)

        self.assertEqual(2, len(proto.metric))
        self.assertEqual("val", proto.metric[0].label[0].value)
        self.assertEqual(1.23, proto.metric[0].counter.value)
        self.assertEqual("val2", proto.metric[1].label[0].value)
        self.assertEqual(2.34, proto.metric[1].counter.value)

    def test_gauge_to_proto(self):
        test_gauge = prometheus_client.core.GaugeMetricFamily(
            "test",
            "",
            labels=["testLabel"],
        )
        test_gauge.add_metric(["val"], 1.23)
        test_gauge.add_metric(["val2"], 2.34)

        proto = _gauge_to_proto(test_gauge)
        self.assertEqual(proto.name, test_gauge.name)
        self.assertEqual(proto.type, metrics_pb2.GAUGE)

        self.assertEqual(2, len(proto.metric))
        self.assertEqual("val", proto.metric[0].label[0].value)
        self.assertEqual(1.23, proto.metric[0].gauge.value)
        self.assertEqual("val2", proto.metric[1].label[0].value)
        self.assertEqual(2.34, proto.metric[1].gauge.value)

    def test_untyped_to_proto(self):
        test_untyped = prometheus_client.core.UntypedMetricFamily(
            "test",
            "",
            labels=["testLabel"],
        )
        test_untyped.add_metric(["val"], 1.23)
        test_untyped.add_metric(["val2"], 2.34)

        proto = _untyped_to_proto(test_untyped)
        self.assertEqual(proto.name, test_untyped.name)
        self.assertEqual(proto.type, metrics_pb2.UNTYPED)

        self.assertEqual(2, len(proto.metric))
        self.assertEqual("val", proto.metric[0].label[0].value)
        self.assertEqual(1.23, proto.metric[0].untyped.value)
        self.assertEqual("val2", proto.metric[1].label[0].value)
        self.assertEqual(2.34, proto.metric[1].untyped.value)

    def test_summary_to_proto(self):
        test_summary = prometheus_client.core.SummaryMetricFamily(
            "test",
            "",
            labels=["testLabel"],
        )
        # Add first unique labelset metrics
        test_summary.add_metric(["val1"], 10, 0.1)
        test_summary.add_sample("test", {
            "quantile": "0.0",
            "testLabel": "val1"
        }, 0.01)
        test_summary.add_sample("test", {
            "quantile": "0.5",
            "testLabel": "val1"
        }, 0.02)
        test_summary.add_sample("test", {
            "quantile": "1.0",
            "testLabel": "val1"
        }, 0.03)

        # Add second unique labelset metrics
        test_summary.add_metric(["val2"], 20, 0.2)
        test_summary.add_sample("test", {
            "quantile": "0.0",
            "testLabel": "val2"
        }, 0.02)
        test_summary.add_sample("test", {
            "quantile": "0.5",
            "testLabel": "val2"
        }, 0.04)
        test_summary.add_sample("test", {
            "quantile": "1.0",
            "testLabel": "val2"
        }, 0.06)

        protos = _summary_to_proto(test_summary)
        self.assertEqual(2, len(protos))

        for proto in protos:
            self.assertEqual(proto.name, test_summary.name)
            self.assertEqual(proto.type, metrics_pb2.SUMMARY)
            if proto.metric[0].label[0].value == "val1":
                self.assertEqual(1, len(proto.metric))
                self.assertEqual(10, proto.metric[0].summary.sample_count)
                self.assertEqual(0.1, proto.metric[0].summary.sample_sum)
                self.assertEqual(3, len(proto.metric[0].summary.quantile))
                self.assertEqual(0.01,
                                 proto.metric[0].summary.quantile[0].value)
                self.assertEqual(0.02,
                                 proto.metric[0].summary.quantile[1].value)
                self.assertEqual(0.03,
                                 proto.metric[0].summary.quantile[2].value)
            else:
                self.assertEqual(1, len(proto.metric))
                self.assertEqual(20, proto.metric[0].summary.sample_count)
                self.assertEqual(0.2, proto.metric[0].summary.sample_sum)
                self.assertEqual(3, len(proto.metric[0].summary.quantile))
                self.assertEqual(0.02,
                                 proto.metric[0].summary.quantile[0].value)
                self.assertEqual(0.04,
                                 proto.metric[0].summary.quantile[1].value)
                self.assertEqual(0.06,
                                 proto.metric[0].summary.quantile[2].value)

    def test_histogram_to_proto(self):
        test_hist = prometheus_client.core.HistogramMetricFamily(
            "test",
            "",
            labels=["testLabel"],
        )
        # Add first unique labelset metrics
        test_hist.add_metric(["val1"], [(1, 1), (10, 2), (100, 3)], 6)

        # Add second unique labelset metrics
        test_hist.add_metric(["val2"], [(1, 2), (10, 3), (100, 4)], 9)

        protos = _histogram_to_proto(test_hist)
        self.assertEqual(2, len(protos))

        for proto in protos:
            self.assertEqual(proto.name, test_hist.name)
            self.assertEqual(proto.type, metrics_pb2.HISTOGRAM)
            if proto.metric[0].label[0].value == "val1":
                self.assertEqual(1, len(proto.metric))
                self.assertEqual(3, proto.metric[0].histogram.sample_count)
                self.assertEqual(6, proto.metric[0].histogram.sample_sum)
                self.assertEqual(3, len(proto.metric[0].histogram.bucket))
                self.assertEqual(
                    1, proto.metric[0].histogram.bucket[0].cumulative_count)
                self.assertEqual(
                    2, proto.metric[0].histogram.bucket[1].cumulative_count)
                self.assertEqual(
                    3, proto.metric[0].histogram.bucket[2].cumulative_count)
            else:
                self.assertEqual(1, len(proto.metric))
                self.assertEqual(4, proto.metric[0].histogram.sample_count)
                self.assertEqual(9, proto.metric[0].histogram.sample_sum)
                self.assertEqual(3, len(proto.metric[0].histogram.bucket))
                self.assertEqual(
                    2, proto.metric[0].histogram.bucket[0].cumulative_count)
                self.assertEqual(
                    3, proto.metric[0].histogram.bucket[1].cumulative_count)
                self.assertEqual(
                    4, proto.metric[0].histogram.bucket[2].cumulative_count)

    def _generate_samples(self, number):
        samples = []
        for _ in range(number):
            sample_name = randrange(10000)
            samples.append(MetricFamily(name=str(sample_name)))
        return samples
コード例 #2
0
ファイル: collector_tests.py プロジェクト: stjordanis/magma-1
class MetricsCollectorTests(unittest.TestCase):
    """
    Tests for the MetricCollector collect and sync
    """
    @classmethod
    def setUpClass(cls):
        cls.queue_size = 5

    def setUp(self):
        ServiceRegistry.add_service('test', '0.0.0.0', 0)
        ServiceRegistry._PROXY_CONFIG = {
            'local_port': 1234,
            'cloud_address': 'test',
            'proxy_cloud_connections': True
        }

        self._services = ['test']
        self.gateway_id = "2876171d-bf38-4254-b4da-71a713952904"
        self.queue_length = 5
        self.timeout = 1
        self._collector = MetricsCollector(self._services,
                                           5,
                                           10,
                                           self.timeout,
                                           queue_length=self.queue_length,
                                           loop=asyncio.new_event_loop())

    @unittest.mock.patch('magma.magmad.metrics_collector.MetricsControllerStub'
                         )
    def test_sync(self, controller_mock):
        """
        Test if the collector syncs our sample.
        """
        # Mock out Collect.future
        mock = unittest.mock.Mock()
        mock.Collect.future.side_effect = [unittest.mock.Mock()]
        controller_mock.side_effect = [mock]

        # Call with no samples
        self._collector.sync()
        controller_mock.Collect.future.assert_not_called()
        self._collector._loop.stop()

        # Call with new samples to send and some to retry
        samples = [MetricFamily(name="1234")]
        self._collector._samples.extend(samples)
        self._collector._retry_queue.extend(samples)
        with unittest.mock.patch('snowflake.snowflake') as mock_snowflake:
            mock_snowflake.side_effect = lambda: self.gateway_id
            self._collector.sync()
        mock.Collect.future.assert_called_once_with(
            MetricsContainer(gatewayId=self.gateway_id, family=samples * 2),
            self.timeout)
        self.assertCountEqual(self._collector._samples, [])
        self.assertCountEqual(self._collector._retry_queue, [])

    def test_sync_queue(self):
        """
        Test if the sync queues items on failure
        """
        # We should retry sending the newest samples
        samples = [
            MetricFamily(name=str(i)) for i in range(self.queue_length + 1)
        ]
        mock_future = MockFuture(is_error=True)
        self._collector.sync_done(samples, mock_future)
        self.assertCountEqual(self._collector._samples, [])
        self.assertCountEqual(self._collector._retry_queue,
                              samples[-self.queue_length:])

        # On success don't retry to send
        self._collector._retry_queue.clear()
        mock_future = MockFuture(is_error=False)
        self._collector.sync_done(samples, mock_future)
        self.assertCountEqual(self._collector._samples, [])
        self.assertCountEqual(self._collector._retry_queue, [])

    def test_collect(self):
        """
        Test if the collector syncs our sample.
        """
        mock = unittest.mock.MagicMock()
        samples = [MetricFamily(name="2345")]
        self._collector._samples.clear()
        self._collector._samples.extend(samples)
        mock.result.side_effect = [MetricsContainer(family=samples)]
        mock.exception.side_effect = [False]

        self._collector.collect_done('test', mock)
        # Should dequeue sample from the left, and enqueue on right
        # collector should add one more metric for collection success/failure
        self.assertEqual(len(self._collector._samples), len(samples * 2) + 1)

    def test_collect_start_time(self):
        """
        Test if the collector syncs our sample.
        """
        mock = unittest.mock.MagicMock()
        start_metric = Metric()
        start_metric.gauge.value = calendar.timegm(time.gmtime()) - 1
        start_time = MetricFamily(
            name=str(metricsd_pb2.process_start_time_seconds),
            metric=[start_metric],
        )
        samples = [start_time]
        self._collector._samples.clear()
        mock.result.side_effect = [MetricsContainer(family=samples)]
        mock.exception.side_effect = [False]

        self._collector.collect_done('test', mock)

        # should have uptime, start time, and collection success
        self.assertEqual(len(self._collector._samples), 3)
        uptime_list = [
            fam for fam in self._collector._samples
            if fam.name == str(metricsd_pb2.process_uptime_seconds)
        ]
        self.assertEqual(len(uptime_list), 1)
        self.assertEqual(len(uptime_list[0].metric), 1)
        self.assertGreater(uptime_list[0].metric[0].gauge.value, 0)

        # ensure no exceptions with empty metric
        empty = MetricFamily(name=str(metricsd_pb2.process_start_time_seconds))
        samples = [empty]
        self._collector._samples.clear()
        mock.result.side_effect = [MetricsContainer(family=samples)]
        mock.exception.side_effect = [False]
        try:
            self._collector.collect_done('test', mock)
        except Exception:  # pylint: disable=broad-except
            self.fail("Collection with empty metric should not have failed")