Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add capacity of metrics #699

Merged
merged 2 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions include/ylt/metric/counter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class counter_t : public metric_t {

virtual ~counter_t() { g_user_metric_count--; }

double value() { return default_lable_value_; }
double value() { return default_label_value_; }

double value(const std::vector<std::string> &labels_value) {
if (use_atomic_) {
Expand All @@ -78,7 +78,7 @@ class counter_t : public metric_t {

void serialize(std::string &str) override {
if (labels_name_.empty()) {
if (default_lable_value_ == 0) {
if (default_label_value_ == 0) {
return;
}
serialize_head(str);
Expand All @@ -103,11 +103,11 @@ class counter_t : public metric_t {
void serialize_to_json(std::string &str) override {
std::string s;
if (labels_name_.empty()) {
if (default_lable_value_ == 0) {
if (default_label_value_ == 0) {
return;
}
json_counter_t counter{name_, help_, std::string(metric_name())};
int64_t value = default_lable_value_;
int64_t value = default_label_value_;
counter.metrics.push_back({{}, value});
iguana::to_json(counter, str);
return;
Expand Down Expand Up @@ -144,9 +144,9 @@ class counter_t : public metric_t {
}

#ifdef __APPLE__
mac_os_atomic_fetch_add(&default_lable_value_, val);
mac_os_atomic_fetch_add(&default_label_value_, val);
#else
default_lable_value_ += val;
default_label_value_ += val;
#endif
}

Expand All @@ -172,15 +172,11 @@ class counter_t : public metric_t {

void stat_metric(const std::vector<std::string> &labels_value) {
if (!value_map_.contains(labels_value)) {
for (auto &key : labels_value) {
g_user_metric_memory->inc(key.size());
}
g_user_metric_memory->inc(8);
g_user_metric_labels->inc();
}
}

void update(double value) { default_lable_value_ = value; }
void update(double value) { default_label_value_ = value; }

void update(const std::vector<std::string> &labels_value, double value) {
if (labels_value.empty() || labels_name_.size() != labels_value.size()) {
Expand Down Expand Up @@ -212,10 +208,10 @@ class counter_t : public metric_t {
}

if (type_ == MetricType::Counter) {
str.append(std::to_string((int64_t)default_lable_value_));
str.append(std::to_string((int64_t)default_label_value_));
}
else {
str.append(std::to_string(default_lable_value_));
str.append(std::to_string(default_label_value_));
}

str.append("\n");
Expand Down Expand Up @@ -305,7 +301,7 @@ class counter_t : public metric_t {
}

metric_hash_map<std::atomic<double>> atomic_value_map_;
std::atomic<double> default_lable_value_ = 0;
std::atomic<double> default_label_value_ = 0;

std::mutex mtx_;
metric_hash_map<double> value_map_;
Expand Down
4 changes: 2 additions & 2 deletions include/ylt/metric/gauge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ class gauge_t : public counter_t {

void dec(double value = 1) {
#ifdef __APPLE__
mac_os_atomic_fetch_sub(&default_lable_value_, value);
mac_os_atomic_fetch_sub(&default_label_value_, value);
#else
default_lable_value_ -= value;
default_label_value_ -= value;
#endif
}

Expand Down
6 changes: 6 additions & 0 deletions include/ylt/metric/histogram.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class histogram_t : public metric_t {
throw std::invalid_argument("Bucket Boundaries must be strictly sorted");
}

g_user_metric_count++;

for (size_t i = 0; i < buckets.size() + 1; i++) {
bucket_counts_.push_back(std::make_shared<counter_t>("", ""));
}
Expand All @@ -51,6 +53,8 @@ class histogram_t : public metric_t {
throw std::invalid_argument("Bucket Boundaries must be strictly sorted");
}

g_user_metric_count++;

for (size_t i = 0; i < buckets.size() + 1; i++) {
bucket_counts_.push_back(
std::make_shared<counter_t>(name, help, labels_name));
Expand All @@ -66,6 +70,8 @@ class histogram_t : public metric_t {
throw std::invalid_argument("Bucket Boundaries must be strictly sorted");
}

g_user_metric_count++;

for (size_t i = 0; i < buckets.size() + 1; i++) {
bucket_counts_.push_back(std::make_shared<counter_t>(name, help, labels));
}
Expand Down
63 changes: 60 additions & 3 deletions include/ylt/metric/metric.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <regex>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>

#include "async_simple/coro/Lazy.h"
Expand Down Expand Up @@ -208,14 +209,18 @@ struct ylt_system_tag_t {};
using system_metric_manager = metric_manager_t<ylt_system_tag_t>;

class counter_t;
inline auto g_user_metric_memory =
std::make_shared<counter_t>("ylt_user_metric_memory", "");
inline auto g_user_metric_labels =
std::make_shared<counter_t>("ylt_user_metric_labels", "");
inline auto g_summary_failed_count =
std::make_shared<counter_t>("ylt_summary_failed_count", "");
inline std::atomic<int64_t> g_user_metric_count = 0;

inline std::atomic<int64_t> ylt_metric_capacity = 10000000;

inline void set_metric_capacity(int64_t max_count) {
ylt_metric_capacity = max_count;
}

template <typename Tag>
struct metric_manager_t {
struct null_mutex_t {
Expand Down Expand Up @@ -264,13 +269,59 @@ struct metric_manager_t {
return remove_metric_impl<true>(name);
}

static bool remove_metric_dynamic(std::shared_ptr<metric_t> metric) {
return remove_metric_impl<true>(std::string(metric->name()));
}

static void remove_metric_dynamic(const std::vector<std::string>& names) {
if (names.empty()) {
return;
}
auto lock = get_lock<true>();
for (auto& name : names) {
metric_map_.erase(name);
}
}

static void remove_metric_dynamic(
std::vector<std::shared_ptr<metric_t>> metrics) {
if (metrics.empty()) {
return;
}
auto lock = get_lock<true>();
for (auto& metric : metrics) {
metric_map_.erase(std::string(metric->name()));
}
}

template <typename... Metrics>
static bool register_metric_dynamic(Metrics... metrics) {
bool r = true;
((void)(r && (r = register_metric_impl<true>(metrics), true)), ...);
return r;
}

static bool register_metric_dynamic(
std::vector<std::shared_ptr<metric_t>> metrics) {
bool r = true;
std::vector<std::shared_ptr<metric_t>> vec;
for (auto& metric : metrics) {
r = register_metric_impl<true>(metric);
if (!r) {
r = false;
break;
}

vec.push_back(metric);
}

if (!r) {
remove_metric_dynamic(vec);
}

return r;
}

template <typename... Metrics>
static bool register_metric_static(Metrics... metrics) {
bool r = true;
Expand Down Expand Up @@ -476,6 +527,11 @@ struct metric_manager_t {

std::string name(metric->name());
auto lock = get_lock<need_lock>();
if (g_user_metric_count > ylt_metric_capacity) {
CINATRA_LOG_ERROR << "metric count at capacity size: "
<< g_user_metric_count;
return false;
}
bool r = metric_map_.emplace(name, std::move(metric)).second;
if (!r) {
CINATRA_LOG_ERROR << "duplicate registered metric name: " << name;
Expand Down Expand Up @@ -597,7 +653,8 @@ struct metric_manager_t {
}

static inline std::mutex mtx_;
static inline std::map<std::string, std::shared_ptr<metric_t>> metric_map_;
static inline std::unordered_map<std::string, std::shared_ptr<metric_t>>
metric_map_;

static inline null_mutex_t null_mtx_;
static inline std::atomic_bool need_lock_ = true;
Expand Down
3 changes: 3 additions & 0 deletions include/ylt/metric/summary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class summary_t : public metric_t {
block_->quantile_values_ =
std::make_shared<TimeWindowQuantiles>(quantiles_, max_age, age_buckets);
use_atomic_ = true;
g_user_metric_count++;
}

summary_t(std::string name, std::string help, Quantiles quantiles,
Expand All @@ -58,6 +59,7 @@ class summary_t : public metric_t {
max_age_(max_age),
age_buckets_(age_buckets) {
init_block(labels_block_);
g_user_metric_count++;
}

summary_t(std::string name, std::string help, Quantiles quantiles,
Expand All @@ -75,6 +77,7 @@ class summary_t : public metric_t {
labels_block_->label_count_.emplace(labels_value_, 0);
labels_block_->label_sum_.emplace(labels_value_, 0);
use_atomic_ = true;
g_user_metric_count++;
}

~summary_t() {
Expand Down
3 changes: 1 addition & 2 deletions include/ylt/metric/system_metric.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ inline void stat_memory() {
file >> virtual_size >> resident >> share;
static long page_size = sysconf(_SC_PAGE_SIZE);

process_memory_virtual->update(virtual_size);
process_memory_virtual->update(virtual_size * page_size);
process_memory_resident->update(resident * page_size);
process_memory_shared->update(share * page_size);
}
Expand Down Expand Up @@ -324,7 +324,6 @@ inline bool start_system_metric() {
system_metric_manager::create_metric_static<gauge_t>(
"ylt_process_io_write_second", "");

system_metric_manager::register_metric_static(g_user_metric_memory);
system_metric_manager::register_metric_static(g_user_metric_labels);
system_metric_manager::register_metric_static(g_summary_failed_count);

Expand Down
69 changes: 68 additions & 1 deletion src/metric/tests/test_metric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ TEST_CASE("test remove metric and serialize metrics") {
auto s = metric_mgr2::serialize_to_json_static();
std::cout << s << "\n";
auto s1 = metric_mgr2::serialize_to_json({c, c2});
CHECK(s == s1);
CHECK(s.size() == s1.size());
#endif
CHECK_THROWS_AS(metric_mgr2::metric_count_dynamic(), std::invalid_argument);
count = metric_mgr2::metric_count_static();
Expand Down Expand Up @@ -973,6 +973,73 @@ TEST_CASE("test system metric") {
}
#endif

TEST_CASE("test metric capacity") {
std::cout << g_user_metric_count << "\n";
using test_metric_manager = metric_manager_t<test_id_t<21>>;
set_metric_capacity(g_user_metric_count + 2);
auto c = test_metric_manager::create_metric_dynamic<counter_t>("counter", "");
CHECK(c != nullptr);
auto c1 =
test_metric_manager::create_metric_dynamic<counter_t>("counter1", "");
CHECK(c1 != nullptr);
auto c2 =
test_metric_manager::create_metric_dynamic<counter_t>("counter2", "");
CHECK(c2 == nullptr);
set_metric_capacity(10000000);

auto process_memory_resident =
system_metric_manager::get_metric_static<gauge_t>(
"ylt_process_memory_resident");
std::cout << (int64_t)process_memory_resident->value() << "\n";

auto process_memory_virtual =
system_metric_manager::get_metric_static<gauge_t>(
"ylt_process_memory_virtual");
std::cout << (int64_t)process_memory_virtual->value() << "\n";
}

TEST_CASE("test remove dynamic metric") {
using test_metric_manager = metric_manager_t<test_id_t<22>>;
auto c = test_metric_manager::create_metric_dynamic<counter_t>("counter", "");
CHECK(c != nullptr);
auto c1 =
test_metric_manager::create_metric_dynamic<counter_t>("counter1", "");
CHECK(c1 != nullptr);
auto c2 =
test_metric_manager::create_metric_dynamic<counter_t>("counter2", "");
CHECK(c2 != nullptr);

test_metric_manager::remove_metric_dynamic(c);
CHECK(test_metric_manager::metric_count_dynamic() == 2);
test_metric_manager::remove_metric_dynamic(c1);
CHECK(test_metric_manager::metric_count_dynamic() == 1);
test_metric_manager::remove_metric_dynamic(c2);
CHECK(test_metric_manager::metric_count_dynamic() == 0);

test_metric_manager::register_metric_dynamic(c, c1, c2);
CHECK(test_metric_manager::metric_count_dynamic() == 3);
test_metric_manager::remove_metric_dynamic("counter");
CHECK(test_metric_manager::metric_count_dynamic() == 2);
test_metric_manager::remove_metric_dynamic(
std::vector<std::string>{"counter1", "counter2"});
CHECK(test_metric_manager::metric_count_dynamic() == 0);

test_metric_manager::register_metric_dynamic(
std::vector<std::shared_ptr<metric_t>>{c, c1, c2});
CHECK(test_metric_manager::metric_count_dynamic() == 3);
test_metric_manager::remove_metric_dynamic({c1, c2});
CHECK(test_metric_manager::metric_count_dynamic() == 1);
auto r = test_metric_manager::register_metric_dynamic(
std::vector<std::shared_ptr<metric_t>>{c, c1});
CHECK(!r);
CHECK(test_metric_manager::metric_count_dynamic() == 1);

r = test_metric_manager::register_metric_dynamic(
std::vector<std::shared_ptr<metric_t>>{c1, c});
CHECK(!r);
CHECK(test_metric_manager::metric_count_dynamic() == 1);
}

DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007)
int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
DOCTEST_MSVC_SUPPRESS_WARNING_POP
Loading