More scaffolding

This commit is contained in:
2025-08-28 17:32:34 -04:00
parent ca5b299da8
commit d0f2b6550a
2 changed files with 100 additions and 13 deletions

View File

@@ -1,9 +1,15 @@
#include "metric.hpp"
#include <atomic>
#include <cassert>
#include <cstdint>
#include <mutex>
#include <string_view>
#include <thread>
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace metric {
struct MetricKey {
std::string_view name;
@@ -33,9 +39,24 @@ template <> struct hash<metric::MetricKey> {
namespace metric {
struct Counter::State {};
struct Gauge::State {};
struct Histogram::State {};
using AtomicWord = std::atomic<uint64_t>;
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 {
static std::mutex mutex;
@@ -47,6 +68,8 @@ struct Metric {
static std::unordered_map<std::thread::id, PerThreadState> perThreadState;
static std::unordered_map<MetricKey, Gauge::State> gauges;
struct ThreadInit {
ThreadInit() {
std::unique_lock<std::mutex> _{mutex};
@@ -58,23 +81,88 @@ struct Metric {
}
};
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) {}
void Gauge::inc(double x) {}
void Gauge::dec(double x) {}
void Gauge::set(double x) {}
void Histogram::observe(double x) {}
template <class U, class V> U reinterpret(V v) {
static_assert(sizeof(U) == sizeof(V));
static_assert(std::is_arithmetic_v<U>);
static_assert(std::is_arithmetic_v<V>);
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 <>
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 <>
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 <>
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<Gauge> create_gauge(std::string_view name, std::string_view help) {}

View File

@@ -45,8 +45,7 @@ private:
template <class T> struct Family {
static_assert(std::is_same_v<T, Counter> || std::is_same_v<T, Gauge> ||
std::is_same_v<T, Histogram>);
T create(
std::initializer_list<std::pair<std::string_view, std::string_view>>);
T create(std::vector<std::pair<std::string, std::string>>);
private:
friend struct Metric;