diff --git a/gcloud/monitoring/client.py b/gcloud/monitoring/client.py index 633740a36cb1..21ff9189b731 100644 --- a/gcloud/monitoring/client.py +++ b/gcloud/monitoring/client.py @@ -131,26 +131,36 @@ def fetch_metric_descriptor(self, metric_type): """ return MetricDescriptor._fetch(self, metric_type) - def list_metric_descriptors(self, filter_string=None): + def list_metric_descriptors(self, filter_string=None, type_prefix=None): """List all metric descriptors for the project. - Example:: + Examples:: >>> for descriptor in client.list_metric_descriptors(): ... print(descriptor.type) + >>> for descriptor in client.list_metric_descriptors( + ... type_prefix='custom.'): + ... print(descriptor.type) + :type filter_string: string or None :param filter_string: An optional filter expression describing the metric descriptors to be returned. See the `filter documentation`_. + :type type_prefix: string or None + :param type_prefix: An optional prefix constraining the selected + metric types. This adds ``metric.type = starts_with("")`` + to the filter. + :rtype: list of :class:`~gcloud.monitoring.metric.MetricDescriptor` :returns: A list of metric descriptor instances. .. _filter documentation: https://cloud.google.com/monitoring/api/v3/filters """ - return MetricDescriptor._list(self, filter_string) + return MetricDescriptor._list(self, filter_string, + type_prefix=type_prefix) def fetch_resource_descriptor(self, resource_type): """Look up a resource descriptor by type. diff --git a/gcloud/monitoring/metric.py b/gcloud/monitoring/metric.py index a6c3f3eae82d..dedf22c161fb 100644 --- a/gcloud/monitoring/metric.py +++ b/gcloud/monitoring/metric.py @@ -132,7 +132,7 @@ def _fetch(cls, client, metric_type): return cls._from_dict(info) @classmethod - def _list(cls, client, filter_string=None): + def _list(cls, client, filter_string=None, type_prefix=None): """List all metric descriptors for the project. :type client: :class:`gcloud.monitoring.client.Client` @@ -143,6 +143,11 @@ def _list(cls, client, filter_string=None): An optional filter expression describing the metric descriptors to be returned. See the `filter documentation`_. + :type type_prefix: string or None + :param type_prefix: An optional prefix constraining the selected + metric types. This adds ``metric.type = starts_with("")`` + to the filter. + :rtype: list of :class:`MetricDescriptor` :returns: A list of metric descriptor instances. @@ -152,14 +157,21 @@ def _list(cls, client, filter_string=None): path = '/projects/{project}/metricDescriptors/'.format( project=client.project) - descriptors = [] + filters = [] + if filter_string is not None: + filters.append(filter_string) + if type_prefix is not None: + filters.append('metric.type = starts_with("{prefix}")'.format( + prefix=type_prefix)) + + descriptors = [] page_token = None while True: params = {} - if filter_string is not None: - params['filter'] = filter_string + if filters: + params['filter'] = ' AND '.join(filters) if page_token is not None: params['pageToken'] = page_token diff --git a/gcloud/monitoring/test_metric.py b/gcloud/monitoring/test_metric.py index 19e6f76cba78..544d10a450cf 100644 --- a/gcloud/monitoring/test_metric.py +++ b/gcloud/monitoring/test_metric.py @@ -321,6 +321,28 @@ def test_list_filtered(self): 'query_params': {'filter': FILTER}} self.assertEqual(request, expected_request) + def test_list_filtered_by_type_prefix(self): + PROJECT = 'my-project' + PATH = 'projects/{project}/metricDescriptors/'.format(project=PROJECT) + + # Request only custom metrics. + PREFIX = 'custom.googleapis.com/' + FILTER = 'metric.type = starts_with("{prefix}")'.format(prefix=PREFIX) + + # But let's say there are no custom metrics. + RESPONSE = {'metricDescriptors': []} + + connection = _Connection(RESPONSE) + client = _Client(project=PROJECT, connection=connection) + descriptors = self._getTargetClass()._list(client, type_prefix=PREFIX) + + self.assertEqual(len(descriptors), 0) + + request, = connection._requested + expected_request = {'method': 'GET', 'path': '/' + PATH, + 'query_params': {'filter': FILTER}} + self.assertEqual(request, expected_request) + class TestMetric(unittest2.TestCase): diff --git a/system_tests/monitoring.py b/system_tests/monitoring.py index 5efbe0ce3a7b..35a34f9a1692 100644 --- a/system_tests/monitoring.py +++ b/system_tests/monitoring.py @@ -79,6 +79,18 @@ def test_list_metric_descriptors(self): self.assertTrue(label.value_type) self.assertTrue(label.description) + def test_list_metric_descriptors_filtered(self): + client = monitoring.Client() + + PREFIX = 'compute.googleapis.com/' + descriptors = client.list_metric_descriptors(type_prefix=PREFIX) + + # There are currently 18 types with this prefix, but that may change. + self.assertGreater(len(descriptors), 10) + + for descriptor in descriptors: + self.assertTrue(descriptor.type.startswith(PREFIX)) + def test_fetch_resource_descriptor(self): client = monitoring.Client() descriptor = client.fetch_resource_descriptor(RESOURCE_TYPE)