def test_p50(self): histogram1 = Histogram(LinearBucket(0, 0.2, 50)) histogram1.record(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) self.assertEqual(histogram1.p50(), 4.2) histogram2 = Histogram(LinearBucket(0, 0.02, 50)) histogram2.record(0, 0, 0) self.assertEqual(histogram2.p50(), 0.01)
def test_p99(self): histogram1 = Histogram(LinearBucket(0, 0.2, 50)) histogram1.record(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) self.assertEqual(histogram1.p99(), 9.18) histogram2 = Histogram(LinearBucket(0, 0.02, 50)) histogram2.record(0, 0, 0) self.assertAlmostEqual(histogram2.p99(), 0.02, places=3)
def test_p90_negative(self): histogram1 = Histogram(LinearBucket(-10, 0.2, 50)) histogram1.record(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10) self.assertEqual(histogram1.p90(), -1.8) histogram2 = Histogram(LinearBucket(-1, 0.02, 50)) histogram2.record(-1, -1, -1) self.assertEqual(histogram2.p90(), -0.982)
def test_p90_negative_to_positive(self): histogram1 = Histogram(LinearBucket(-5, 0.2, 50)) histogram1.record(-1, -2, -3, -4, -5, 0, 1, 2, 3, 4) self.assertEqual(histogram1.p90(), 3.2) histogram2 = Histogram(LinearBucket(-0.5, 0.02, 50)) histogram2.record(-0.5, -0.5, -0.5) self.assertEqual(histogram2.p90(), -0.482)
def test_combine(self): histogram1 = Histogram(LinearBucket(0, 0.2, 50)) histogram1.record(0, 1, 2, 3, 4) histogram2 = Histogram(LinearBucket(0, 0.2, 50)) histogram2.record(5, 6, 7, 8, 9) histogram = Histogram(LinearBucket(0, 0.2, 50)) histogram.record(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) self.assertEqual(histogram1.combine(histogram2), histogram)
def test_fractional_buckets(self): histogram1 = Histogram(LinearBucket(0, 10 / 3, 3)) histogram1.record(3.33) histogram1.record(6.66) self.assertEqual(histogram1._buckets[0], 1) self.assertEqual(histogram1._buckets[1], 1) histogram2 = Histogram(LinearBucket(0, 10 / 3, 3)) histogram2.record(3.34) histogram2.record(6.67) self.assertEqual(histogram2._buckets[1], 1) self.assertEqual(histogram2._buckets[2], 1)
def test_clear(self): histogram = Histogram(LinearBucket(0, 0.2, 50)) histogram.record(-1, 1, 2, 3) self.assertEqual(histogram.total_count(), 4) self.assertEqual(histogram._buckets[5], 1) histogram.clear() self.assertEqual(histogram.total_count(), 0) self.assertEqual(histogram._buckets.get(5, 0), 0)
def test_copy(self): histogram1 = Histogram(LinearBucket(0, 0.2, 50)) histogram1.record(0, 1, 2, 3, 4) histogram2 = histogram1.copy() self.assertEqual(histogram1, histogram2) histogram1.record(5, 6, 7, 8, 9) self.assertNotEqual(histogram1, histogram2)
def test_log_metrics(self, mock_logger): logger = MetricLogger() logger.minimum_logging_frequency_msec = -1 namespace = Metrics.get_namespace(self.__class__) metric_name = MetricName(namespace, 'metric_logger_test') logger.update(HistogramCellFactory(LinearBucket(0, 1, 10)), metric_name, 1) logger.log_metrics() class Contains(str): def __eq__(self, other): return self in other mock_logger.info.assert_called_once_with( Contains('HistogramData(Total count: 1, P99: 2, P90: 2, P50: 2)'))
def test_basic_operations(self): d = HistogramCellFactory(LinearBucket(0, 1, 10))() d.update(10) self.assertEqual( str(d.get_cumulative()), 'HistogramData(Total count: 1, P99: >=10, P90: >=10, P50: >=10)') d.update(0) self.assertEqual( str(d.get_cumulative()), 'HistogramData(Total count: 2, P99: >=10, P90: >=10, P50: 1)') d.update(5) self.assertEqual( str(d.get_cumulative()), 'HistogramData(Total count: 3, P99: >=10, P90: >=10, P50: 6)')
def test_parallel_access(self): # We create NUM_THREADS threads that concurrently modify the distribution. threads = [] bucket_type = LinearBucket(0, 1, 100) d = HistogramCell(bucket_type) for _ in range(TestHistogramCell.NUM_THREADS): t = threading.Thread(target=TestHistogramCell._modify_histogram, args=(d, )) threads.append(t) t.start() for t in threads: t.join() histogram = Histogram(bucket_type) for _ in range(self.NUM_THREADS): for i in range(self.NUM_ITERATIONS): histogram.record(i) self.assertEqual(d.get_cumulative(), HistogramData(histogram))
def test_equal(self): histogram1 = Histogram(LinearBucket(0, 0.2, 50)) histogram2 = Histogram(LinearBucket(0, 0.2, 50)) self.assertEqual(histogram1, histogram2) self.assertEqual(hash(histogram1), hash(histogram2)) histogram1 = Histogram(LinearBucket(0, 0.2, 5)) histogram2 = Histogram(LinearBucket(0, 0.2, 50)) self.assertNotEqual(histogram1, histogram2) histogram1 = Histogram(LinearBucket(0, 0.2, 50)) histogram2 = Histogram(LinearBucket(0, 0.2, 50)) histogram1.record(1) histogram2.record(1) self.assertEqual(histogram1, histogram2) self.assertEqual(hash(histogram1), hash(histogram2)) histogram1 = Histogram(LinearBucket(0, 0.2, 50)) histogram2 = Histogram(LinearBucket(0, 0.2, 50)) histogram1.record(1) histogram2.record(10) self.assertNotEqual(histogram1, histogram2)
def test_p50_negative_infinity(self): histogram = Histogram(LinearBucket(0, 0.2, 50)) histogram.record(-1, -2, -3, -4, -5, 0, 1, 2, 3, 4) self.assertEqual(histogram.p50(), float('-inf')) self.assertIn('P50: <0', histogram.get_percentile_info())
def test_p50_positive_infinity(self): histogram = Histogram(LinearBucket(0, 0.2, 50)) histogram.record(6, 7, 8, 9, 10, 11, 12, 13, 14, 15) self.assertEqual(histogram.p50(), float('inf')) self.assertIn('P50: >=10', histogram.get_percentile_info())
def test_empty_p99(self): histogram = Histogram(LinearBucket(0, 0.2, 50)) with self.assertRaises(RuntimeError) as cm: histogram.p99() self.assertEqual(str(cm.exception), 'histogram has no record.')
def test_boundary_buckets(self): histogram = Histogram(LinearBucket(0, 20, 5)) histogram.record(0) histogram.record(99.9) self.assertEqual(histogram._buckets[0], 1) self.assertEqual(histogram._buckets[4], 1)
def test_out_of_range(self, mock_logger): histogram = Histogram(LinearBucket(0, 20, 5)) histogram.record(100) mock_logger.warning.assert_called_with( 'record is out of upper bound %s: %s', 100, 100) self.assertEqual(histogram.total_count(), 1)