From c13a21a8ae693adb4ff2f25bbf4d1908c0eb84dc Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 2 Aug 2016 15:16:56 +0200 Subject: [PATCH] storage: allow to specify regaggregation over aggregation retrieval Currently, when retrieving e.g. 'mean' aggregation of several metrics, the aggregation of those metrics is always done using 'mean'. This patches allows to specify a reaggregation methods, which applies on top of the measures retrieved. You can know retrieve e.g. the 'max' of the 'mean' of several metrics. Related-Bug: #1573023 Change-Id: I9ea60de498e6f81c738a7236a392019b47b0c269 --- gnocchi/rest/__init__.py | 1 + gnocchi/storage/__init__.py | 3 +++ gnocchi/storage/_carbonara.py | 8 ++++++-- gnocchi/tests/test_storage.py | 10 ++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/gnocchi/rest/__init__.py b/gnocchi/rest/__init__.py index 701fb2fd7..c740383d2 100644 --- a/gnocchi/rest/__init__.py +++ b/gnocchi/rest/__init__.py @@ -483,6 +483,7 @@ class AggregatedMetricController(rest.RestController): else: measures = pecan.request.storage.get_cross_metric_measures( metrics, start, stop, aggregation, + None, granularity, needed_overlap) # Replace timestamp keys by their string versions diff --git a/gnocchi/storage/__init__.py b/gnocchi/storage/__init__.py index 2a5688031..80ed0ae0b 100644 --- a/gnocchi/storage/__init__.py +++ b/gnocchi/storage/__init__.py @@ -267,6 +267,7 @@ class StorageDriver(object): @staticmethod def get_cross_metric_measures(metrics, from_timestamp=None, to_timestamp=None, aggregation='mean', + reaggregation=None, granularity=None, needed_overlap=None): """Get aggregated measures of multiple entities. @@ -276,6 +277,8 @@ class StorageDriver(object): :param to timestamp: The timestamp to get the measure to. :param granularity: The granularity to retrieve. :param aggregation: The type of aggregation to retrieve. + :param reaggregation: The type of aggregation to compute + on the retrieved measures. """ for metric in metrics: if aggregation not in metric.archive_policy.aggregation_methods: diff --git a/gnocchi/storage/_carbonara.py b/gnocchi/storage/_carbonara.py index 17434acf6..44eaae8ec 100644 --- a/gnocchi/storage/_carbonara.py +++ b/gnocchi/storage/_carbonara.py @@ -418,11 +418,15 @@ class CarbonaraBasedStorage(storage.StorageDriver): def get_cross_metric_measures(self, metrics, from_timestamp=None, to_timestamp=None, aggregation='mean', + reaggregation=None, granularity=None, needed_overlap=100.0): super(CarbonaraBasedStorage, self).get_cross_metric_measures( metrics, from_timestamp, to_timestamp, - aggregation, granularity, needed_overlap) + aggregation, reaggregation, granularity, needed_overlap) + + if reaggregation is None: + reaggregation = aggregation if granularity is None: granularities = ( @@ -452,7 +456,7 @@ class CarbonaraBasedStorage(storage.StorageDriver): return [(timestamp.replace(tzinfo=iso8601.iso8601.UTC), r, v) for timestamp, r, v in carbonara.AggregatedTimeSerie.aggregated( - tss, aggregation, from_timestamp, to_timestamp, + tss, reaggregation, from_timestamp, to_timestamp, needed_overlap)] except carbonara.UnAggregableTimeseries as e: raise storage.MetricUnaggregatable(metrics, e.reason) diff --git a/gnocchi/tests/test_storage.py b/gnocchi/tests/test_storage.py index 58936c7da..c5fc78fee 100644 --- a/gnocchi/tests/test_storage.py +++ b/gnocchi/tests/test_storage.py @@ -425,6 +425,16 @@ class TestStorageDriver(tests_base.TestCase): (utils.datetime_utc(2014, 1, 1, 12, 10, 0), 300.0, 24.0) ], values) + values = self.storage.get_cross_metric_measures([self.metric, metric2], + reaggregation='max') + self.assertEqual([ + (utils.datetime_utc(2014, 1, 1, 0, 0, 0), 86400.0, 39.75), + (utils.datetime_utc(2014, 1, 1, 12, 0, 0), 3600.0, 39.75), + (utils.datetime_utc(2014, 1, 1, 12, 0, 0), 300.0, 69), + (utils.datetime_utc(2014, 1, 1, 12, 5, 0), 300.0, 23), + (utils.datetime_utc(2014, 1, 1, 12, 10, 0), 300.0, 44) + ], values) + values = self.storage.get_cross_metric_measures( [self.metric, metric2], from_timestamp=utils.to_timestamp('2014-01-01 12:10:00'))