diff --git a/core/include/prometheus/histogram.h b/core/include/prometheus/histogram.h index a532129e..a06f3284 100644 --- a/core/include/prometheus/histogram.h +++ b/core/include/prometheus/histogram.h @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include #include "prometheus/client_metric.h" @@ -62,7 +64,28 @@ class PROMETHEUS_CPP_CORE_EXPORT Histogram { /// this function must have already sorted the values into buckets). /// Also increments the total sum of all observations by the given value. void ObserveMultiple(const std::vector& bucket_increments, - const double sum_of_values); + double sum_of_values); + + /// Same as above with custom iterator type. + template + void ObserveMultiple(InputIt from, InputIt end, double sum_of_values) { + std::lock_guard lock(mutex_); + sum_.Increment(sum_of_values); + + for (std::size_t i{0}; i < bucket_counts_.size(); ++i, ++from) { + if (from == end) { + throw std::length_error( + "The size of bucket_increments should be equal to " + "the number of buckets in the histogram."); + } + bucket_counts_[i].Increment(*from); + } + if (from != end) { + throw std::length_error( + "The size of bucket_increments should be equal to " + "the number of buckets in the histogram."); + } + } /// \brief Get the current value of the histogram. /// diff --git a/core/tests/histogram_test.cc b/core/tests/histogram_test.cc index 5b9959ae..bd3822c6 100644 --- a/core/tests/histogram_test.cc +++ b/core/tests/histogram_test.cc @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -89,7 +90,7 @@ TEST(HistogramTest, cumulative_bucket_count) { EXPECT_EQ(h.bucket.at(2).cumulative_count, 7U); } -TEST(HistogramTest, observe_multiple_test_bucket_counts) { +TEST(HistogramTest, observe_multiple_test_bucket_counts_1) { Histogram histogram{{1, 2}}; histogram.ObserveMultiple({5, 9, 3}, 20); histogram.ObserveMultiple({0, 20, 6}, 34); @@ -101,6 +102,20 @@ TEST(HistogramTest, observe_multiple_test_bucket_counts) { EXPECT_EQ(h.bucket.at(2).cumulative_count, 43U); } +TEST(HistogramTest, observe_multiple_test_bucket_counts_2) { + Histogram histogram{{1, 2}}; + const std::forward_list values1 = {5, 9, 3}; + const std::forward_list values2 = {0, 20, 6}; + histogram.ObserveMultiple(values1.begin(), values1.end(), 20); + histogram.ObserveMultiple(values2.begin(), values2.end(), 34); + auto metric = histogram.Collect(); + auto h = metric.histogram; + ASSERT_EQ(h.bucket.size(), 3U); + EXPECT_EQ(h.bucket.at(0).cumulative_count, 5U); + EXPECT_EQ(h.bucket.at(1).cumulative_count, 34U); + EXPECT_EQ(h.bucket.at(2).cumulative_count, 43U); +} + TEST(HistogramTest, observe_multiple_test_total_sum) { Histogram histogram{{1, 2}}; histogram.ObserveMultiple({5, 9, 3}, 20); @@ -111,13 +126,23 @@ TEST(HistogramTest, observe_multiple_test_total_sum) { EXPECT_EQ(h.sample_sum, 54); } -TEST(HistogramTest, observe_multiple_test_length_error) { +TEST(HistogramTest, observe_multiple_test_length_error1) { Histogram histogram{{1, 2}}; // 2 bucket boundaries means there are 3 buckets, so giving just 2 bucket // increments should result in a length_error. ASSERT_THROW(histogram.ObserveMultiple({5, 9}, 20), std::length_error); } +TEST(HistogramTest, observe_multiple_test_length_error2) { + Histogram histogram{{1, 2}}; + const std::forward_list values1 = {5, 9}; + ASSERT_THROW(histogram.ObserveMultiple(values1.begin(), values1.end(), 20), + std::length_error); + const std::forward_list values2 = {5, 9, 5, 6}; + ASSERT_THROW(histogram.ObserveMultiple(values2.begin(), values2.end(), 20), + std::length_error); +} + TEST(HistogramTest, sum_can_go_down) { Histogram histogram{{1}}; auto metric1 = histogram.Collect();