def test_rewrite_append_only_violation(self): gauged = Gauged(self.driver, append_only_violation=Gauged.REWRITE) with gauged.writer as writer: writer.add('foo', 123, timestamp=2000) writer.add('foo', 456, timestamp=1000) self.assertIsNone(gauged.value('foo', timestamp=1000)) self.assertEqual(gauged.value('foo', timestamp=2000), 456)
def test_accepting_data_as_string(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000, key_overflow=Gauged.IGNORE, gauge_nan=Gauged.IGNORE) with gauged.writer as writer: writer.add('foo=123.456&bar=-15.98&qux=0&invalid=foobar\n', timestamp=20000) self.assertAlmostEqual(123.456, gauged.value('foo', timestamp=20000), 5) self.assertAlmostEqual(-15.98, gauged.value('bar', timestamp=20000), 5) self.assertEqual(gauged.value('qux', timestamp=20000), 0) self.assertEqual(gauged.value('invalid', timestamp=20000), None) stats = gauged.statistics() self.assertEqual(stats.data_points, 3) self.assertEqual(stats.byte_count, 24) stats = gauged.statistics(end=25000) self.assertEqual(stats.data_points, 3) self.assertEqual(stats.byte_count, 24) gauged = Gauged(self.driver, resolution=1000, block_size=10000, key_overflow=Gauged.IGNORE) with self.assertRaises(GaugedNaNError): with gauged.writer as writer: writer.add(u'foo=123.456&bar=-15.98&qux=0&invalid=foobar\n', timestamp=20000)
def test_append_only_violation(self): gauged = Gauged(self.driver) with gauged.writer as writer: writer.add('foo', 123, timestamp=2000) with self.assertRaises(GaugedAppendOnlyError): writer.add('foo', 456, timestamp=1000) self.assertIsNone(gauged.value('foo', timestamp=1000)) self.assertEqual(gauged.value('foo', timestamp=2000), 123)
def test_look_behind(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000, max_look_behind=10000) with gauged.writer as writer: writer.add('foo', 123, timestamp=10000) writer.add('bar', 123, timestamp=40000) self.assertEqual(gauged.value('foo', timestamp=10000), 123) self.assertEqual(gauged.value('foo', timestamp=20000), 123) self.assertEqual(gauged.value('foo', timestamp=30000), None)
def test_coercing_non_string_keys(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add(1234, 100, timestamp=10000) writer.add(True, 100, timestamp=10000) writer.add(u'foo', 100, timestamp=10000) self.assertEqual(gauged.value('1234', timestamp=10000), 100) self.assertEqual(gauged.value('True', timestamp=10000), 100) self.assertEqual(gauged.value('foo', timestamp=10000), 100)
def test_gauge_nan(self): gauged = Gauged(self.driver, block_size=50000) with gauged.writer as writer: with self.assertRaises(GaugedNaNError): writer.add('foobar', 'baz') self.assertEqual(gauged.value('foobar'), None) gauged = Gauged(self.driver, block_size=50000, gauge_nan=Gauged.IGNORE) with gauged.writer as writer: writer.add('foobar', 'baz') self.assertEqual(gauged.value('foobar'), None)
def test_flush_flushes_last_complete_block(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add('foo', 1, timestamp=1000) writer.add('foo', 2, timestamp=2000) writer.add('foo', 3, timestamp=3000) self.assertEqual(gauged.value('foo', timestamp=3000), None) writer.flush() self.assertEqual(gauged.value('foo', timestamp=3000), 2) self.assertEqual(gauged.value('foo', timestamp=3000), 3)
def test_interim_flushing(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add('foo', 123, timestamp=1000) writer.flush() writer.add('bar', 456, timestamp=2000) writer.flush() writer.add('baz', 789, timestamp=10000) self.assertEqual(gauged.value('foo', timestamp=10000), 123) self.assertEqual(gauged.value('bar', timestamp=10000), 456) self.assertEqual(gauged.value('baz', timestamp=10000), 789)
def test_relative_dates(self): now = long(time() * 1000) gauged = Gauged(self.driver, defaults={'start': -4 * Gauged.DAY}) with gauged.writer as writer: writer.add('foo', 1, timestamp=now - 6 * Gauged.DAY) writer.add('foo', 2, timestamp=now - 5 * Gauged.DAY) writer.add('foo', 3, timestamp=now - 3 * Gauged.DAY) writer.add('foo', 4, timestamp=now - 2 * Gauged.DAY) writer.add('foo', 5, timestamp=now - Gauged.DAY) self.assertEqual(gauged.value('foo'), 5) self.assertEqual(gauged.value('foo', timestamp=-1.5 * Gauged.DAY), 4)
def test_relative_dates(self): now = long(time() * 1000) gauged = Gauged(self.driver, defaults={'start':-4*Gauged.DAY}) with gauged.writer as writer: writer.add('foo', 1, timestamp=now-6*Gauged.DAY) writer.add('foo', 2, timestamp=now-5*Gauged.DAY) writer.add('foo', 3, timestamp=now-3*Gauged.DAY) writer.add('foo', 4, timestamp=now-2*Gauged.DAY) writer.add('foo', 5, timestamp=now-Gauged.DAY) self.assertEqual(gauged.value('foo'), 5) self.assertEqual(gauged.value('foo', timestamp=-1.5*Gauged.DAY), 4)
def test_auto_flush(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000, flush_seconds=0.001) with gauged.writer as writer: writer.add('foo', 1, timestamp=1000) self.assertEqual(gauged.value('foo', timestamp=2000), None) sleep(0.002) self.assertEqual(gauged.value('foo', timestamp=2000), None) # note: the next write triggers the flush() of all prior writes writer.add('foo', 2, timestamp=2000) sleep(0.002) self.assertEqual(gauged.value('foo', timestamp=2000), 1) self.assertEqual(gauged.value('foo', timestamp=2000), 2)
def test_ignore_append_only_violation(self): gauged = Gauged(self.driver, append_only_violation=Gauged.IGNORE) with gauged.writer as writer: writer.add('foo', 123, timestamp=2000) writer.add('foo', 456, timestamp=1000) self.assertEqual(gauged.value('foo', timestamp=1000), None) self.assertEqual(gauged.value('foo', timestamp=2000), 123)
def test_rewrite_append_only_violation(self): gauged = Gauged(self.driver, append_only_violation=Gauged.REWRITE) with gauged.writer as writer: writer.add('foo', 123, timestamp=2000) writer.add('foo', 456, timestamp=1000) self.assertEqual(gauged.value('foo', timestamp=1000), None) self.assertEqual(gauged.value('foo', timestamp=2000), 456)
def test_config_instance(self): config = Config(append_only_violation=Gauged.REWRITE, resolution=1000, block_size=10000) gauged = Gauged(self.driver, config=config) with gauged.writer as writer: writer.add('foo', 1, timestamp=2000) writer.add('foo', 2, timestamp=1000) self.assertEqual(gauged.value('foo', timestamp=2000), 2)
def test_append_only_violation(self): gauged = Gauged(self.driver) with gauged.writer as writer: writer.add('foo', 123, timestamp=2000) with self.assertRaises(GaugedAppendOnlyError): writer.add('foo', 456, timestamp=1000) self.assertEqual(gauged.value('foo', timestamp=1000), None) self.assertEqual(gauged.value('foo', timestamp=2000), 123)
def test_no_data(self): gauged = Gauged(self.driver) self.assertEqual(len(gauged.namespaces()), 0) self.assertEqual(len(gauged.value_series('foo')), 0) self.assertEqual(len(gauged.aggregate_series('foo', Gauged.SUM)), 0) self.assertEqual(gauged.value('foo'), None) self.assertEqual(gauged.aggregate('foo', Gauged.SUM), None) self.assertEqual(len(gauged.keys()), 0) stats = gauged.statistics() for attr in ['data_points', 'byte_count']: self.assertEqual(getattr(stats, attr), 0)
def test_add_debug(self): context = dict(called=False) gauged = Gauged(self.driver) def mock_debug(*_): context['called'] = True with gauged.writer as writer: writer.debug = mock_debug writer.add('foo', 123, timestamp=10000, debug=True) writer.add('foo=123', timestamp=10000, debug=True) self.assertEqual(gauged.value('foo', timestamp=10000), None) self.assertTrue(context['called'])
def test_clear_from(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add('foo', 1, timestamp=10000) writer.add('foo', 2, timestamp=20000) writer.add('foo', 3, timestamp=30000) writer.add('foo', 4, timestamp=40000, namespace=1) with gauged.writer as writer: self.assertEqual(writer.resume_from(), 41000) self.assertEqual(gauged.value('foo', timestamp=40000), 3) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), 4) with gauged.writer as writer: with self.assertRaises(ValueError): # note: must be cleared from nearest block boundary (20000) writer.clear_from(25000) writer.clear_from(20000) self.assertEqual(gauged.value('foo', timestamp=40000), 1) self.assertEqual( gauged.value('foo', timestamp=40000, namespace=1), None) with gauged.writer as writer: self.assertEqual(writer.resume_from(), 21000) writer.add('foo', 5, timestamp=30000) writer.add('foo', 6, timestamp=30000, namespace=1) self.assertEqual(gauged.value('foo', timestamp=40000), 5) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), 6)
def test_clear_from(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add('foo', 1, timestamp=10000) writer.add('foo', 2, timestamp=20000) writer.add('foo', 3, timestamp=30000) writer.add('foo', 4, timestamp=40000, namespace=1) with gauged.writer as writer: self.assertEqual(writer.resume_from(), 41000) self.assertEqual(gauged.value('foo', timestamp=40000), 3) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), 4) with gauged.writer as writer: with self.assertRaises(ValueError): # note: must be cleared from nearest block boundary (20000) writer.clear_from(25000) writer.clear_from(20000) self.assertEqual(gauged.value('foo', timestamp=40000), 1) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), None) with gauged.writer as writer: self.assertEqual(writer.resume_from(), 21000) writer.add('foo', 5, timestamp=30000) writer.add('foo', 6, timestamp=30000, namespace=1) self.assertEqual(gauged.value('foo', timestamp=40000), 5) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), 6)
def test_clear_key_after(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add({'foo': 1, 'bar': 1}, timestamp=10000) writer.add({'foo': 2, 'bar': 2}, timestamp=20000) writer.add({'foo': 3, 'bar': 3}, timestamp=30000) writer.add({'foo': 4, 'bar': 4}, timestamp=40000, namespace=1) self.assertEqual(gauged.value('foo', timestamp=40000), 3) self.assertEqual(gauged.value('bar', timestamp=40000), 3) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), 4) self.assertEqual(gauged.value('bar', timestamp=40000, namespace=1), 4) # timestamp should be on a block boundary with gauged.writer as writer: with self.assertRaises(ValueError): writer.clear_key_after('foo', timestamp=15000) with gauged.writer as writer: writer.clear_key_after('foo', timestamp=20000) # every value before 20000 stays the same self.assertEqual(gauged.value('foo', timestamp=10000), 1) self.assertEqual(gauged.value('bar', timestamp=10000), 1) # 'foo' value on 20000 is cleared self.assertEqual(gauged.aggregate('foo', Gauged.COUNT, start=19000, end=21000), 0) # 'foo' value after 20000 is cleared self.assertEqual(gauged.aggregate('foo', Gauged.COUNT, start=20000, end=40000), 0) # 'bar' stays there self.assertEqual(gauged.value('bar', timestamp=10000), 1) with gauged.writer as writer: writer.add({'foo': 5, 'bar': 5}, timestamp=50000) writer.add({'foo': 5, 'bar': 5}, timestamp=50000, namespace=1) writer.add({'foo': 6, 'bar': 6}, timestamp=60000) writer.add({'foo': 6, 'bar': 6}, timestamp=60000, namespace=1) with gauged.writer as writer: writer.clear_key_after('foo', namespace=1, timestamp=50000) # 'foo' in namespace 0 is untouched after 50000 self.assertEqual(gauged.value('foo', timestamp=60000), 6) # 'foo' in namespace 1 is correctly cleared self.assertEqual(gauged.aggregate('foo', Gauged.COUNT, start=50000, end=60000, namespace=1), 0) # 'bar' is still there self.assertEqual(gauged.value('bar', timestamp=60000), 6) self.assertEqual(gauged.value('bar', timestamp=60000, namespace=1), 6)
def test_add_with_whitelist(self): gauged = Gauged(self.driver, key_whitelist=['a']) with gauged.writer as writer: writer.add({'a': 123, 'b': 456}, timestamp=2000) self.assertEqual(gauged.value('a', timestamp=2000), 123) self.assertEqual(gauged.value('b', timestamp=2000), None)
def test_clear_key_before(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add({'foo': 1, 'bar': 1}, timestamp=10000) writer.add({'foo': 1.5, 'bar': 1.5}, timestamp=15000) writer.add({'foo': 2, 'bar': 2}, timestamp=20000) writer.add({'foo': 2.5, 'bar': 2.5}, timestamp=25000) writer.add({'foo': 2.9, 'bar': 2.9}, timestamp=29999) writer.add({'foo': 3, 'bar': 3}, timestamp=30000) writer.add({'foo': 4, 'bar': 4}, timestamp=40000, namespace=1) # timestamp should be on a block boundary with gauged.writer as writer: with self.assertRaises(ValueError): writer.clear_key_before('foo', timestamp=15000) self.assertEqual(gauged.value('foo', timestamp=40000), 3) self.assertEqual(gauged.value('bar', timestamp=40000), 3) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), 4) self.assertEqual(gauged.value('bar', timestamp=40000, namespace=1), 4) with gauged.writer as writer: writer.clear_key_before('foo', timestamp=20000) # every value >= 20000 stays the same self.assertEqual(gauged.value('foo', timestamp=20000), 2) self.assertAlmostEqual(gauged.value('foo', timestamp=25000), 2.5, places=5) self.assertAlmostEqual(gauged.value('foo', timestamp=29000), 2.9, places=5) self.assertEqual(gauged.value('foo', timestamp=30000), 3) self.assertEqual(gauged.value('bar', timestamp=30000), 3) # 'foo' values < 20000 are cleared self.assertEqual(gauged.value('foo', timestamp=15000), None) self.assertEqual(gauged.value('foo', timestamp=10000), None) # 'bar' stays there self.assertEqual(gauged.value('bar', timestamp=10000), 1) with gauged.writer as writer: writer.add({'foo': 5, 'bar': 5}, timestamp=50000) writer.add({'foo': 5, 'bar': 5}, timestamp=50000, namespace=1) writer.add({'foo': 6, 'bar': 6}, timestamp=60000) writer.add({'foo': 6, 'bar': 6}, timestamp=60000, namespace=1) with gauged.writer as writer: writer.clear_key_before('foo', namespace=1, timestamp=60000) # 'foo' in namespace 0 is untouched before 60000 self.assertEqual(gauged.value('foo', timestamp=50000), 5) # 'foo' in namespace 1 is correctly cleared self.assertEqual(gauged.value('foo', timestamp=50000, namespace=1), None) # 'bar' is still there self.assertEqual(gauged.value('bar', timestamp=50000), 5) self.assertEqual(gauged.value('bar', timestamp=50000, namespace=1), 5)
def test_memory_driver(self): gauged = Gauged() with gauged.writer as writer: writer.add('foo', 1, timestamp=1000) self.assertEqual(gauged.value('foo', timestamp=1000), 1)
def test_gauge(self): gauged = Gauged(self.driver, block_size=50000, gauge_nan=Gauged.IGNORE) self.assertEqual(gauged.value('foobar'), None) with gauged.writer as writer: writer.add('foobar', 200, timestamp=23000) self.assertEqual(gauged.value('foobar'), 200) self.assertEqual(gauged.value('foobar', timestamp=22000), None) with gauged.writer as writer: writer.add({ 'foobar': 300, 'invalid': 'nan' }, timestamp=50000) self.assertEqual(gauged.value('foobar'), 300) self.assertEqual(gauged.value('foobar', 30000), 200) timestamp = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=60) self.assertEqual(gauged.value('foobar', timestamp), 300) with gauged.writer as writer: writer.add({ 'foobar': 350 }, timestamp=90000) writer.add('foobar', 100, timestamp=120000) writer.add('bar', 150, timestamp=130000) self.assertItemsEqual(gauged.keys(), [ 'foobar', 'bar' ]) self.assertEqual(gauged.value('foobar'), 100) with gauged.writer as writer: writer.add('foobar', 500, timestamp=150000) self.assertEqual(gauged.value('foobar'), 500) with gauged.writer as writer: writer.add('foobar', 1500, timestamp=10000, namespace=1) self.assertEqual(gauged.value('foobar', namespace=1), 1500) self.assertEqual(gauged.value('foobar'), 500) with gauged.writer as writer: writer.clear_from(100000) self.assertEqual(gauged.value('foobar'), 350) with self.assertRaises(GaugedDateRangeError): self.assertEqual(gauged.value('foobar', timestamp=-10000000000000), None)
def test_gauge(self): gauged = Gauged(self.driver, block_size=50000, gauge_nan=Gauged.IGNORE) self.assertEqual(gauged.value('foobar'), None) with gauged.writer as writer: writer.add('foobar', 200, timestamp=23000) self.assertEqual(gauged.value('foobar'), 200) self.assertEqual(gauged.value('foobar', timestamp=22000), None) with gauged.writer as writer: writer.add({'foobar': 300, 'invalid': 'nan'}, timestamp=50000) self.assertEqual(gauged.value('foobar'), 300) self.assertEqual(gauged.value('foobar', 30000), 200) timestamp = datetime.datetime( 1970, 1, 1) + datetime.timedelta(seconds=60) self.assertEqual(gauged.value('foobar', timestamp), 300) with gauged.writer as writer: writer.add({'foobar': 350}, timestamp=90000) writer.add('foobar', 100, timestamp=120000) writer.add('bar', 150, timestamp=130000) self.assertItemsEqual(gauged.keys(), ['foobar', 'bar']) self.assertEqual(gauged.value('foobar'), 100) with gauged.writer as writer: writer.add('foobar', 500, timestamp=150000) self.assertEqual(gauged.value('foobar'), 500) with gauged.writer as writer: writer.add('foobar', 1500, timestamp=10000, namespace=1) self.assertEqual(gauged.value('foobar', namespace=1), 1500) self.assertEqual(gauged.value('foobar'), 500) with gauged.writer as writer: writer.clear_from(100000) self.assertEqual(gauged.value('foobar'), 350) with self.assertRaises(GaugedDateRangeError): self.assertEqual( gauged.value('foobar', timestamp=-10000000000000), None)
def test_add_with_whitelist(self): gauged = Gauged(self.driver, key_whitelist=['a']) with gauged.writer as writer: writer.add({ 'a': 123, 'b': 456 }, timestamp=2000) self.assertEqual(gauged.value('a', timestamp=2000), 123) self.assertEqual(gauged.value('b', timestamp=2000), None)
def test_clear_key_before(self): gauged = Gauged(self.driver, resolution=1000, block_size=10000) with gauged.writer as writer: writer.add({'foo': 1, 'bar': 1}, timestamp=10000) writer.add({'foo': 1.5, 'bar': 1.5}, timestamp=15000) writer.add({'foo': 2, 'bar': 2}, timestamp=20000) writer.add({'foo': 2.5, 'bar': 2.5}, timestamp=25000) writer.add({'foo': 2.9, 'bar': 2.9}, timestamp=29999) writer.add({'foo': 3, 'bar': 3}, timestamp=30000) writer.add({'foo': 4, 'bar': 4}, timestamp=40000, namespace=1) # timestamp should be on a block boundary with gauged.writer as writer: with self.assertRaises(ValueError): writer.clear_key_before('foo', timestamp=15000) self.assertEqual(gauged.value('foo', timestamp=40000), 3) self.assertEqual(gauged.value('bar', timestamp=40000), 3) self.assertEqual(gauged.value('foo', timestamp=40000, namespace=1), 4) self.assertEqual(gauged.value('bar', timestamp=40000, namespace=1), 4) with gauged.writer as writer: writer.clear_key_before('foo', timestamp=20000) # every value >= 20000 stays the same self.assertEqual(gauged.value('foo', timestamp=20000), 2) self.assertAlmostEqual(gauged.value('foo', timestamp=25000), 2.5, places=5) self.assertAlmostEqual(gauged.value('foo', timestamp=29000), 2.9, places=5) self.assertEqual(gauged.value('foo', timestamp=30000), 3) self.assertEqual(gauged.value('bar', timestamp=30000), 3) # 'foo' values < 20000 are cleared self.assertIsNone(gauged.value('foo', timestamp=15000)) self.assertIsNone(gauged.value('foo', timestamp=10000)) # 'bar' stays there self.assertEqual(gauged.value('bar', timestamp=10000), 1) with gauged.writer as writer: writer.add({'foo': 5, 'bar': 5}, timestamp=50000) writer.add({'foo': 5, 'bar': 5}, timestamp=50000, namespace=1) writer.add({'foo': 6, 'bar': 6}, timestamp=60000) writer.add({'foo': 6, 'bar': 6}, timestamp=60000, namespace=1) with gauged.writer as writer: writer.clear_key_before('foo', namespace=1, timestamp=60000) # 'foo' in namespace 0 is untouched before 60000 self.assertEqual(gauged.value('foo', timestamp=50000), 5) # 'foo' in namespace 1 is correctly cleared self.assertEqual(gauged.value('foo', timestamp=50000, namespace=1), None) # 'bar' is still there self.assertEqual(gauged.value('bar', timestamp=50000), 5) self.assertEqual(gauged.value('bar', timestamp=50000, namespace=1), 5)