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] refactor code #784

Merged
merged 4 commits into from
Sep 26, 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
356 changes: 85 additions & 271 deletions include/ylt/metric/counter.hpp

Large diffs are not rendered by default.

146 changes: 146 additions & 0 deletions include/ylt/metric/dynamic_metric.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#pragma once
#include "metric.hpp"
namespace ylt::metric {

class dynamic_metric : public metric_t {
public:
using metric_t::metric_t;
};

template <typename core_type, uint8_t N>
class dynamic_metric_impl : public dynamic_metric {
struct my_hash {
using is_transparent = void;
std::size_t operator()(
const std::span<const std::string, N>& s) const noexcept {
unsigned int seed = 131;
unsigned int hash = 0;
for (const auto& str : s) {
for (auto ch : str) {
hash = hash * seed + ch;
}
}
return hash;
}
std::size_t operator()(
const std::span<std::string_view, N>& s) const noexcept {
unsigned int seed = 131;
unsigned int hash = 0;
for (const auto& str : s) {
for (auto ch : str) {
hash = hash * seed + ch;
}
}
return hash;
}
};
struct my_equal {
bool operator()(const std::span<const std::string, N>& s1,
const std::span<const std::string, N>& s2) const noexcept {
if constexpr (N > 0) {
for (int i = 0; i < N; ++i) {
if (s1[i] != s2[i]) {
return false;
}
}
}
return true;
}
};
using key_type = std::array<std::string, N>;
struct metric_pair {
public:
key_type label;
core_type value;
template <typename T, typename... Args>
metric_pair(T&& first, Args&&... args)
: label(std::forward<T>(first)), value(std::forward<Args>(args)...) {
g_user_metric_label_count->inc();
if (ylt_label_max_age.count()) {
tp = std::chrono::steady_clock::now();
}
}
std::chrono::steady_clock::time_point get_created_time() const {
return tp;
}

private:
std::chrono::steady_clock::time_point tp;
};

struct value_type : public std::shared_ptr<metric_pair> {
value_type() : std::shared_ptr<metric_pair>(nullptr) {}
template <typename... Args>
value_type(Args&&... args)
: std::shared_ptr<metric_pair>(
std::make_shared<metric_pair>(std::forward<Args>(args)...)){};
};

public:
using dynamic_metric::dynamic_metric;
size_t size() const {
std::lock_guard guard(mtx_);
return table.size();
}
size_t empty() const { return !size(); }
size_t label_value_count() const { return size(); }

std::vector<std::shared_ptr<metric_pair>> copy() const {
std::lock_guard guard(mtx_);
std::vector<std::shared_ptr<metric_pair>> ret;
ret.reserve(table.size());
for (auto& e : table) {
ret.push_back(e.second);
}
return ret;
}

protected:
template <typename Key, typename... Args>
std::shared_ptr<metric_pair> try_emplace(Key&& key, Args&&... args) {
std::lock_guard guard(mtx_);
std::span<const std::string, N> view = key;
auto iter = table.try_emplace(view, std::forward<Key>(key),
std::forward<Args>(args)...);
if (iter.second) {
*const_cast<std::span<const std::string, N>*>(&iter.first->first) =
iter.first->second->label;
}
return table
.try_emplace(view, std::forward<Key>(key), std::forward<Args>(args)...)
.first->second;
}
void clean_expired_label() override {
erase_if([now = std::chrono::steady_clock::now()](auto& pair) mutable {
bool r = std::chrono::duration_cast<std::chrono::seconds>(
now - pair.second->get_created_time())
.count() >= ylt_label_max_age.count();
return r;
});
}
std::shared_ptr<metric_pair> find(std::span<const std::string, N> key) {
std::lock_guard guard(mtx_);
auto iter = table.find(key);
if (iter != table.end()) {
return iter->second;
}
else {
return nullptr;
}
}
size_t erase(std::span<const std::string, N> key) {
std::lock_guard guard(mtx_);
return table.erase(key);
}
void erase_if(auto&& op) {
std::lock_guard guard(mtx_);
std::erase_if(table, op);
}

private:
mutable std::mutex mtx_;
std::unordered_map<std::span<const std::string, N>, value_type, my_hash,
my_equal>
table;
};
} // namespace ylt::metric
45 changes: 6 additions & 39 deletions include/ylt/metric/gauge.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once
#include <atomic>
#include <chrono>

#include "counter.hpp"
#include "ylt/metric/metric.hpp"

namespace ylt::metric {

Expand Down Expand Up @@ -32,16 +34,7 @@ class basic_static_gauge : public basic_static_counter<value_type> {
if (!has_change_) [[unlikely]] {
has_change_ = true;
}
#ifdef __APPLE__
if constexpr (std::is_floating_point_v<value_type>) {
mac_os_atomic_fetch_sub(&default_label_value_.local_value(), value);
}
else {
default_label_value_.dec(value);
}
#else
default_label_value_.dec(value);
#endif
}
};
using gauge_t = basic_static_gauge<int64_t>;
Expand All @@ -50,44 +43,18 @@ using gauge_d = basic_static_gauge<double>;
template <typename value_type, uint8_t N>
class basic_dynamic_gauge : public basic_dynamic_counter<value_type, N> {
using metric_t::set_metric_type;
using basic_dynamic_counter<value_type, N>::value_map_;
using basic_dynamic_counter<value_type, N>::mtx_;
using basic_dynamic_counter<value_type, N>::dupli_count_;
using basic_dynamic_counter<value_type, N>::has_change_;
using Base = basic_dynamic_counter<value_type, N>;

public:
basic_dynamic_gauge(std::string name, std::string help,
std::array<std::string, N> labels_name,
size_t dupli_count = 2)
: basic_dynamic_counter<value_type, N>(std::move(name), std::move(help),
std::move(labels_name),
dupli_count) {
std::array<std::string, N> labels_name)
: Base(std::move(name), std::move(help), std::move(labels_name)) {
set_metric_type(MetricType::Gauge);
}

void dec(const std::array<std::string, N>& labels_value,
value_type value = 1) {
if (value == 0) {
return;
}

std::unique_lock lock(mtx_);
if (value_map_.size() > ylt_label_capacity) {
return;
}
if (!has_change_) [[unlikely]]
has_change_ = true;
auto [it, r] = value_map_.try_emplace(
labels_value, thread_local_value<value_type>(dupli_count_));
lock.unlock();
if (r) {
g_user_metric_label_count->local_value()++;
if (ylt_label_max_age.count()) {
it->second.set_created_time(std::chrono::system_clock::now());
}
}

set_value(it->second.local_value(), value, op_type_t::DEC);
detail::dec_impl(Base::try_emplace(labels_value)->value, value);
}
};

Expand Down
34 changes: 17 additions & 17 deletions include/ylt/metric/histogram.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include <vector>

#include "counter.hpp"
#include "metric.hpp"
#include "dynamic_metric.hpp"
#include "gauge.hpp"

namespace ylt::metric {
#ifdef CINATRA_ENABLE_METRIC_JSON
Expand Down Expand Up @@ -140,8 +141,6 @@ class basic_static_histogram : public static_metric {

private:
void init_bucket_counter(size_t dupli_count, size_t bucket_size) {
g_user_metric_count++;

for (size_t i = 0; i < bucket_size + 1; i++) {
bucket_counts_.push_back(
std::make_shared<counter_t>("", "", dupli_count));
Expand All @@ -167,18 +166,15 @@ class basic_dynamic_histogram : public dynamic_metric {
public:
basic_dynamic_histogram(std::string name, std::string help,
std::vector<double> buckets,
std::array<std::string, N> labels_name,
size_t dupli_count = 2)
std::array<std::string, N> labels_name)
: bucket_boundaries_(buckets),
dynamic_metric(MetricType::Histogram, name, help, labels_name),
sum_(std::make_shared<basic_dynamic_gauge<value_type, N>>(
name, help, labels_name, dupli_count)) {
g_user_metric_count++;

name, help, labels_name)) {
for (size_t i = 0; i < buckets.size() + 1; i++) {
bucket_counts_.push_back(
std::make_shared<basic_dynamic_counter<value_type, N>>(
name, help, labels_name, dupli_count));
std::make_shared<basic_dynamic_counter<value_type, N>>(name, help,
labels_name));
}
}

Expand Down Expand Up @@ -207,7 +203,7 @@ class basic_dynamic_histogram : public dynamic_metric {
}

void serialize(std::string &str) override {
auto value_map = sum_->value_map();
auto value_map = sum_->copy();
if (value_map.empty()) {
return;
}
Expand All @@ -216,8 +212,10 @@ class basic_dynamic_histogram : public dynamic_metric {

std::string value_str;
auto bucket_counts = get_bucket_counts();
for (auto &[labels_value, value] : value_map) {
if (value.value() == 0) {
for (auto &e : value_map) {
auto &labels_value = e->label;
auto &value = e->value;
if (value == 0) {
continue;
}

Expand Down Expand Up @@ -255,7 +253,7 @@ class basic_dynamic_histogram : public dynamic_metric {
build_label_string(str, sum_->labels_name(), labels_value);
str.append("} ");

str.append(std::to_string(value.value()));
str.append(std::to_string(value));
str.append("\n");

str.append(name_).append("_count{");
Expand All @@ -268,16 +266,18 @@ class basic_dynamic_histogram : public dynamic_metric {

#ifdef CINATRA_ENABLE_METRIC_JSON
void serialize_to_json(std::string &str) override {
auto value_map = sum_->value_map();
auto value_map = sum_->copy();
if (value_map.empty()) {
return;
}

json_histogram_t hist{name_, help_, std::string(metric_name())};
auto bucket_counts = get_bucket_counts();

for (auto &[labels_value, value] : value_map) {
if (value.value() == 0) {
for (auto &e : value_map) {
auto &labels_value = e->label;
auto &value = e->value;
if (value == 0) {
continue;
}

Expand Down
Loading
Loading