Skip to content

Commit

Permalink
add capacity of metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos committed Jun 25, 2024
1 parent 865be82 commit 585aeaa
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 22 deletions.
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: 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

0 comments on commit 585aeaa

Please sign in to comment.