diff --git a/include/ylt/metric/counter.hpp b/include/ylt/metric/counter.hpp index db9eb953d..cf690af7c 100644 --- a/include/ylt/metric/counter.hpp +++ b/include/ylt/metric/counter.hpp @@ -166,9 +166,9 @@ class basic_static_counter : public static_metric { uint32_t dupli_count_ = 2; }; -template +template struct array_hash { - size_t operator()(const std::array &arr) const { + size_t operator()(const Key &arr) const { unsigned int seed = 131; unsigned int hash = 0; @@ -185,11 +185,10 @@ struct array_hash { using counter_t = basic_static_counter; using counter_d = basic_static_counter; -template -using dynamic_metric_hash_map = - std::unordered_map, T, array_hash>; +template +using dynamic_metric_hash_map = std::unordered_map>; -template +template class basic_dynamic_counter : public dynamic_metric { public: // dynamic labels value @@ -264,8 +263,12 @@ class basic_dynamic_counter : public dynamic_metric { return val; } - dynamic_metric_hash_map, N> value_map() { - dynamic_metric_hash_map, N> map; + dynamic_metric_hash_map, + thread_local_value> + value_map() { + dynamic_metric_hash_map, + thread_local_value> + map; { std::lock_guard lock(mtx_); map = value_map_; @@ -378,7 +381,7 @@ class basic_dynamic_counter : public dynamic_metric { bool has_label_value(const std::vector &label_value) override { std::array arr{}; - size_t size = (std::min)(N, label_value.size()); + size_t size = (std::min)((size_t)N, label_value.size()); for (size_t i = 0; i < size; i++) { arr[i] = label_value[i]; } @@ -470,7 +473,9 @@ class basic_dynamic_counter : public dynamic_metric { } std::mutex mtx_; - dynamic_metric_hash_map, N> value_map_; + dynamic_metric_hash_map, + thread_local_value> + value_map_; size_t dupli_count_ = 2; }; diff --git a/include/ylt/metric/detail/ckms_quantiles.hpp b/include/ylt/metric/detail/ckms_quantiles.hpp index fd42a8c24..b56b6167e 100644 --- a/include/ylt/metric/detail/ckms_quantiles.hpp +++ b/include/ylt/metric/detail/ckms_quantiles.hpp @@ -117,7 +117,7 @@ class CKMSQuantiles { std::size_t idx = 0; std::size_t item = idx++; - for (std::size_t i = start; i < buffer_count_; ++i) { + for (uint16_t i = start; i < buffer_count_; ++i) { double v = buffer_[i]; while (idx < sample_.size() && sample_[item].value < v) { item = idx++; @@ -167,9 +167,9 @@ class CKMSQuantiles { private: const std::reference_wrapper> quantiles_; - std::size_t count_; + uint16_t count_; std::vector sample_; - std::array buffer_; - std::size_t buffer_count_; + std::array buffer_; + uint16_t buffer_count_; }; } // namespace ylt::metric \ No newline at end of file diff --git a/include/ylt/metric/detail/time_window_quantiles.hpp b/include/ylt/metric/detail/time_window_quantiles.hpp index 6b81179f0..07debac19 100644 --- a/include/ylt/metric/detail/time_window_quantiles.hpp +++ b/include/ylt/metric/detail/time_window_quantiles.hpp @@ -8,7 +8,7 @@ class TimeWindowQuantiles { public: TimeWindowQuantiles(const std::vector& quantiles, - Clock::duration max_age_seconds, int age_buckets) + Clock::duration max_age_seconds, uint16_t age_buckets) : quantiles_(quantiles), ckms_quantiles_(age_buckets, CKMSQuantiles(quantiles_)), current_bucket_(0), @@ -44,7 +44,7 @@ class TimeWindowQuantiles { const std::vector& quantiles_; mutable std::vector ckms_quantiles_; - mutable std::size_t current_bucket_; + mutable uint16_t current_bucket_; mutable Clock::time_point last_rotation_; const Clock::duration rotation_interval_; diff --git a/include/ylt/metric/gauge.hpp b/include/ylt/metric/gauge.hpp index c68d46de6..7deb301e9 100644 --- a/include/ylt/metric/gauge.hpp +++ b/include/ylt/metric/gauge.hpp @@ -43,7 +43,7 @@ class basic_static_gauge : public basic_static_counter { using gauge_t = basic_static_gauge; using gauge_d = basic_static_gauge; -template +template class basic_dynamic_gauge : public basic_dynamic_counter { using metric_t::set_metric_type; using basic_dynamic_counter::value_map_; diff --git a/include/ylt/metric/histogram.hpp b/include/ylt/metric/histogram.hpp index 7da52da4f..4b4fe1406 100644 --- a/include/ylt/metric/histogram.hpp +++ b/include/ylt/metric/histogram.hpp @@ -162,7 +162,7 @@ class basic_static_histogram : public static_metric { using histogram_t = basic_static_histogram; using histogram_d = basic_static_histogram; -template +template class basic_dynamic_histogram : public dynamic_metric { public: basic_dynamic_histogram(std::string name, std::string help, diff --git a/include/ylt/metric/summary.hpp b/include/ylt/metric/summary.hpp index 270d1b66c..d7f9a5b6f 100644 --- a/include/ylt/metric/summary.hpp +++ b/include/ylt/metric/summary.hpp @@ -41,23 +41,19 @@ class summary_t : public static_metric { using Quantiles = std::vector; summary_t(std::string name, std::string help, Quantiles quantiles, std::chrono::milliseconds max_age = std::chrono::seconds{60}, - int age_buckets = 5) + uint16_t age_buckets = 5) : quantiles_{std::move(quantiles)}, - static_metric(MetricType::Summary, std::move(name), std::move(help)), - max_age_(max_age), - age_buckets_(age_buckets) { + static_metric(MetricType::Summary, std::move(name), std::move(help)) { init_no_label(max_age, age_buckets); } summary_t(std::string name, std::string help, Quantiles quantiles, std::map static_labels, std::chrono::milliseconds max_age = std::chrono::seconds{60}, - int age_buckets = 5) + uint16_t age_buckets = 5) : quantiles_{std::move(quantiles)}, static_metric(MetricType::Summary, std::move(name), std::move(help), - std::move(static_labels)), - max_age_(max_age), - age_buckets_(age_buckets) { + std::move(static_labels)) { init_no_label(max_age, age_buckets); } @@ -190,7 +186,7 @@ class summary_t : public static_metric { }); } - void init_no_label(std::chrono::milliseconds max_age, int age_buckets) { + void init_no_label(std::chrono::milliseconds max_age, uint16_t age_buckets) { init_block(block_); block_->quantile_values_ = std::make_shared(quantiles_, max_age, age_buckets); @@ -236,29 +232,33 @@ class summary_t : public static_metric { std::shared_ptr block_; static inline std::shared_ptr excutor_ = coro_io::create_io_context_pool(1); - std::chrono::milliseconds max_age_; - int age_buckets_; std::atomic is_coro_started_ = false; }; -template +template struct summary_label_sample { std::array labels_value; double value; }; -template +struct sum_and_count_t { + double sum; + uint64_t count; +}; + +template struct labels_block_t { std::atomic stop_ = false; ylt::detail::moodycamel::ConcurrentQueue> sample_queue_; - dynamic_metric_hash_map, N> + dynamic_metric_hash_map, + std::shared_ptr> label_quantile_values_; - dynamic_metric_hash_map label_count_; - dynamic_metric_hash_map label_sum_; + dynamic_metric_hash_map, sum_and_count_t> + sum_and_count_; }; -template +template class basic_dynamic_summary : public dynamic_metric { public: using Quantiles = std::vector; @@ -267,7 +267,7 @@ class basic_dynamic_summary : public dynamic_metric { std::string name, std::string help, Quantiles quantiles, std::array labels_name, std::chrono::milliseconds max_age = std::chrono::seconds{60}, - int age_buckets = 5) + uint16_t age_buckets = 5) : quantiles_{std::move(quantiles)}, dynamic_metric(MetricType::Summary, std::move(name), std::move(help), std::move(labels_name)), @@ -300,6 +300,14 @@ class basic_dynamic_summary : public dynamic_metric { size_t size_approx() { return labels_block_->sample_queue_.size_approx(); } + size_t label_value_count() override { + auto block = labels_block_; + return async_simple::coro::syncAwait(coro_io::post([block] { + return block->sum_and_count_.size(); + })) + .value(); + } + async_simple::coro::Lazy> get_rates( const std::array &labels_value, double &sum, uint64_t &count) { @@ -314,8 +322,8 @@ class basic_dynamic_summary : public dynamic_metric { if (it == labels_block_->label_quantile_values_.end()) { return; } - sum = labels_block_->label_sum_[labels_value]; - count = labels_block_->label_count_[labels_value]; + sum = labels_block_->sum_and_count_[labels_value].sum; + count = labels_block_->sum_and_count_[labels_value].count; for (const auto &quantile : quantiles_) { vec.push_back(it->second->get(quantile.quantile)); } @@ -325,15 +333,6 @@ class basic_dynamic_summary : public dynamic_metric { co_return vec; } - dynamic_metric_hash_map value_map() { - auto ret = async_simple::coro::syncAwait(coro_io::post( - [this] { - return labels_block_->label_sum_; - }, - excutor_->get_executor())); - return ret.value(); - } - async_simple::coro::Lazy serialize_async(std::string &str) override { co_await serialize_async_with_label(str); } @@ -368,8 +367,8 @@ class basic_dynamic_summary : public dynamic_metric { ptr->insert(sample.value); - label_block->label_count_[sample.labels_value] += 1; - label_block->label_sum_[sample.labels_value] += sample.value; + label_block->sum_and_count_[sample.labels_value].count += 1; + label_block->sum_and_count_[sample.labels_value].sum += sample.value; index++; if (index == count) { break; @@ -406,11 +405,11 @@ class basic_dynamic_summary : public dynamic_metric { auto sum_map = co_await coro_io::post( [this] { - return labels_block_->label_sum_; + return labels_block_->sum_and_count_; }, excutor_->get_executor()); - for (auto &[labels_value, sum_val] : sum_map.value()) { + for (auto &[labels_value, _] : sum_map.value()) { double sum = 0; uint64_t count = 0; auto rates = co_await get_rates(labels_value, sum, count); @@ -447,13 +446,13 @@ class basic_dynamic_summary : public dynamic_metric { auto sum_map = co_await coro_io::post( [this] { - return labels_block_->label_sum_; + return labels_block_->sum_and_count_; }, excutor_->get_executor()); json_summary_t summary{name_, help_, std::string(metric_name())}; - for (auto &[labels_value, sum_val] : sum_map.value()) { + for (auto &[labels_value, _] : sum_map.value()) { json_summary_metric_t metric; double sum = 0; uint64_t count = 0; @@ -478,7 +477,7 @@ class basic_dynamic_summary : public dynamic_metric { static inline std::shared_ptr excutor_ = coro_io::create_io_context_pool(1); std::chrono::milliseconds max_age_; - int age_buckets_; + uint16_t age_buckets_; std::atomic is_coro_started_ = false; };