Add support for limiting the number of samples returned

Blueprint: api-limit

Change-Id: Id053eb60674fea58b3d83b460fd0344dbc050cbf
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2013-05-31 14:00:47 +02:00
parent 0e10d2ddb7
commit 426cd49d86
6 changed files with 57 additions and 11 deletions

View File

@ -126,8 +126,11 @@ class Connection(object):
""" """
@abc.abstractmethod @abc.abstractmethod
def get_samples(self, sample_filter): def get_samples(self, sample_filter, limit=None):
"""Return an iterable of model.Sample instances """Return an iterable of model.Sample instances.
:param sample_filter: Filter.
:param limit: Maximum number of results to return.
""" """
@abc.abstractmethod @abc.abstractmethod

View File

@ -393,8 +393,11 @@ class Connection(base.Connection):
user_id=data['f:user_id'], user_id=data['f:user_id'],
) )
def get_samples(self, sample_filter): def get_samples(self, sample_filter, limit=None):
"""Return an iterable of models.Sample instances """Return an iterable of models.Sample instances.
:param sample_filter: Filter.
:param limit: Maximum number of results to return.
""" """
def make_sample(data): def make_sample(data):
""" transform HBase fields to Sample model """ transform HBase fields to Sample model
@ -415,6 +418,9 @@ class Connection(base.Connection):
# properly. # properly.
# handle metaquery # handle metaquery
metaquery = sample_filter.metaquery metaquery = sample_filter.metaquery
# TODO(jd) implements using HBase capabilities
if limit == 0:
break
if len(metaquery) > 0: if len(metaquery) > 0:
# metaquery checks resource table # metaquery checks resource table
resource = self.resource.row(meter['f:resource_id']) resource = self.resource.row(meter['f:resource_id'])
@ -423,8 +429,12 @@ class Connection(base.Connection):
if resource['f:r_' + k.split('.', 1)[1]] != v: if resource['f:r_' + k.split('.', 1)[1]] != v:
break # if one metaquery doesn't match, break break # if one metaquery doesn't match, break
else: else:
if limit:
limit -= 1
yield make_sample(meter) yield make_sample(meter)
else: else:
if limit:
limit -= 1
yield make_sample(meter) yield make_sample(meter)
def _update_meter_stats(self, stat, meter): def _update_meter_stats(self, stat, meter):

View File

@ -100,7 +100,7 @@ class Connection(base.Connection):
return [] return []
def get_meters(self, user=None, project=None, resource=None, source=None, def get_meters(self, user=None, project=None, resource=None, source=None,
metaquery={}): limit=None, metaquery={}):
"""Return an iterable of dictionaries containing meter information. """Return an iterable of dictionaries containing meter information.
{ 'name': name of the meter, { 'name': name of the meter,
@ -114,6 +114,7 @@ class Connection(base.Connection):
:param project: Optional ID for project that owns the resource. :param project: Optional ID for project that owns the resource.
:param resource: Optional resource filter. :param resource: Optional resource filter.
:param source: Optional source filter. :param source: Optional source filter.
:param limit: Maximum number of results to return.
:param metaquery: Optional dict with metadata to match on. :param metaquery: Optional dict with metadata to match on.
""" """
return [] return []

View File

@ -440,12 +440,16 @@ class Connection(base.Connection):
user_id=r['user_id'], user_id=r['user_id'],
) )
def get_samples(self, sample_filter): def get_samples(self, sample_filter, limit=None):
"""Return an iterable of samples as created by """Return an iterable of model.Sample instances.
:func:`ceilometer.meter.meter_message_from_counter`.
:param sample_filter: Filter.
:param limit: Maximum number of results to return.
""" """
if limit == 0:
return
q = make_query_from_filter(sample_filter, require_meter=False) q = make_query_from_filter(sample_filter, require_meter=False)
samples = self.db.meter.find(q) samples = self.db.meter.find(q).limit(limit or 0)
for s in samples: for s in samples:
# Remove the ObjectId generated by the database when # Remove the ObjectId generated by the database when
# the sample was inserted. It is an implementation # the sample was inserted. It is an implementation

View File

@ -311,12 +311,20 @@ class Connection(base.Connection):
user_id=resource.user_id, user_id=resource.user_id,
) )
def get_samples(self, sample_filter): def get_samples(self, sample_filter, limit=None):
"""Return an iterable of api_models.Samples """Return an iterable of api_models.Samples.
:param sample_filter: Filter.
:param limit: Maximum number of results to return.
""" """
if limit == 0:
return
query = self.session.query(Meter) query = self.session.query(Meter)
query = make_query_from_filter(query, sample_filter, query = make_query_from_filter(query, sample_filter,
require_meter=False) require_meter=False)
if limit:
query = query.limit(limit)
samples = query.all() samples = query.all()
for s in samples: for s in samples:

View File

@ -271,6 +271,16 @@ class MeterTest(DBTestBase):
class RawSampleTest(DBTestBase): class RawSampleTest(DBTestBase):
def test_get_samples_limit_zero(self):
f = storage.SampleFilter()
results = list(self.conn.get_samples(f, limit=0))
self.assertEqual(len(results), 0)
def test_get_samples_limit(self):
f = storage.SampleFilter()
results = list(self.conn.get_samples(f, limit=3))
self.assertEqual(len(results), 3)
def test_get_samples_by_user(self): def test_get_samples_by_user(self):
f = storage.SampleFilter(user='user-id') f = storage.SampleFilter(user='user-id')
results = list(self.conn.get_samples(f)) results = list(self.conn.get_samples(f))
@ -278,6 +288,16 @@ class RawSampleTest(DBTestBase):
for meter in results: for meter in results:
assert meter.as_dict() in [self.msg1, self.msg2] assert meter.as_dict() in [self.msg1, self.msg2]
def test_get_samples_by_user_limit(self):
f = storage.SampleFilter(user='user-id')
results = list(self.conn.get_samples(f, limit=1))
self.assertEqual(len(results), 1)
def test_get_samples_by_user_limit_bigger(self):
f = storage.SampleFilter(user='user-id')
results = list(self.conn.get_samples(f, limit=42))
self.assertEqual(len(results), 2)
def test_get_samples_by_project(self): def test_get_samples_by_project(self):
f = storage.SampleFilter(project='project-id') f = storage.SampleFilter(project='project-id')
results = list(self.conn.get_samples(f)) results = list(self.conn.get_samples(f))