diff --git a/include/ylt/metric/counter.hpp b/include/ylt/metric/counter.hpp index d1d801ba1..35170ebd8 100644 --- a/include/ylt/metric/counter.hpp +++ b/include/ylt/metric/counter.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -14,17 +15,18 @@ enum class op_type_t { INC, DEC, SET }; #ifdef CINATRA_ENABLE_METRIC_JSON struct json_counter_metric_t { - std::map labels; + std::vector labels; std::variant value; }; YLT_REFL(json_counter_metric_t, labels, value); struct json_counter_t { - std::string name; - std::string help; - std::string type; + std::string_view name; + std::string_view help; + std::string_view type; + std::vector labels_name; std::vector metrics; }; -YLT_REFL(json_counter_t, name, help, type, metrics); +YLT_REFL(json_counter_t, name, help, type, labels_name, metrics); #endif template @@ -78,13 +80,23 @@ class basic_static_counter : public static_metric { #ifdef CINATRA_ENABLE_METRIC_JSON void serialize_to_json(std::string &str) override { - if (default_label_value_.value() == 0) { + auto value = default_label_value_.value(); + if (value == 0 && !has_change_) { return; } - json_counter_t counter{name_, help_, std::string(metric_name())}; - auto value = default_label_value_.value(); - counter.metrics.push_back({static_labels_, value}); + json_counter_t counter{name_, help_, metric_name()}; + + counter.labels_name.reserve(static_labels_.size()); + for (auto &[k, _] : static_labels_) { + counter.labels_name.emplace_back(k); + } + counter.metrics.resize(1); + counter.metrics[0].labels.reserve(static_labels_.size()); + for (auto &[k, _] : static_labels_) { + counter.metrics[0].labels.emplace_back(k); + } + counter.metrics[0].value = value; iguana::to_json(counter, str); } #endif @@ -248,10 +260,12 @@ class basic_dynamic_counter #ifdef CINATRA_ENABLE_METRIC_JSON void serialize_to_json(std::string &str) override { - std::string s; auto map = Base::copy(); - json_counter_t counter{Base::name_, Base::help_, - std::string(Base::metric_name())}; + json_counter_t counter{Base::name_, Base::help_, Base::metric_name()}; + counter.labels_name.reserve(Base::labels_name().size()); + for (auto &e : Base::labels_name()) { + counter.labels_name.emplace_back(e); + } to_json(counter, map, str); } @@ -262,10 +276,11 @@ class basic_dynamic_counter auto &val = e->value; json_counter_metric_t metric; size_t index = 0; + metric.labels.reserve(k.size()); for (auto &label_value : k) { - metric.labels.emplace(Base::labels_name_[index++], label_value); + metric.labels.emplace_back(label_value); } - metric.value = (int64_t)val; + metric.value = val.load(std::memory_order::relaxed); counter.metrics.push_back(std::move(metric)); } if (!counter.metrics.empty()) { @@ -279,7 +294,7 @@ class basic_dynamic_counter void serialize_map(T &value_map, std::string &str) { for (auto &e : value_map) { auto &labels_value = e->label; - auto &val = e->value; + auto val = e->value.load(std::memory_order::relaxed); str.append(Base::name_); if (Base::labels_name_.empty()) { str.append(" "); diff --git a/include/ylt/metric/summary.hpp b/include/ylt/metric/summary.hpp index 6caccb3f0..793e565de 100644 --- a/include/ylt/metric/summary.hpp +++ b/include/ylt/metric/summary.hpp @@ -17,19 +17,21 @@ namespace ylt::metric { #ifdef CINATRA_ENABLE_METRIC_JSON struct json_summary_metric_t { - std::map labels; - std::map quantiles; - int64_t count; + std::vector labels; + std::vector quantiles_value; + uint64_t count; double sum; }; -YLT_REFL(json_summary_metric_t, labels, quantiles, count, sum); +YLT_REFL(json_summary_metric_t, labels, quantiles_value, count, sum); struct json_summary_t { - std::string name; - std::string help; - std::string type; + std::string_view name; + std::string_view help; + std::string_view type; + const std::vector& labels_name; + const std::vector& quantiles_key; std::vector metrics; }; -YLT_REFL(json_summary_t, name, help, type, metrics); +YLT_REFL(json_summary_t, name, help, type, labels_name, quantiles_key, metrics); #endif class summary_t : public static_metric { @@ -114,29 +116,17 @@ class summary_t : public static_metric { return; } - double sum = 0; - uint64_t count = 0; - auto rates = get_rates(sum, count); - if (count == 0) { - return; - } - - json_summary_t summary{name_, help_, std::string(metric_name())}; - + json_summary_t summary{name_, help_, metric_name(), labels_name(), + quantiles_}; json_summary_metric_t metric; - for (size_t i = 0; i < quantiles_.size(); i++) { - for (size_t i = 0; i < labels_name_.size(); i++) { - metric.labels[labels_name_[i]] = labels_value_[i]; - } - metric.quantiles.emplace(quantiles_[i], rates[i]); + metric.quantiles_value = get_rates(metric.sum, metric.count); + if (metric.count == 0) { + return; } - - metric.sum = sum; - metric.count = count; - + metric.labels.reserve(labels_value_.size()); + for (auto& e : labels_value_) metric.labels.emplace_back(e); summary.metrics.push_back(std::move(metric)); - iguana::to_json(summary, str); } #endif @@ -228,26 +218,30 @@ class basic_dynamic_summary #ifdef CINATRA_ENABLE_METRIC_JSON virtual void serialize_to_json(std::string& str) override { - json_summary_t summary{Base::name_, Base::help_, - std::string(Base::metric_name())}; auto map = Base::copy(); - for (auto& e : map) { - auto& labels_value = e->label; - auto& summary_value = e->value; - json_summary_metric_t metric; + if (map.empty()) { + return; + } + json_summary_t summary{Base::name_, Base::help_, Base::metric_name(), + Base::labels_name(), quantiles_}; + summary.metrics.reserve(map.size()); + for (size_t i = 0; i < map.size(); ++i) { + auto& labels_value = map[i]->label; + auto& summary_value = map[i]->value; double sum = 0; uint64_t count = 0; auto rates = summary_value.stat(sum, count); + if (count == 0) + continue; + summary.metrics.emplace_back(); + json_summary_metric_t& metric = summary.metrics.back(); metric.count = count; metric.sum = sum; - for (size_t i = 0; i < quantiles_.size(); i++) { - for (size_t i = 0; i < labels_value.size(); i++) { - metric.labels[Base::labels_name_[i]] = labels_value[i]; - } - metric.quantiles.emplace(quantiles_[i], rates[i]); - } - summary.metrics.push_back(std::move(metric)); + metric.quantiles_value = std::move(rates); + metric.labels.reserve(labels_value.size()); + for (auto& e : labels_value) metric.labels.emplace_back(e); } + auto i3 = std::chrono::steady_clock::now(); iguana::to_json(summary, str); } #endif diff --git a/src/metric/tests/parallel_test.cpp b/src/metric/tests/parallel_test.cpp index 971d4aed9..3807e89a9 100644 --- a/src/metric/tests/parallel_test.cpp +++ b/src/metric/tests/parallel_test.cpp @@ -6,8 +6,10 @@ #include "ylt/metric.hpp" TEST_CASE("test high parallel perform test") { +#ifndef _MSC_VER bench_static_summary_mixed(std::thread::hardware_concurrency() * 4, 3s); bench_dynamic_summary_mixed(std::thread::hardware_concurrency() * 4, 2s); bench_static_counter_mixed(std::thread::hardware_concurrency() * 4, 2s); bench_static_counter_mixed(std::thread::hardware_concurrency() * 4, 2s); +#endif } \ No newline at end of file diff --git a/src/metric/tests/test_metric.cpp b/src/metric/tests/test_metric.cpp index b8d853281..ff7e99511 100644 --- a/src/metric/tests/test_metric.cpp +++ b/src/metric/tests/test_metric.cpp @@ -631,7 +631,8 @@ TEST_CASE("test gauge") { std::string str_json; g.serialize_to_json(str_json); std::cout << str_json << "\n"; - CHECK(str_json.find("\"code\":\"200\"") != std::string::npos); + std::cout << str_json.size() << std::endl; + CHECK(str_json.size() == 185); #endif std::string str; @@ -702,7 +703,8 @@ TEST_CASE("test summary") { std::string str_json; summary.serialize_to_json(str_json); std::cout << str_json << "\n"; - CHECK(str_json.find("\"0.9\":") != std::string::npos); + std::cout << str_json.size() << std::endl; + CHECK(str_json.size() == 195); #endif } @@ -731,7 +733,8 @@ TEST_CASE("test summary with INF") { std::string str_json; summary.serialize_to_json(str_json); std::cout << str_json << "\n"; - CHECK(str_json.find("\"0.9\":") != std::string::npos); + std::cout << str_json.size() << std::endl; + CHECK(str_json.size() == 238); #endif } @@ -760,7 +763,8 @@ TEST_CASE("test summary with NAN") { std::string str_json; summary.serialize_to_json(str_json); std::cout << str_json << "\n"; - CHECK(str_json.find("\"0.9\":") != std::string::npos); + std::cout << str_json.size() << std::endl; + CHECK(str_json.size() == 238); #endif } @@ -793,7 +797,8 @@ TEST_CASE("test summary with illegal quantities") { std::string str_json; summary.serialize_to_json(str_json); std::cout << str_json << "\n"; - CHECK(str_json.find("\"0.9\":") != std::string::npos); + std::cout << str_json.size() << std::endl; + CHECK(str_json.size() == 233); #endif } @@ -811,7 +816,7 @@ TEST_CASE("test summary with many quantities") { } std::string str; summary.serialize(str); - std::cout << str; + // std::cout << str; double sum; uint64_t cnt; auto result = summary.get_rates(sum, cnt); @@ -828,7 +833,8 @@ TEST_CASE("test summary with many quantities") { std::string str_json; summary.serialize_to_json(str_json); std::cout << str_json << "\n"; - CHECK(str_json.find("\"0.9\":") != std::string::npos); + std::cout << str_json.size() << std::endl; + CHECK(str_json.size() == 8868); #endif }