diff --git a/include/cinatra/ylt/metric/counter.hpp b/include/cinatra/ylt/metric/counter.hpp index 19ff9f88..d801722a 100644 --- a/include/cinatra/ylt/metric/counter.hpp +++ b/include/cinatra/ylt/metric/counter.hpp @@ -60,12 +60,8 @@ class counter_t : public metric_t { } } - std::map, double, - std::less>> - value_map() override { - std::map, double, - std::less>> - map; + metric_hash_map value_map() override { + metric_hash_map map; if (use_atomic_) { map = {atomic_value_map_.begin(), atomic_value_map_.end()}; } @@ -192,9 +188,7 @@ class counter_t : public metric_t { } } - std::map, std::atomic, - std::less>> - &atomic_value_map() { + metric_hash_map> &atomic_value_map() { return atomic_value_map_; } @@ -298,14 +292,10 @@ class counter_t : public metric_t { } } - std::map, std::atomic, - std::less>> - atomic_value_map_; + metric_hash_map> atomic_value_map_; std::atomic default_lable_value_ = 0; std::mutex mtx_; - std::map, double, - std::less>> - value_map_; + metric_hash_map value_map_; }; } // namespace ylt::metric \ No newline at end of file diff --git a/include/cinatra/ylt/metric/histogram.hpp b/include/cinatra/ylt/metric/histogram.hpp index d85225a5..1f371b85 100644 --- a/include/cinatra/ylt/metric/histogram.hpp +++ b/include/cinatra/ylt/metric/histogram.hpp @@ -100,11 +100,7 @@ class histogram_t : public metric_t { auto get_bucket_counts() { return bucket_counts_; } - std::map, double, - std::less>> - value_map() override { - return sum_->value_map(); - } + metric_hash_map value_map() override { return sum_->value_map(); } void serialize(std::string &str) override { if (!sum_->labels_name().empty()) { diff --git a/include/cinatra/ylt/metric/metric.hpp b/include/cinatra/ylt/metric/metric.hpp index f818ed7e..12c25c6b 100644 --- a/include/cinatra/ylt/metric/metric.hpp +++ b/include/cinatra/ylt/metric/metric.hpp @@ -47,6 +47,25 @@ struct metric_filter_options { bool is_white = true; }; +struct vector_hash { + size_t operator()(const std::vector& vec) const { + unsigned int seed = 131; + unsigned int hash = 0; + + for (const auto& str : vec) { + for (auto ch : str) { + hash = hash * seed + ch; + } + } + + return (hash & 0x7FFFFFFF); + } +}; + +template +using metric_hash_map = + std::unordered_map, T, vector_hash>; + class metric_t { public: metric_t() = default; @@ -102,11 +121,7 @@ class metric_t { return static_labels_; } - virtual std::map, double, - std::less>> - value_map() { - return {}; - } + virtual metric_hash_map value_map() { return {}; } virtual void serialize(std::string& str) {} @@ -248,14 +263,6 @@ struct metric_manager_t { return r; } - static void set_metric_max_age(std::chrono::steady_clock::duration max_age, - std::chrono::steady_clock::duration - check_duration = std::chrono::minutes(5)) { - metric_max_age_ = max_age; - metric_check_duration_ = check_duration; - start_check(); - } - static auto metric_map_static() { return metric_map_impl(); } static auto metric_map_dynamic() { return metric_map_impl(); } @@ -565,63 +572,12 @@ struct metric_manager_t { return filtered_metrics; } - static void check_impl() { - check_timer_->expires_after(metric_check_duration_); - check_timer_->async_wait([](std::error_code ec) { - if (ec) { - return; - } - - check_clean_metrics(); - check_impl(); - }); - } - - static void start_check() { - if (has_start_check_metric_) { - return; - } - - has_start_check_metric_ = true; - - executor_ = coro_io::create_io_context_pool(1); - - check_timer_ = - std::make_shared(executor_->get_executor()); - - check_impl(); - } - - static void check_clean_metrics() { - auto cur_time = std::chrono::system_clock::now(); - { - auto lock = get_lock(); - for (auto it = metric_map_.begin(); it != metric_map_.end();) { - if (cur_time - it->second->get_created_time() > metric_max_age_) { - metric_map_.erase(it++); - } - else { - ++it; - } - } - } - } - - static inline bool has_start_check_metric_ = false; - static inline std::shared_ptr check_timer_ = nullptr; - static inline std::shared_ptr executor_ = nullptr; - static inline std::mutex mtx_; static inline std::map> metric_map_; static inline null_mutex_t null_mtx_; static inline std::atomic_bool need_lock_ = true; static inline std::once_flag flag_; - - static inline std::chrono::steady_clock::duration metric_max_age_{ - std::chrono::hours(24)}; - static inline std::chrono::steady_clock::duration metric_check_duration_{ - std::chrono::minutes(5)}; }; using default_metric_manager = metric_manager_t<0>; diff --git a/include/cinatra/ylt/metric/summary.hpp b/include/cinatra/ylt/metric/summary.hpp index fcf9f03a..58957bc7 100644 --- a/include/cinatra/ylt/metric/summary.hpp +++ b/include/cinatra/ylt/metric/summary.hpp @@ -98,24 +98,19 @@ class summary_t : public metric_t { struct labels_block_t { std::atomic stop_ = false; moodycamel::ConcurrentQueue sample_queue_; - - std::map, std::shared_ptr, - std::less>> + metric_hash_map> label_quantile_values_; - std::map, std::uint64_t, - std::less>> - label_count_; - std::map, double, - std::less>> - label_sum_; + metric_hash_map label_count_; + metric_hash_map label_sum_; }; void observe(double value) { if (!labels_name_.empty()) { throw std::invalid_argument("not a default label metric"); } - while (block_->sample_queue_.size_approx() >= 20000000) { - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + if (block_->sample_queue_.size_approx() >= 20000000) { + // TODO: record failed count. + return; } block_->sample_queue_.enqueue(value); @@ -135,8 +130,9 @@ class summary_t : public metric_t { throw std::invalid_argument("not equal with static label"); } } - while (labels_block_->sample_queue_.size_approx() >= 20000000) { - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + if (labels_block_->sample_queue_.size_approx() >= 20000000) { + // TODO: record failed count. + return; } labels_block_->sample_queue_.enqueue({std::move(labels_value), value}); @@ -198,9 +194,7 @@ class summary_t : public metric_t { co_return vec; } - std::map, double, - std::less>> - value_map() override { + metric_hash_map value_map() override { auto ret = async_simple::coro::syncAwait(coro_io::post( [this] { return labels_block_->label_sum_; diff --git a/lang/how_to_use_metrics.md b/lang/how_to_use_metrics.md index 3b14ae63..471a6b5a 100644 --- a/lang/how_to_use_metrics.md +++ b/lang/how_to_use_metrics.md @@ -109,8 +109,7 @@ void inc(const std::vector &labels_value, double value = 1); void serialize(std::string &str); // 返回带标签的指标内部的计数map,map的key是标签的值,值是对应计数,如:{{{"GET", "/"}, 100}, {{"POST", "/test"}, 20}} -std::map, double, - std::less>> +std::unordered_map, double, vector_hash> value_map(); ``` @@ -234,13 +233,6 @@ struct metric_manager_t { static bool register_metric_static(std::shared_ptr metric); static bool register_metric_dynamic(std::shared_ptr metric); - // 启用metric 定时清理功能,在使用metric之前设置 - // max_age:设置metric的过期时间,过期之后metric会被清理 - // check_duration:设置定期监测metric过期的时间间隔 - static void set_metric_max_age(std::chrono::steady_clock::duration max_age, - std::chrono::steady_clock::duration - check_duration = std::chrono::minutes(5)); - // 根据metric名称删除metric static bool remove_metric_static(const std::string& name); static bool remove_metric_dynamic(const std::string& name); diff --git a/tests/test_metric.cpp b/tests/test_metric.cpp index 1f78d722..86a6039d 100644 --- a/tests/test_metric.cpp +++ b/tests/test_metric.cpp @@ -777,30 +777,6 @@ TEST_CASE("test summary with static labels") { #endif } -TEST_CASE("check clean metrics") { - using metric_mgr = metric_manager_t<11>; - metric_mgr::create_metric_dynamic("test_counter", ""); - metric_mgr::create_metric_dynamic("test_counter2", ""); - metric_mgr::create_metric_dynamic( - "http_req_static_hist", "help", - std::vector{5.23, 10.54, 20.0, 50.0, 100.0}, - std::vector{"method", "url"}); - - metric_mgr::create_metric_dynamic( - "http_req_static_summary", "help", - summary_t::Quantiles{ - {0.5, 0.05}, {0.9, 0.01}, {0.95, 0.005}, {0.99, 0.001}}, - std::vector{"method", "url"}); - - CHECK(metric_mgr::metric_count_dynamic() == 4); - metric_mgr::set_metric_max_age(std::chrono::milliseconds(10), - std::chrono::milliseconds(10)); - - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - CHECK(metric_mgr::metric_count_dynamic() == 0); -} - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } DOCTEST_MSVC_SUPPRESS_WARNING_POP \ No newline at end of file