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

[metric]Fix and improve #743

Merged
merged 5 commits into from
Aug 11, 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
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
Loading