From bd4093b8ce9b3ecfd3cd1bee9a51d79da9075ca8 Mon Sep 17 00:00:00 2001 From: Gordon Chung Date: Wed, 31 Jul 2013 12:08:26 -0400 Subject: [PATCH] add unit attribute to statistics statistics currently aren't associated with a unit it just provides sum, average, etc... values without a unit context Fixes: Bug#1204458 Change-Id: Ib92a6a2ab5899a0b269424e94468a73b6559deda --- ceilometer/api/controllers/v2.py | 6 +++++- ceilometer/storage/impl_hbase.py | 4 +++- ceilometer/storage/impl_mongodb.py | 9 ++++++--- ceilometer/storage/impl_sqlalchemy.py | 2 ++ ceilometer/storage/models.py | 5 +++-- .../v1/test_compute_duration_by_resource_scenarios.py | 1 + .../v2/test_compute_duration_by_resource_scenarios.py | 3 +++ tests/storage/base.py | 5 +++++ 8 files changed, 28 insertions(+), 7 deletions(-) diff --git a/ceilometer/api/controllers/v2.py b/ceilometer/api/controllers/v2.py index 3a9ef263f..41f71ea96 100644 --- a/ceilometer/api/controllers/v2.py +++ b/ceilometer/api/controllers/v2.py @@ -365,6 +365,9 @@ class Statistics(_Base): """Computed statistics for a query. """ + unit = wtypes.text + "The unit type of the data set" + min = float "The minimum volume seen in the data" @@ -436,7 +439,8 @@ class Statistics(_Base): @classmethod def sample(cls): - return cls(min=1, + return cls(unit='GiB', + min=1, max=9, avg=4.5, sum=45, diff --git a/ceilometer/storage/impl_hbase.py b/ceilometer/storage/impl_hbase.py index 84c1fd8d3..e4f918882 100644 --- a/ceilometer/storage/impl_hbase.py +++ b/ceilometer/storage/impl_hbase.py @@ -462,6 +462,7 @@ class Connection(base.Connection): """ vol = int(meter['f:counter_volume']) ts = timeutils.parse_strtime(meter['f:timestamp']) + stat.unit = meter['f:counter_unit'] stat.min = min(vol, stat.min or vol) stat.max = max(vol, stat.max) stat.sum = vol + (stat.sum or 0) @@ -531,7 +532,8 @@ class Connection(base.Connection): period_end = period_start + datetime.timedelta( 0, period) results.append( - models.Statistics(count=0, + models.Statistics(unit='', + count=0, min=0, max=0, avg=0, diff --git a/ceilometer/storage/impl_mongodb.py b/ceilometer/storage/impl_mongodb.py index 1da5c5eb3..e5e610b91 100644 --- a/ceilometer/storage/impl_mongodb.py +++ b/ceilometer/storage/impl_mongodb.py @@ -177,7 +177,8 @@ class Connection(base.Connection): MAP_STATS = bson.code.Code(""" function () { - emit('statistics', { min : this.counter_volume, + emit('statistics', { unit: this.counter_unit, + min : this.counter_volume, max : this.counter_volume, sum : this.counter_volume, count : NumberInt(1), @@ -197,7 +198,8 @@ class Connection(base.Connection): - period_first) / period) * period); emit(period_start, - { min : this.counter_volume, + { unit: this.counter_unit, + min : this.counter_volume, max : this.counter_volume, sum : this.counter_volume, count : NumberInt(1), @@ -210,7 +212,8 @@ class Connection(base.Connection): REDUCE_STATS = bson.code.Code(""" function (key, values) { - var res = { min: values[0].min, + var res = { unit: values[0].unit, + min: values[0].min, max: values[0].max, count: values[0].count, sum: values[0].sum, diff --git a/ceilometer/storage/impl_sqlalchemy.py b/ceilometer/storage/impl_sqlalchemy.py index 81469981d..86b98fa1b 100644 --- a/ceilometer/storage/impl_sqlalchemy.py +++ b/ceilometer/storage/impl_sqlalchemy.py @@ -428,6 +428,7 @@ class Connection(base.Connection): def _make_stats_query(sample_filter): session = sqlalchemy_session.get_session() query = session.query( + Meter.counter_unit.label('unit'), func.min(Meter.timestamp).label('tsmin'), func.max(Meter.timestamp).label('tsmax'), func.avg(Meter.counter_volume).label('avg'), @@ -444,6 +445,7 @@ class Connection(base.Connection): if result.tsmin is not None and result.tsmax is not None else None) return api_models.Statistics( + unit=result.unit, count=int(result.count), min=result.min, max=result.max, diff --git a/ceilometer/storage/models.py b/ceilometer/storage/models.py index 1129ca86d..c5686b292 100644 --- a/ceilometer/storage/models.py +++ b/ceilometer/storage/models.py @@ -202,12 +202,13 @@ class Sample(Model): class Statistics(Model): """Computed statistics based on a set of sample data. """ - def __init__(self, + def __init__(self, unit, min, max, avg, sum, count, period, period_start, period_end, duration, duration_start, duration_end): """Create a new statistics object. + :param unit: The unit type of the data set :param min: The smallest volume found :param max: The largest volume found :param avg: The average of all volumes found @@ -220,7 +221,7 @@ class Statistics(Model): :param duration_start: The earliest time for the matching samples :param duration_end: The latest time for the matching samples """ - Model.__init__(self, + Model.__init__(self, unit=unit, min=min, max=max, avg=avg, sum=sum, count=count, period=period, period_start=period_start, period_end=period_end, duration=duration, diff --git a/tests/api/v1/test_compute_duration_by_resource_scenarios.py b/tests/api/v1/test_compute_duration_by_resource_scenarios.py index 3656fc0d3..8b70b617b 100644 --- a/tests/api/v1/test_compute_duration_by_resource_scenarios.py +++ b/tests/api/v1/test_compute_duration_by_resource_scenarios.py @@ -57,6 +57,7 @@ class TestComputeDurationByResource(tests_api.TestBase, def _set_stats(self, start, end): def get_meter_statistics(event_filter): return models.Statistics( + unit='', min=0, max=0, avg=0, sum=0, count=0, period=None, period_start=None, diff --git a/tests/api/v2/test_compute_duration_by_resource_scenarios.py b/tests/api/v2/test_compute_duration_by_resource_scenarios.py index 736bfa1ab..1ad4e2b24 100644 --- a/tests/api/v2/test_compute_duration_by_resource_scenarios.py +++ b/tests/api/v2/test_compute_duration_by_resource_scenarios.py @@ -68,6 +68,7 @@ class TestComputeDurationByResource(FunctionalTest, duration = timeutils.delta_seconds(duration_start, duration_end) return [ models.Statistics( + unit='', min=0, max=0, avg=0, @@ -142,6 +143,7 @@ class TestComputeDurationByResource(FunctionalTest, def get_interval(ignore_self, event_filter, period): return [ models.Statistics( + unit=None, count=0, min=None, max=None, @@ -171,6 +173,7 @@ class TestComputeDurationByResource(FunctionalTest, def get_interval(ignore_self, event_filter, period): return [ models.Statistics( + unit=None, count=0, min=None, max=None, diff --git a/tests/storage/base.py b/tests/storage/base.py index 56718a731..8d99f842a 100644 --- a/tests/storage/base.py +++ b/tests/storage/base.py @@ -599,6 +599,7 @@ class StatisticsTest(DBTestBase): (datetime.datetime(2012, 9, 25, 12, 32) - datetime.datetime(2012, 9, 25, 10, 30)).seconds) assert results.count == 3 + assert results.unit == 'GiB' assert results.min == 8 assert results.max == 10 assert results.sum == 27 @@ -638,6 +639,7 @@ class StatisticsTest(DBTestBase): self.assertEqual(r.period_start, datetime.datetime(2012, 9, 25, 10, 28)) self.assertEqual(r.count, 2) + self.assertEqual(r.unit, 'GiB') self.assertEqual(r.avg, 8.5) self.assertEqual(r.min, 8) self.assertEqual(r.max, 9) @@ -706,6 +708,7 @@ class StatisticsTest(DBTestBase): self.assertEqual(r.period_start, datetime.datetime(2012, 9, 25, 10, 28)) self.assertEqual(r.count, 1) + self.assertEqual(r.unit, 'GiB') self.assertEqual(r.avg, 8) self.assertEqual(r.min, 8) self.assertEqual(r.max, 8) @@ -730,6 +733,7 @@ class StatisticsTest(DBTestBase): results = list(self.conn.get_meter_statistics(f))[0] self.assertEqual(results.duration, 0) assert results.count == 1 + assert results.unit == 'GiB' assert results.min == 6 assert results.max == 6 assert results.sum == 6 @@ -745,6 +749,7 @@ class StatisticsTest(DBTestBase): (datetime.datetime(2012, 9, 25, 12, 32) - datetime.datetime(2012, 9, 25, 10, 30)).seconds) assert results.count == 3 + assert results.unit == 'GiB' assert results.min == 5 assert results.max == 7 assert results.sum == 18