diff --git a/gnocchi/carbonara.py b/gnocchi/carbonara.py index 26dac750f..81fbc826d 100644 --- a/gnocchi/carbonara.py +++ b/gnocchi/carbonara.py @@ -65,9 +65,15 @@ class SerializableMixin(object): class TimeSerie(SerializableMixin): + """A representation of series of a timestamp with a value. + + Duplicate timestamps are not allowed and will be filtered to use the + last in the group when the TimeSerie is created or extended. + """ def __init__(self, timestamps=None, values=None): - self.ts = pandas.Series(values, timestamps).sort_index() + self.ts = pandas.Series(values, timestamps).groupby( + level=0).last().sort_index() def __eq__(self, other): return (isinstance(other, TimeSerie) @@ -77,7 +83,8 @@ class TimeSerie(SerializableMixin): return self.ts[key] def set_values(self, values): - t = pandas.Series(*reversed(list(zip(*values)))) + t = pandas.Series(*reversed(list(zip(*values)))).groupby( + level=0).last() self.ts = t.combine_first(self.ts).sort_index() def __len__(self): diff --git a/gnocchi/tests/test_carbonara.py b/gnocchi/tests/test_carbonara.py index a611bdcf0..8b83e86b0 100644 --- a/gnocchi/tests/test_carbonara.py +++ b/gnocchi/tests/test_carbonara.py @@ -74,6 +74,27 @@ class TestBoundTimeSerie(base.BaseTestCase): (datetime.datetime(2014, 1, 1, 12, 0, 10), 4)]) self.assertEqual(2, len(ts)) + def test_duplicate_timestamps(self): + ts = carbonara.BoundTimeSerie( + [datetime.datetime(2014, 1, 1, 12, 0, 0), + datetime.datetime(2014, 1, 1, 12, 0, 9), + datetime.datetime(2014, 1, 1, 12, 0, 9)], + [10, 5, 23]) + self.assertEqual(2, len(ts)) + self.assertEqual(10.0, ts[0]) + self.assertEqual(23.0, ts[1]) + + ts.set_values([(datetime.datetime(2014, 1, 1, 13, 0, 10), 3), + (datetime.datetime(2014, 1, 1, 13, 0, 11), 9), + (datetime.datetime(2014, 1, 1, 13, 0, 11), 8), + (datetime.datetime(2014, 1, 1, 13, 0, 11), 7), + (datetime.datetime(2014, 1, 1, 13, 0, 11), 4)]) + self.assertEqual(4, len(ts)) + self.assertEqual(10.0, ts[0]) + self.assertEqual(23.0, ts[1]) + self.assertEqual(3.0, ts[2]) + self.assertEqual(4.0, ts[3]) + class TestAggregatedTimeSerie(base.BaseTestCase): @staticmethod