More scaffolding
This commit is contained in:
110
src/metric.cpp
110
src/metric.cpp
@@ -1,9 +1,15 @@
|
|||||||
#include "metric.hpp"
|
#include "metric.hpp"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace metric {
|
namespace metric {
|
||||||
struct MetricKey {
|
struct MetricKey {
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
@@ -33,9 +39,24 @@ template <> struct hash<metric::MetricKey> {
|
|||||||
|
|
||||||
namespace metric {
|
namespace metric {
|
||||||
|
|
||||||
struct Counter::State {};
|
using AtomicWord = std::atomic<uint64_t>;
|
||||||
struct Gauge::State {};
|
|
||||||
struct Histogram::State {};
|
struct Counter::State {
|
||||||
|
AtomicWord value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Gauge::State {
|
||||||
|
std::mutex mutex;
|
||||||
|
double value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Histogram::State {
|
||||||
|
std::vector<double> thresholds;
|
||||||
|
std::vector<AtomicWord> counts;
|
||||||
|
AtomicWord sum;
|
||||||
|
AtomicWord observations;
|
||||||
|
};
|
||||||
|
|
||||||
struct Metric {
|
struct Metric {
|
||||||
|
|
||||||
static std::mutex mutex;
|
static std::mutex mutex;
|
||||||
@@ -47,6 +68,8 @@ struct Metric {
|
|||||||
|
|
||||||
static std::unordered_map<std::thread::id, PerThreadState> perThreadState;
|
static std::unordered_map<std::thread::id, PerThreadState> perThreadState;
|
||||||
|
|
||||||
|
static std::unordered_map<MetricKey, Gauge::State> gauges;
|
||||||
|
|
||||||
struct ThreadInit {
|
struct ThreadInit {
|
||||||
ThreadInit() {
|
ThreadInit() {
|
||||||
std::unique_lock<std::mutex> _{mutex};
|
std::unique_lock<std::mutex> _{mutex};
|
||||||
@@ -58,23 +81,88 @@ struct Metric {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
static thread_local ThreadInit thread_init;
|
static thread_local ThreadInit thread_init;
|
||||||
|
|
||||||
|
static Counter
|
||||||
|
create_counter(std::string_view name,
|
||||||
|
std::vector<std::pair<std::string, std::string>> labels) {
|
||||||
|
std::unique_lock<std::mutex> _{mutex};
|
||||||
|
Counter result;
|
||||||
|
result.p = &perThreadState[std::this_thread::get_id()]
|
||||||
|
.counters[MetricKey{name, labels}];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Gauge
|
||||||
|
create_gauge(std::string_view name,
|
||||||
|
std::vector<std::pair<std::string, std::string>> labels) {
|
||||||
|
std::unique_lock<std::mutex> _{mutex};
|
||||||
|
Gauge result;
|
||||||
|
result.p = &gauges[MetricKey{name, labels}];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Histogram
|
||||||
|
create_histogram(std::string_view name,
|
||||||
|
std::vector<std::pair<std::string, std::string>> labels) {
|
||||||
|
std::unique_lock<std::mutex> _{mutex};
|
||||||
|
Histogram result;
|
||||||
|
result.p = &perThreadState[std::this_thread::get_id()]
|
||||||
|
.histograms[MetricKey{name, labels}];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Counter::inc(double x) {}
|
template <class U, class V> U reinterpret(V v) {
|
||||||
void Gauge::inc(double x) {}
|
static_assert(sizeof(U) == sizeof(V));
|
||||||
void Gauge::dec(double x) {}
|
static_assert(std::is_arithmetic_v<U>);
|
||||||
void Gauge::set(double x) {}
|
static_assert(std::is_arithmetic_v<V>);
|
||||||
void Histogram::observe(double x) {}
|
U u;
|
||||||
|
memcpy(&u, &v, sizeof(u));
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Counter::inc(double x) {
|
||||||
|
assert(x >= 0);
|
||||||
|
p->value.fetch_add(x, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
void Gauge::inc(double x) {
|
||||||
|
std::unique_lock<std::mutex> _{p->mutex};
|
||||||
|
p->value += x;
|
||||||
|
}
|
||||||
|
void Gauge::dec(double x) {
|
||||||
|
std::unique_lock<std::mutex> _{p->mutex};
|
||||||
|
p->value -= x;
|
||||||
|
}
|
||||||
|
void Gauge::set(double x) {
|
||||||
|
std::unique_lock<std::mutex> _{p->mutex};
|
||||||
|
p->value = x;
|
||||||
|
}
|
||||||
|
void Histogram::observe(double x) {
|
||||||
|
assert(p->thresholds.size() == p->counts.size());
|
||||||
|
for (size_t i = 0; i < p->thresholds.size(); ++i) {
|
||||||
|
p->counts[i].fetch_add(x <= p->thresholds[i], std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
auto sum = reinterpret<double>(p->sum.load(std::memory_order_relaxed));
|
||||||
|
sum += x;
|
||||||
|
p->sum.store(reinterpret<decltype(p->sum.load())>(sum));
|
||||||
|
p->observations.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
Counter Family<Counter>::create(
|
Counter Family<Counter>::create(
|
||||||
std::initializer_list<std::pair<std::string_view, std::string_view>>) {}
|
std::vector<std::pair<std::string, std::string>> labels) {
|
||||||
|
return Metric::create_counter(name, labels);
|
||||||
|
}
|
||||||
template <>
|
template <>
|
||||||
Gauge Family<Gauge>::create(
|
Gauge Family<Gauge>::create(
|
||||||
std::initializer_list<std::pair<std::string_view, std::string_view>>) {}
|
std::vector<std::pair<std::string, std::string>> labels) {
|
||||||
|
return Metric::create_gauge(name, labels);
|
||||||
|
}
|
||||||
template <>
|
template <>
|
||||||
Histogram Family<Histogram>::create(
|
Histogram Family<Histogram>::create(
|
||||||
std::initializer_list<std::pair<std::string_view, std::string_view>>) {}
|
std::vector<std::pair<std::string, std::string>> labels) {
|
||||||
|
return Metric::create_histogram(name, labels);
|
||||||
|
}
|
||||||
|
|
||||||
Family<Counter> create_counter(std::string_view name, std::string_view help) {}
|
Family<Counter> create_counter(std::string_view name, std::string_view help) {}
|
||||||
Family<Gauge> create_gauge(std::string_view name, std::string_view help) {}
|
Family<Gauge> create_gauge(std::string_view name, std::string_view help) {}
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ private:
|
|||||||
template <class T> struct Family {
|
template <class T> struct Family {
|
||||||
static_assert(std::is_same_v<T, Counter> || std::is_same_v<T, Gauge> ||
|
static_assert(std::is_same_v<T, Counter> || std::is_same_v<T, Gauge> ||
|
||||||
std::is_same_v<T, Histogram>);
|
std::is_same_v<T, Histogram>);
|
||||||
T create(
|
T create(std::vector<std::pair<std::string, std::string>>);
|
||||||
std::initializer_list<std::pair<std::string_view, std::string_view>>);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct Metric;
|
friend struct Metric;
|
||||||
|
|||||||
Reference in New Issue
Block a user