|
1 | 1 | from concurrent.futures import ThreadPoolExecutor |
| 2 | +from decimal import Decimal |
| 3 | +import math |
2 | 4 | import os |
3 | 5 | from threading import Barrier, Event |
4 | 6 | import time |
@@ -311,6 +313,67 @@ def test_summary_not_observable(self): |
311 | 313 | """.observe() must fail if the Summary is not observable.""" |
312 | 314 | assert_not_observable(self.summary_with_labels.observe, 1) |
313 | 315 |
|
| 316 | + def test_observe_batch(self): |
| 317 | + self.summary.observe(1) |
| 318 | + self.summary.observe_batch([-2, 0, 0.5, 2]) |
| 319 | + self.summary.observe_batch((3, 4)) |
| 320 | + self.assertEqual(7, self.registry.get_sample_value('s_count')) |
| 321 | + self.assertEqual(8.5, self.registry.get_sample_value('s_sum')) |
| 322 | + |
| 323 | + def test_observe_batch_empty(self): |
| 324 | + self.summary.observe(1) |
| 325 | + self.summary.observe_batch([]) |
| 326 | + self.summary.observe_batch(()) |
| 327 | + self.assertEqual(1, self.registry.get_sample_value('s_count')) |
| 328 | + self.assertEqual(1, self.registry.get_sample_value('s_sum')) |
| 329 | + |
| 330 | + def test_observe_batch_not_observable(self): |
| 331 | + assert_not_observable(self.summary_with_labels.observe_batch, [1]) |
| 332 | + assert_not_observable(self.summary_with_labels.observe_batch, []) |
| 333 | + |
| 334 | + def test_observe_batch_labels(self): |
| 335 | + self.summary_with_labels.labels('a').observe_batch([1, 2]) |
| 336 | + self.summary_with_labels.labels('b').observe_batch([4]) |
| 337 | + self.assertEqual(2, self.registry.get_sample_value('s_with_labels_count', {'label1': 'a'})) |
| 338 | + self.assertEqual(3, self.registry.get_sample_value('s_with_labels_sum', {'label1': 'a'})) |
| 339 | + self.assertEqual(1, self.registry.get_sample_value('s_with_labels_count', {'label1': 'b'})) |
| 340 | + self.assertEqual(4, self.registry.get_sample_value('s_with_labels_sum', {'label1': 'b'})) |
| 341 | + |
| 342 | + def test_observe_batch_nonfinite(self): |
| 343 | + self.summary.observe_batch([float('inf')]) |
| 344 | + self.assertEqual(float('inf'), self.registry.get_sample_value('s_sum')) |
| 345 | + self.summary.observe_batch([float('-inf')]) |
| 346 | + self.assertTrue(math.isnan(self.registry.get_sample_value('s_sum'))) |
| 347 | + self.summary.observe_batch([float('nan')]) |
| 348 | + self.assertEqual(3, self.registry.get_sample_value('s_count')) |
| 349 | + self.assertTrue(math.isnan(self.registry.get_sample_value('s_sum'))) |
| 350 | + |
| 351 | + def test_observe_batch_invalid_amounts(self): |
| 352 | + self.summary.observe(1) |
| 353 | + self.assertRaises(TypeError, self.summary.observe_batch, [2, 'invalid']) |
| 354 | + self.assertEqual(1, self.registry.get_sample_value('s_count')) |
| 355 | + self.assertEqual(1, self.registry.get_sample_value('s_sum')) |
| 356 | + self.assertRaises(TypeError, self.summary.observe_batch, [Decimal('1.5')]) |
| 357 | + self.assertEqual(1, self.registry.get_sample_value('s_count')) |
| 358 | + self.assertEqual(1, self.registry.get_sample_value('s_sum')) |
| 359 | + |
| 360 | + def test_observe_batch_iterators(self): |
| 361 | + self.summary.observe_batch(iter(())) |
| 362 | + self.summary.observe_batch(iter([1, 2])) |
| 363 | + self.summary.observe_batch(x for x in [3, 4]) |
| 364 | + self.assertEqual(4, self.registry.get_sample_value('s_count')) |
| 365 | + self.assertEqual(10, self.registry.get_sample_value('s_sum')) |
| 366 | + |
| 367 | + def test_observe_batch_iteration_failure(self): |
| 368 | + def amounts(): |
| 369 | + yield 2 |
| 370 | + raise RuntimeError('iteration failed') |
| 371 | + |
| 372 | + self.summary.observe(1) |
| 373 | + self.assertRaises(RuntimeError, self.summary.observe_batch, amounts()) |
| 374 | + self.assertEqual(1, self.registry.get_sample_value('s_count')) |
| 375 | + self.assertEqual(1, self.registry.get_sample_value('s_sum')) |
| 376 | + |
314 | 377 | def test_function_decorator(self): |
315 | 378 | self.assertEqual(0, self.registry.get_sample_value('s_count')) |
316 | 379 |
|
@@ -449,6 +512,93 @@ def test_histogram_not_observable(self): |
449 | 512 | """.observe() must fail if the Summary is not observable.""" |
450 | 513 | assert_not_observable(self.labels.observe, 1) |
451 | 514 |
|
| 515 | + def test_observe_batch(self): |
| 516 | + self.histogram.observe(0.5) |
| 517 | + self.histogram.observe_batch([-1, 0, 1, 2.5]) |
| 518 | + self.histogram.observe_batch((3, 20)) |
| 519 | + self.assertEqual(2, self.registry.get_sample_value('h_bucket', {'le': '0.005'})) |
| 520 | + self.assertEqual(3, self.registry.get_sample_value('h_bucket', {'le': '0.5'})) |
| 521 | + self.assertEqual(4, self.registry.get_sample_value('h_bucket', {'le': '1.0'})) |
| 522 | + self.assertEqual(5, self.registry.get_sample_value('h_bucket', {'le': '2.5'})) |
| 523 | + self.assertEqual(6, self.registry.get_sample_value('h_bucket', {'le': '5.0'})) |
| 524 | + self.assertEqual(7, self.registry.get_sample_value('h_bucket', {'le': '+Inf'})) |
| 525 | + self.assertEqual(7, self.registry.get_sample_value('h_count')) |
| 526 | + self.assertEqual(26, self.registry.get_sample_value('h_sum')) |
| 527 | + |
| 528 | + def test_observe_batch_empty(self): |
| 529 | + self.histogram.observe(1) |
| 530 | + self.histogram.observe_batch([]) |
| 531 | + self.histogram.observe_batch(()) |
| 532 | + self.assertEqual(1, self.registry.get_sample_value('h_count')) |
| 533 | + self.assertEqual(1, self.registry.get_sample_value('h_sum')) |
| 534 | + |
| 535 | + def test_observe_batch_not_observable(self): |
| 536 | + assert_not_observable(self.labels.observe_batch, [1]) |
| 537 | + assert_not_observable(self.labels.observe_batch, []) |
| 538 | + |
| 539 | + def test_observe_batch_labels(self): |
| 540 | + self.labels.labels('a').observe_batch([1, 2]) |
| 541 | + self.labels.labels('b').observe_batch([4]) |
| 542 | + self.assertEqual(1, self.registry.get_sample_value('hl_bucket', {'l': 'a', 'le': '1.0'})) |
| 543 | + self.assertEqual(2, self.registry.get_sample_value('hl_count', {'l': 'a'})) |
| 544 | + self.assertEqual(3, self.registry.get_sample_value('hl_sum', {'l': 'a'})) |
| 545 | + self.assertEqual(1, self.registry.get_sample_value('hl_count', {'l': 'b'})) |
| 546 | + self.assertEqual(4, self.registry.get_sample_value('hl_sum', {'l': 'b'})) |
| 547 | + |
| 548 | + def test_observe_batch_custom_buckets(self): |
| 549 | + h = Histogram('custom', 'help', registry=self.registry, buckets=[-2, 0, 1, 1, 2]) |
| 550 | + h.observe_batch([-3, -2, 0, 1, 2, 3]) |
| 551 | + self.assertEqual(2, self.registry.get_sample_value('custom_bucket', {'le': '-2.0'})) |
| 552 | + self.assertEqual(3, self.registry.get_sample_value('custom_bucket', {'le': '0.0'})) |
| 553 | + self.assertEqual(4, self.registry.get_sample_value('custom_bucket', {'le': '1.0'})) |
| 554 | + self.assertEqual(5, self.registry.get_sample_value('custom_bucket', {'le': '2.0'})) |
| 555 | + self.assertEqual(6, self.registry.get_sample_value('custom_count')) |
| 556 | + |
| 557 | + def test_observe_batch_nonfinite(self): |
| 558 | + self.histogram.observe_batch([float('nan')]) |
| 559 | + self.assertEqual(0, self.registry.get_sample_value('h_count')) |
| 560 | + self.assertTrue(math.isnan(self.registry.get_sample_value('h_sum'))) |
| 561 | + self.histogram.observe_batch([float('-inf'), float('inf')]) |
| 562 | + self.assertEqual(1, self.registry.get_sample_value('h_bucket', {'le': '0.005'})) |
| 563 | + self.assertEqual(2, self.registry.get_sample_value('h_bucket', {'le': '+Inf'})) |
| 564 | + self.assertEqual(2, self.registry.get_sample_value('h_count')) |
| 565 | + self.assertTrue(math.isnan(self.registry.get_sample_value('h_sum'))) |
| 566 | + |
| 567 | + def test_observe_batch_invalid_amounts(self): |
| 568 | + self.histogram.observe(1) |
| 569 | + self.assertRaises(TypeError, self.histogram.observe_batch, [2, 'invalid']) |
| 570 | + self.assertEqual(1, self.registry.get_sample_value('h_count')) |
| 571 | + self.assertEqual(1, self.registry.get_sample_value('h_sum')) |
| 572 | + self.assertRaises(TypeError, self.histogram.observe_batch, [Decimal('1.5')]) |
| 573 | + self.assertEqual(1, self.registry.get_sample_value('h_count')) |
| 574 | + self.assertEqual(1, self.registry.get_sample_value('h_sum')) |
| 575 | + |
| 576 | + def test_observe_batch_iterators(self): |
| 577 | + self.histogram.observe_batch(iter(())) |
| 578 | + self.histogram.observe_batch(iter([1, 2])) |
| 579 | + self.histogram.observe_batch(x for x in [3, 4]) |
| 580 | + self.assertEqual(1, self.registry.get_sample_value('h_bucket', {'le': '1.0'})) |
| 581 | + self.assertEqual(2, self.registry.get_sample_value('h_bucket', {'le': '2.5'})) |
| 582 | + self.assertEqual(4, self.registry.get_sample_value('h_bucket', {'le': '+Inf'})) |
| 583 | + self.assertEqual(4, self.registry.get_sample_value('h_count')) |
| 584 | + self.assertEqual(10, self.registry.get_sample_value('h_sum')) |
| 585 | + |
| 586 | + def test_observe_batch_iteration_failure(self): |
| 587 | + def amounts(): |
| 588 | + yield 2 |
| 589 | + raise RuntimeError('iteration failed') |
| 590 | + |
| 591 | + self.histogram.observe(1) |
| 592 | + self.assertRaises(RuntimeError, self.histogram.observe_batch, amounts()) |
| 593 | + self.assertEqual(1, self.registry.get_sample_value('h_count')) |
| 594 | + self.assertEqual(1, self.registry.get_sample_value('h_sum')) |
| 595 | + |
| 596 | + def test_observe_batch_preserves_exemplars(self): |
| 597 | + self.histogram.observe(0.25, exemplar={'trace_id': 'abc'}) |
| 598 | + before = [s.exemplar for s in self.histogram.collect()[0].samples] |
| 599 | + self.histogram.observe_batch([0.125, 0.25, 1]) |
| 600 | + self.assertEqual(before, [s.exemplar for s in self.histogram.collect()[0].samples]) |
| 601 | + |
452 | 602 | def test_setting_buckets(self): |
453 | 603 | h = Histogram('h', 'help', registry=None, buckets=[0, 1, 2]) |
454 | 604 | self.assertEqual([0.0, 1.0, 2.0, float("inf")], h._upper_bounds) |
|
0 commit comments