Fix static initialization order fiasco
This commit is contained in:
@@ -23,8 +23,6 @@
|
||||
|
||||
#include "format.hpp"
|
||||
|
||||
// TODO fix static initialization order fiasco
|
||||
|
||||
// Verify that malloc provides sufficient alignment for atomic 128-bit
|
||||
// operations
|
||||
static_assert(__STDCPP_DEFAULT_NEW_ALIGNMENT__ >= 16,
|
||||
@@ -193,15 +191,27 @@ struct Histogram::State {
|
||||
struct Metric {
|
||||
static std::mutex mutex;
|
||||
|
||||
// Two-level map: name -> Family
|
||||
static std::unordered_map<std::string,
|
||||
std::unique_ptr<Family<Counter>::State>>
|
||||
counterFamilies;
|
||||
static std::unordered_map<std::string, std::unique_ptr<Family<Gauge>::State>>
|
||||
gaugeFamilies;
|
||||
static std::unordered_map<std::string,
|
||||
std::unique_ptr<Family<Histogram>::State>>
|
||||
histogramFamilies;
|
||||
// Function-local statics to avoid static initialization order fiasco
|
||||
static auto &get_counter_families() {
|
||||
static std::unordered_map<std::string,
|
||||
std::unique_ptr<Family<Counter>::State>>
|
||||
counterFamilies;
|
||||
return counterFamilies;
|
||||
}
|
||||
|
||||
static auto &get_gauge_families() {
|
||||
static std::unordered_map<std::string,
|
||||
std::unique_ptr<Family<Gauge>::State>>
|
||||
gaugeFamilies;
|
||||
return gaugeFamilies;
|
||||
}
|
||||
|
||||
static auto &get_histogram_families() {
|
||||
static std::unordered_map<std::string,
|
||||
std::unique_ptr<Family<Histogram>::State>>
|
||||
histogramFamilies;
|
||||
return histogramFamilies;
|
||||
}
|
||||
|
||||
// Thread cleanup for per-family thread-local storage
|
||||
struct ThreadInit {
|
||||
@@ -214,7 +224,7 @@ struct Metric {
|
||||
auto thread_id = std::this_thread::get_id();
|
||||
|
||||
// Accumulate counter families
|
||||
for (auto &[name, family] : counterFamilies) {
|
||||
for (auto &[name, family] : Metric::get_counter_families()) {
|
||||
auto thread_it = family->perThreadState.find(thread_id);
|
||||
if (thread_it != family->perThreadState.end()) {
|
||||
for (auto &[labels_key, instance] : thread_it->second.instances) {
|
||||
@@ -236,7 +246,7 @@ struct Metric {
|
||||
}
|
||||
|
||||
// Accumulate histogram families
|
||||
for (auto &[name, family] : histogramFamilies) {
|
||||
for (auto &[name, family] : Metric::get_histogram_families()) {
|
||||
auto thread_it = family->perThreadState.find(thread_id);
|
||||
if (thread_it != family->perThreadState.end()) {
|
||||
for (auto &[labels_key, instance] : thread_it->second.instances) {
|
||||
@@ -490,7 +500,7 @@ Family<Counter> create_counter(std::string name, std::string help) {
|
||||
name.c_str());
|
||||
|
||||
std::unique_lock<std::mutex> _{Metric::mutex};
|
||||
auto &familyPtr = Metric::counterFamilies[name];
|
||||
auto &familyPtr = Metric::get_counter_families()[name];
|
||||
if (!familyPtr) {
|
||||
familyPtr = std::make_unique<Family<Counter>::State>();
|
||||
familyPtr->name = std::move(name);
|
||||
@@ -511,7 +521,7 @@ Family<Gauge> create_gauge(std::string name, std::string help) {
|
||||
name.c_str());
|
||||
|
||||
std::unique_lock<std::mutex> _{Metric::mutex};
|
||||
auto &familyPtr = Metric::gaugeFamilies[name];
|
||||
auto &familyPtr = Metric::get_gauge_families()[name];
|
||||
if (!familyPtr) {
|
||||
familyPtr = std::make_unique<Family<Gauge>::State>();
|
||||
familyPtr->name = std::move(name);
|
||||
@@ -533,7 +543,7 @@ Family<Histogram> create_histogram(std::string name, std::string help,
|
||||
name.c_str());
|
||||
|
||||
std::unique_lock<std::mutex> _{Metric::mutex};
|
||||
auto &familyPtr = Metric::histogramFamilies[name];
|
||||
auto &familyPtr = Metric::get_histogram_families()[name];
|
||||
if (!familyPtr) {
|
||||
familyPtr = std::make_unique<Family<Histogram>::State>();
|
||||
familyPtr->name = std::move(name);
|
||||
@@ -724,7 +734,7 @@ std::span<std::string_view> render(ArenaAllocator &arena) {
|
||||
};
|
||||
|
||||
// Render counters
|
||||
for (const auto &[name, family] : Metric::counterFamilies) {
|
||||
for (const auto &[name, family] : Metric::get_counter_families()) {
|
||||
output.push_back(
|
||||
format(arena, "# HELP %s %s\n", name.c_str(), family->help.c_str()));
|
||||
output.push_back(format(arena, "# TYPE %s counter\n", name.c_str()));
|
||||
@@ -777,7 +787,7 @@ std::span<std::string_view> render(ArenaAllocator &arena) {
|
||||
}
|
||||
|
||||
// Render gauges
|
||||
for (const auto &[name, family] : Metric::gaugeFamilies) {
|
||||
for (const auto &[name, family] : Metric::get_gauge_families()) {
|
||||
output.push_back(
|
||||
format(arena, "# HELP %s %s\n", name.c_str(), family->help.c_str()));
|
||||
output.push_back(format(arena, "# TYPE %s gauge\n", name.c_str()));
|
||||
@@ -810,7 +820,7 @@ std::span<std::string_view> render(ArenaAllocator &arena) {
|
||||
}
|
||||
|
||||
// Render histograms
|
||||
for (const auto &[name, family] : Metric::histogramFamilies) {
|
||||
for (const auto &[name, family] : Metric::get_histogram_families()) {
|
||||
output.push_back(
|
||||
format(arena, "# HELP %s %s\n", name.c_str(), family->help.c_str()));
|
||||
output.push_back(format(arena, "# TYPE %s histogram\n", name.c_str()));
|
||||
@@ -995,12 +1005,6 @@ void Family<Gauge>::register_callback(
|
||||
|
||||
// Static member definitions
|
||||
std::mutex Metric::mutex;
|
||||
std::unordered_map<std::string, std::unique_ptr<Family<Counter>::State>>
|
||||
Metric::counterFamilies;
|
||||
std::unordered_map<std::string, std::unique_ptr<Family<Gauge>::State>>
|
||||
Metric::gaugeFamilies;
|
||||
std::unordered_map<std::string, std::unique_ptr<Family<Histogram>::State>>
|
||||
Metric::histogramFamilies;
|
||||
thread_local Metric::ThreadInit Metric::thread_init;
|
||||
|
||||
} // namespace metric
|
||||
|
||||
Reference in New Issue
Block a user