Skip to content

Commit

Permalink
[metric]Fix and improve (#743)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Aug 11, 2024
1 parent a679faf commit c465b6c
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 27 deletions.
76 changes: 75 additions & 1 deletion include/ylt/metric/counter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ inline void set_value(T &label_val, value_type value, op_type_t type) {
case op_type_t::INC: {
#ifdef __APPLE__
if constexpr (std::is_floating_point_v<value_type>) {
mac_os_atomic_fetch_add(&label_val.local_value(), value);
mac_os_atomic_fetch_add(&label_val, value);
}
else {
label_val += value;
Expand Down Expand Up @@ -211,6 +211,9 @@ class basic_dynamic_counter : public dynamic_metric {
}

std::lock_guard lock(mtx_);
if (value_map_.size() > ylt_label_capacity) {
return;
}
auto [it, r] = value_map_.try_emplace(
labels_value, thread_local_value<value_type>(dupli_count_));
if (r) {
Expand All @@ -222,6 +225,9 @@ class basic_dynamic_counter : public dynamic_metric {
value_type update(const std::array<std::string, N> &labels_value,
value_type value) {
std::lock_guard lock(mtx_);
if (value_map_.size() > ylt_label_capacity) {
return value_type{};
}
auto [it, r] = value_map_.try_emplace(
labels_value, thread_local_value<value_type>(dupli_count_));
return it->second.update(value);
Expand Down Expand Up @@ -257,6 +263,66 @@ class basic_dynamic_counter : public dynamic_metric {
return map;
}

size_t label_value_count() override {
std::lock_guard lock(mtx_);
return value_map_.size();
}

void remove_label_value(
const std::map<std::string, std::string> &labels) override {
{
std::lock_guard lock(mtx_);
if (value_map_.empty()) {
return;
}
}

const auto &labels_name = this->labels_name();
if (labels.size() > labels_name.size()) {
return;
}

if (labels.size() == labels_name.size()) {
std::vector<std::string> label_value;
for (auto &lb_name : labels_name) {
if (auto i = labels.find(lb_name); i != labels.end()) {
label_value.push_back(i->second);
}
}

std::lock_guard lock(mtx_);
std::erase_if(value_map_, [&, this](auto &pair) {
return equal(label_value, pair.first);
});
return;
}
else {
std::vector<std::string> vec;
for (auto &lb_name : labels_name) {
if (auto i = labels.find(lb_name); i != labels.end()) {
vec.push_back(i->second);
}
else {
vec.push_back("");
}
}
if (vec.empty()) {
return;
}

std::lock_guard lock(mtx_);
std::erase_if(value_map_, [&](auto &pair) {
auto &[arr, _] = pair;
for (size_t i = 0; i < vec.size(); i++) {
if (!vec[i].empty() && vec[i] != arr[i]) {
return false;
}
}
return true;
});
}
}

bool has_label_value(const std::string &value) override {
auto map = value_map();
for (auto &[label_value, _] : map) {
Expand Down Expand Up @@ -361,6 +427,14 @@ class basic_dynamic_counter : public dynamic_metric {
}
}

template <class T, std::size_t Size>
bool equal(const std::vector<T> &v, const std::array<T, Size> &a) {
if (v.size() != N)
return false;

return std::equal(v.begin(), v.end(), a.begin());
}

void build_string(std::string &str, const std::vector<std::string> &v1,
const auto &v2) {
for (size_t i = 0; i < v1.size(); i++) {
Expand Down
3 changes: 3 additions & 0 deletions include/ylt/metric/gauge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ class basic_dynamic_gauge : public basic_dynamic_counter<value_type, N> {
}

std::lock_guard lock(mtx_);
if (value_map_.size() > ylt_label_capacity) {
return;
}
auto [it, r] = value_map_.try_emplace(
labels_value, thread_local_value<value_type>(dupli_count_));
if (r) {
Expand Down
46 changes: 28 additions & 18 deletions include/ylt/metric/metric.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ struct metric_filter_options {
bool is_white = true;
};

#ifdef __APPLE__
inline double mac_os_atomic_fetch_add(std::atomic<double>* obj, double arg) {
double v;
do {
v = obj->load();
} while (!std::atomic_compare_exchange_weak(obj, &v, v + arg));
return v;
}

inline double mac_os_atomic_fetch_sub(std::atomic<double>* obj, double arg) {
double v;
do {
v = obj->load();
} while (!std::atomic_compare_exchange_weak(obj, &v, v - arg));
return v;
}
#endif

class metric_t {
public:
metric_t() = default;
Expand Down Expand Up @@ -109,6 +127,8 @@ class metric_t {
return static_labels_;
}

virtual size_t label_value_count() { return 0; }

virtual bool has_label_value(const std::string& label_value) {
return std::find(labels_value_.begin(), labels_value_.end(), label_value) !=
labels_value_.end();
Expand All @@ -133,6 +153,9 @@ class metric_t {
labels_name_.end();
}

virtual void remove_label_value(
const std::map<std::string, std::string>& labels) {}

virtual void serialize(std::string& str) {}

#ifdef CINATRA_ENABLE_METRIC_JSON
Expand Down Expand Up @@ -181,24 +204,6 @@ class metric_t {
str.pop_back();
}

#ifdef __APPLE__
double mac_os_atomic_fetch_add(std::atomic<double>* obj, double arg) {
double v;
do {
v = obj->load();
} while (!std::atomic_compare_exchange_weak(obj, &v, v + arg));
return v;
}

double mac_os_atomic_fetch_sub(std::atomic<double>* obj, double arg) {
double v;
do {
v = obj->load();
} while (!std::atomic_compare_exchange_weak(obj, &v, v - arg));
return v;
}
#endif

MetricType type_ = MetricType::Nil;
std::string name_;
std::string help_;
Expand All @@ -221,8 +226,13 @@ inline std::atomic<int64_t> g_summary_failed_count = 0;
inline std::atomic<int64_t> g_user_metric_count = 0;

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

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

inline void set_label_capacity(int64_t max_label_count) {
ylt_label_capacity = max_label_count;
}
} // namespace ylt::metric
61 changes: 54 additions & 7 deletions include/ylt/metric/metric_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,14 +350,55 @@ class dynamic_metric_manager {
}
}

void remove_metric_by_label(
const std::vector<std::pair<std::string, std::string>>& labels) {
std::vector<std::string> label_value;
for (auto& [k, v] : labels) {
label_value.push_back(v);
void remove_label_value(const std::map<std::string, std::string>& labels) {
std::unique_lock lock(mtx_);
for (auto& [_, m] : metric_map_) {
m->remove_label_value(labels);
}
}

remove_metric_by_label_value(label_value);
void remove_metric_by_label(
const std::map<std::string, std::string>& labels) {
std::unique_lock lock(mtx_);
for (auto it = metric_map_.begin(); it != metric_map_.end();) {
auto& m = it->second;
const auto& labels_name = m->labels_name();
if (labels.size() > labels_name.size()) {
continue;
}

if (labels.size() == labels_name.size()) {
std::vector<std::string> label_value;
for (auto& lb_name : labels_name) {
if (auto i = labels.find(lb_name); i != labels.end()) {
label_value.push_back(i->second);
}
}

std::erase_if(metric_map_, [&](auto& pair) {
return pair.second->has_label_value(label_value);
});
if (m->has_label_value(label_value)) {
metric_map_.erase(it);
}
break;
}
else {
bool need_erase = false;
for (auto& lb_name : labels_name) {
if (auto i = labels.find(lb_name); i != labels.end()) {
if (m->has_label_value(i->second)) {
it = metric_map_.erase(it);
need_erase = true;
break;
}
}
}

if (!need_erase)
++it;
}
}
}

void remove_metric_by_label_name(
Expand Down Expand Up @@ -517,9 +558,15 @@ struct metric_collector_t {
auto vec = get_all_metrics();
return manager_helper::serialize_to_json(vec);
}

static std::string serialize_to_json(
const std::vector<std::shared_ptr<metric_t>>& metrics) {
return manager_helper::serialize_to_json(metrics);
}
#endif

static std::string serialize(std::vector<std::shared_ptr<metric_t>> metrics) {
static std::string serialize(
const std::vector<std::shared_ptr<metric_t>>& metrics) {
return manager_helper::serialize(metrics);
}

Expand Down
25 changes: 24 additions & 1 deletion src/metric/tests/test_metric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,28 @@ TEST_CASE("test metric manager") {
CHECK(inst_d.metric_count() == 0);
inst_d.register_metric(dc);

inst_d.remove_metric_by_label({{"url", "/"}, {"code", "200"}});
inst_d.remove_metric_by_label({{"code", "400"}});
CHECK(inst_d.metric_count() == 1);
inst_d.remove_metric_by_label({{"code", "200"}});
CHECK(inst_d.metric_count() == 0);
inst_d.register_metric(dc);

inst_d.remove_label_value({{"code", "400"}});
CHECK(inst_d.metric_count() == 1);
inst_d.remove_label_value({{"code", "200"}});
CHECK(dc->label_value_count() == 0);
dc->inc({"/", "200"});

CHECK(dc->label_value_count() == 1);
inst_d.remove_label_value({{"url", "/"}});
CHECK(dc->label_value_count() == 0);
dc->inc({"/", "200"});

CHECK(dc->label_value_count() == 1);
inst_d.remove_label_value({{"url", "/"}, {"code", "200"}});
CHECK(dc->label_value_count() == 0);
dc->inc({"/", "200"});

inst_d.remove_metric_by_label_name(std::vector<std::string>{"url", "code"});
CHECK(inst_d.metric_count() == 0);
inst_d.register_metric(dc);
Expand Down Expand Up @@ -1260,6 +1278,11 @@ TEST_CASE("test serialize with emptry metrics") {
}

TEST_CASE("test serialize with multiple threads") {
{
dynamic_histogram_d h("test", "help", {5.23, 10.54, 20.0, 50.0, 100.0},
std::array<std::string, 2>{"url", "code"});
h.observe({"/", "code"}, 23);
}
auto c = std::make_shared<dynamic_counter_1t>(
std::string("get_count"), std::string("get counter"),
std::array<std::string, 1>{"method"});
Expand Down

0 comments on commit c465b6c

Please sign in to comment.