Skip to content

Commit

Permalink
[metric] refactor metric
Browse files Browse the repository at this point in the history
  • Loading branch information
poor-circle committed Sep 25, 2024
1 parent 6980632 commit 8e0623c
Show file tree
Hide file tree
Showing 15 changed files with 714 additions and 674 deletions.
353 changes: 89 additions & 264 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
35 changes: 6 additions & 29 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 @@ -50,44 +52,19 @@ 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_;

public:
basic_dynamic_gauge(std::string name, std::string help,
std::array<std::string, N> labels_name,
size_t dupli_count = 2)
std::array<std::string, N> labels_name)
: basic_dynamic_counter<value_type, N>(std::move(name), std::move(help),
std::move(labels_name),
dupli_count) {
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);
basic_dynamic_counter<value_type, N>::try_emplace(labels_value)
->value.fetch_sub(value, std::memory_order::relaxed);
}
};

Expand Down
33 changes: 17 additions & 16 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,7 +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(
Expand All @@ -167,18 +167,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 +204,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 +213,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 +254,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 +267,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

0 comments on commit 8e0623c

Please sign in to comment.