Support time range to query dimension names/values
At present, dimensions are not scoped by time window, which makes dimension related queries to large databases timeout because it searches all of time instead of a time window specified on the grafana app. This commit adds tempest tests to accompany the changes to the API server and as such, depends on it. Depends-On: https://review.opendev.org/#/c/670318/ Change-Id: Ibc5378deea51a18ed7dac857b26d770950b17620 Story: 2006204 Task: 35805
This commit is contained in:
parent
cc0581fcab
commit
9734af4fe8
|
@ -31,47 +31,73 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
@classmethod
|
@classmethod
|
||||||
def resource_setup(cls):
|
def resource_setup(cls):
|
||||||
super(TestDimensions, cls).resource_setup()
|
super(TestDimensions, cls).resource_setup()
|
||||||
|
start_timestamp = int(round(time.time() * 1000))
|
||||||
|
start_time_iso = helpers.timestamp_to_iso(start_timestamp)
|
||||||
|
# NOTE (brtknr): use interval of a day because the tag based queries
|
||||||
|
# appear to only support smallest granularity of a day, and disregard
|
||||||
|
# time of day, which is fine for most use cases.
|
||||||
|
day = 60 * 60 * 24 * 1000
|
||||||
|
end_timestamp = start_timestamp + 10 * day
|
||||||
|
end_time_iso = helpers.timestamp_to_iso(end_timestamp)
|
||||||
|
|
||||||
metric_name1 = data_utils.rand_name()
|
metric_name1 = data_utils.rand_name()
|
||||||
name1 = "name_1"
|
name1 = "name_1"
|
||||||
name2 = "name_2"
|
name2 = "name_2"
|
||||||
value1 = "value_1"
|
value1 = "value_1"
|
||||||
value2 = "value_2"
|
value2 = "value_2"
|
||||||
|
timestamp1 = start_timestamp - day
|
||||||
timestamp = int(round(time.time() * 1000))
|
timestamp2 = start_timestamp + day
|
||||||
time_iso = helpers.timestamp_to_iso(timestamp)
|
timestamp3 = start_timestamp + day + day
|
||||||
|
timestamp4 = end_timestamp + day
|
||||||
metric1 = helpers.create_metric(name=metric_name1,
|
metric1 = helpers.create_metric(name=metric_name1,
|
||||||
|
timestamp=timestamp1,
|
||||||
dimensions={name1: value1,
|
dimensions={name1: value1,
|
||||||
name2: value2
|
name2: value2,
|
||||||
})
|
})
|
||||||
cls.monasca_client.create_metrics(metric1)
|
cls.monasca_client.create_metrics(metric1)
|
||||||
metric1 = helpers.create_metric(name=metric_name1,
|
metric1 = helpers.create_metric(name=metric_name1,
|
||||||
|
timestamp=timestamp2,
|
||||||
dimensions={name1: value2})
|
dimensions={name1: value2})
|
||||||
cls.monasca_client.create_metrics(metric1)
|
cls.monasca_client.create_metrics(metric1)
|
||||||
|
|
||||||
metric_name2 = data_utils.rand_name()
|
metric_name2 = data_utils.rand_name()
|
||||||
name3 = "name_3"
|
name3 = "name_3"
|
||||||
value3 = "value_3"
|
value3 = "value_3"
|
||||||
|
value4 = "value_4"
|
||||||
metric2 = helpers.create_metric(name=metric_name2,
|
metric2 = helpers.create_metric(name=metric_name2,
|
||||||
dimensions={name3: value3})
|
timestamp=timestamp3,
|
||||||
|
dimensions={name1: value3,
|
||||||
|
name3: value4,
|
||||||
|
})
|
||||||
cls.monasca_client.create_metrics(metric2)
|
cls.monasca_client.create_metrics(metric2)
|
||||||
|
|
||||||
metric_name3 = data_utils.rand_name()
|
metric_name3 = data_utils.rand_name()
|
||||||
metric3 = helpers.create_metric(name=metric_name3,
|
metric3 = helpers.create_metric(name=metric_name3,
|
||||||
dimensions={name1: value3})
|
timestamp=timestamp4,
|
||||||
|
dimensions={name2: value3})
|
||||||
cls.monasca_client.create_metrics(metric3)
|
cls.monasca_client.create_metrics(metric3)
|
||||||
|
|
||||||
cls._test_metric1 = metric1
|
cls._test_metric1 = metric1
|
||||||
cls._test_metric2 = metric2
|
cls._test_metric2 = metric2
|
||||||
cls._test_metric_names = {metric_name1, metric_name2, metric_name3}
|
cls._test_metric_names = {metric_name1, metric_name2, metric_name3}
|
||||||
cls._dim_names_metric1 = [name1, name2]
|
cls._dim_names_metric1 = [name1, name2]
|
||||||
cls._dim_names_metric2 = [name3]
|
cls._dim_names_metric1_in_timerange = [name1]
|
||||||
cls._dim_names = cls._dim_names_metric1 + cls._dim_names_metric2
|
cls._dim_names_metric2 = [name1, name3]
|
||||||
cls._dim_values_for_metric1 = [value1, value2]
|
cls._dim_names_metric2_in_timerange = [name1, name3]
|
||||||
cls._dim_values = [value1, value2, value3]
|
cls._dim_names = sorted(set(cls._dim_names_metric1
|
||||||
|
+ cls._dim_names_metric2))
|
||||||
|
cls._dim_names_in_timerange = sorted(set(
|
||||||
|
cls._dim_names_metric1_in_timerange
|
||||||
|
+ cls._dim_names_metric2_in_timerange))
|
||||||
|
cls._dim_name1 = name1
|
||||||
|
cls._dim_name1_values_for_metric1 = [value1, value2]
|
||||||
|
cls._dim_name1_values_for_metric1_in_timerange = [value2]
|
||||||
|
cls._dim_name1_values = [value1, value2, value3]
|
||||||
|
cls._dim_name1_values_in_timerange = [value2, value3]
|
||||||
|
cls._start_time = start_time_iso
|
||||||
|
cls._end_time = end_time_iso
|
||||||
|
|
||||||
param = '?start_time=' + time_iso
|
param = '?start_time=' + start_time_iso
|
||||||
returned_name_set = set()
|
returned_name_set = set()
|
||||||
for i in range(constants.MAX_RETRIES):
|
for i in range(constants.MAX_RETRIES):
|
||||||
resp, response_body = cls.monasca_client.list_metrics(
|
resp, response_body = cls.monasca_client.list_metrics(
|
||||||
|
@ -94,32 +120,62 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
def resource_cleanup(cls):
|
def resource_cleanup(cls):
|
||||||
super(TestDimensions, cls).resource_cleanup()
|
super(TestDimensions, cls).resource_cleanup()
|
||||||
|
|
||||||
@decorators.attr(type='gate')
|
def _test_list_dimension_values_without_metric_name(self, timerange):
|
||||||
def test_list_dimension_values_without_metric_name(self):
|
param = '?dimension_name=' + self._dim_name1
|
||||||
param = '?dimension_name=' + self._dim_names[0]
|
if timerange:
|
||||||
|
param += '&start_time=' + self._start_time
|
||||||
|
param += '&end_time=' + self._end_time
|
||||||
resp, response_body = self.monasca_client.list_dimension_values(param)
|
resp, response_body = self.monasca_client.list_dimension_values(param)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue({'links', 'elements'} == set(response_body))
|
self.assertTrue({'links', 'elements'} == set(response_body))
|
||||||
response_values_length = len(response_body['elements'])
|
response_values_length = len(response_body['elements'])
|
||||||
values = [str(response_body['elements'][i]['dimension_value'])
|
values = [str(response_body['elements'][i]['dimension_value'])
|
||||||
for i in range(response_values_length)]
|
for i in range(response_values_length)]
|
||||||
self.assertEqual(values, self._dim_values)
|
if timerange:
|
||||||
|
self.assertEqual(values, self._dim_name1_values_in_timerange)
|
||||||
|
else:
|
||||||
|
self.assertEqual(values, self._dim_name1_values)
|
||||||
|
|
||||||
@decorators.attr(type='gate')
|
@decorators.attr(type='gate')
|
||||||
def test_list_dimension_values_with_metric_name(self):
|
def test_list_dimension_values_without_metric_name(self):
|
||||||
parms = '?metric_name=' + self._test_metric1['name']
|
self._test_list_dimension_values_without_metric_name(timerange=False)
|
||||||
parms += '&dimension_name=' + self._dim_names[0]
|
|
||||||
resp, response_body = self.monasca_client.list_dimension_values(parms)
|
@decorators.attr(type='gate')
|
||||||
|
@decorators.attr(type='timerange')
|
||||||
|
def test_list_dimension_values_without_metric_name_with_timerange(self):
|
||||||
|
self._test_list_dimension_values_without_metric_name(timerange=True)
|
||||||
|
|
||||||
|
def _test_list_dimension_values_with_metric_name(self, timerange):
|
||||||
|
param = '?metric_name=' + self._test_metric1['name']
|
||||||
|
param += '&dimension_name=' + self._dim_name1
|
||||||
|
if timerange:
|
||||||
|
param += '&start_time=' + self._start_time
|
||||||
|
param += '&end_time=' + self._end_time
|
||||||
|
resp, response_body = self.monasca_client.list_dimension_values(param)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue({'links', 'elements'} == set(response_body))
|
self.assertTrue({'links', 'elements'} == set(response_body))
|
||||||
response_values_length = len(response_body['elements'])
|
response_values_length = len(response_body['elements'])
|
||||||
values = [str(response_body['elements'][i]['dimension_value'])
|
values = [str(response_body['elements'][i]['dimension_value'])
|
||||||
for i in range(response_values_length)]
|
for i in range(response_values_length)]
|
||||||
self.assertEqual(values, self._dim_values_for_metric1)
|
if timerange:
|
||||||
|
self.assertEqual(values, self._dim_name1_values_for_metric1_in_timerange)
|
||||||
|
else:
|
||||||
|
self.assertEqual(values, self._dim_name1_values_for_metric1)
|
||||||
|
|
||||||
@decorators.attr(type='gate')
|
@decorators.attr(type='gate')
|
||||||
def test_list_dimension_values_limit_and_offset(self):
|
def test_list_dimension_values_with_metric_name(self):
|
||||||
param = '?dimension_name=' + self._dim_names[0]
|
self._test_list_dimension_values_with_metric_name(timerange=False)
|
||||||
|
|
||||||
|
@decorators.attr(type='gate')
|
||||||
|
@decorators.attr(type='timerange')
|
||||||
|
def test_list_dimension_values_with_metric_name_with_timerange(self):
|
||||||
|
self._test_list_dimension_values_with_metric_name(timerange=True)
|
||||||
|
|
||||||
|
def _test_list_dimension_values_limit_and_offset(self, timerange):
|
||||||
|
param = '?dimension_name=' + self._dim_name1
|
||||||
|
if timerange:
|
||||||
|
param += '&start_time=' + self._start_time
|
||||||
|
param += '&end_time=' + self._end_time
|
||||||
resp, response_body = self.monasca_client.list_dimension_values(param)
|
resp, response_body = self.monasca_client.list_dimension_values(param)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
elements = response_body['elements']
|
elements = response_body['elements']
|
||||||
|
@ -134,14 +190,16 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
num_expected_elements = num_dim_values - start_index
|
num_expected_elements = num_dim_values - start_index
|
||||||
|
|
||||||
these_params = list(params)
|
these_params = list(params)
|
||||||
# If not the first call, use the offset returned by the last
|
# Use the offset returned by the last call if available
|
||||||
# call
|
|
||||||
if offset:
|
if offset:
|
||||||
these_params.extend([('offset', str(offset))])
|
these_params.extend([('offset', str(offset))])
|
||||||
query_parms = '?dimension_name=' + self._dim_names[0] + '&' + \
|
query_param = '?dimension_name=' + self._dim_name1
|
||||||
urlencode(these_params)
|
if timerange:
|
||||||
|
query_param += '&start_time=' + self._start_time
|
||||||
|
query_param += '&end_time=' + self._end_time
|
||||||
|
query_param += '&' + urlencode(these_params)
|
||||||
resp, response_body = \
|
resp, response_body = \
|
||||||
self.monasca_client.list_dimension_values(query_parms)
|
self.monasca_client.list_dimension_values(query_param)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
if not response_body['elements']:
|
if not response_body['elements']:
|
||||||
self.fail("No metrics returned")
|
self.fail("No metrics returned")
|
||||||
|
@ -164,6 +222,15 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
# Get the next set
|
# Get the next set
|
||||||
offset = self._get_offset(response_body)
|
offset = self._get_offset(response_body)
|
||||||
|
|
||||||
|
@decorators.attr(type='gate')
|
||||||
|
def test_list_dimension_values_limit_and_offset(self):
|
||||||
|
self._test_list_dimension_values_limit_and_offset(timerange=False)
|
||||||
|
|
||||||
|
@decorators.attr(type='gate')
|
||||||
|
@decorators.attr(type='timerange')
|
||||||
|
def test_list_dimension_values_limit_and_offset_with_timerange(self):
|
||||||
|
self._test_list_dimension_values_limit_and_offset(timerange=True)
|
||||||
|
|
||||||
@decorators.attr(type='gate')
|
@decorators.attr(type='gate')
|
||||||
@decorators.attr(type=['negative'])
|
@decorators.attr(type=['negative'])
|
||||||
def test_list_dimension_values_no_dimension_name(self):
|
def test_list_dimension_values_no_dimension_name(self):
|
||||||
|
@ -183,9 +250,23 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
@decorators.attr(type='gate')
|
@decorators.attr(type='gate')
|
||||||
def test_list_dimension_names_with_metric_name(self):
|
def test_list_dimension_names_with_metric_name(self):
|
||||||
self._test_list_dimension_names_with_metric_name(
|
self._test_list_dimension_names_with_metric_name(
|
||||||
self._test_metric1['name'], self._dim_names_metric1)
|
self._test_metric1['name'], self._dim_names_metric1,
|
||||||
|
timerange=False)
|
||||||
self._test_list_dimension_names_with_metric_name(
|
self._test_list_dimension_names_with_metric_name(
|
||||||
self._test_metric2['name'], self._dim_names_metric2)
|
self._test_metric2['name'], self._dim_names_metric2,
|
||||||
|
timerange=False)
|
||||||
|
|
||||||
|
@decorators.attr(type='gate')
|
||||||
|
@decorators.attr(type='timerange')
|
||||||
|
def test_list_dimension_names_with_metric_name_with_timerange(self):
|
||||||
|
self._test_list_dimension_names_with_metric_name(
|
||||||
|
self._test_metric1['name'],
|
||||||
|
self._dim_names_metric1_in_timerange,
|
||||||
|
timerange=True)
|
||||||
|
self._test_list_dimension_names_with_metric_name(
|
||||||
|
self._test_metric2['name'],
|
||||||
|
self._dim_names_metric2_in_timerange,
|
||||||
|
timerange=True)
|
||||||
|
|
||||||
@decorators.attr(type='gate')
|
@decorators.attr(type='gate')
|
||||||
def test_list_dimension_names_limit_and_offset(self):
|
def test_list_dimension_names_limit_and_offset(self):
|
||||||
|
@ -207,9 +288,9 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
# call
|
# call
|
||||||
if offset:
|
if offset:
|
||||||
these_params.extend([('offset', str(offset))])
|
these_params.extend([('offset', str(offset))])
|
||||||
query_parms = '?' + urlencode(these_params)
|
query_param = '?' + urlencode(these_params)
|
||||||
resp, response_body = self.monasca_client.list_dimension_names(
|
resp, response_body = self.monasca_client.list_dimension_names(
|
||||||
query_parms)
|
query_param)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
if not response_body['elements']:
|
if not response_body['elements']:
|
||||||
self.fail("No metrics returned")
|
self.fail("No metrics returned")
|
||||||
|
@ -236,11 +317,15 @@ class TestDimensions(base.BaseMonascaTest):
|
||||||
@decorators.attr(type=['negative'])
|
@decorators.attr(type=['negative'])
|
||||||
def test_list_dimension_names_with_wrong_metric_name(self):
|
def test_list_dimension_names_with_wrong_metric_name(self):
|
||||||
self._test_list_dimension_names_with_metric_name(
|
self._test_list_dimension_names_with_metric_name(
|
||||||
'wrong_metric_name', [])
|
'wrong_metric_name', [], timerange=False)
|
||||||
|
|
||||||
def _test_list_dimension_names_with_metric_name(self, metric_name,
|
def _test_list_dimension_names_with_metric_name(self, metric_name,
|
||||||
dimension_names):
|
dimension_names,
|
||||||
|
timerange):
|
||||||
param = '?metric_name=' + metric_name
|
param = '?metric_name=' + metric_name
|
||||||
|
if timerange:
|
||||||
|
param += '&start_time=' + self._start_time
|
||||||
|
param += '&end_time=' + self._end_time
|
||||||
resp, response_body = self.monasca_client.list_dimension_names(param)
|
resp, response_body = self.monasca_client.list_dimension_names(param)
|
||||||
self.assertEqual(200, resp.status)
|
self.assertEqual(200, resp.status)
|
||||||
self.assertTrue(set(['links', 'elements']) == set(response_body))
|
self.assertTrue(set(['links', 'elements']) == set(response_body))
|
||||||
|
|
Loading…
Reference in New Issue