diff --git a/src/metric.cpp b/src/metric.cpp index 9ca400b..6dfa1b2 100644 --- a/src/metric.cpp +++ b/src/metric.cpp @@ -351,9 +351,6 @@ struct Metric { static_assert(std::is_trivially_destructible_v); static std::mutex mutex; - // Use to invalidate the render plan cache - static uint64_t registration_version; - // Global arena allocator for metric families and persistent global state static ArenaAllocator &get_global_arena() { static auto *global_arena = @@ -746,11 +743,17 @@ struct Metric { ArenaAllocator arena; ArenaVector static_text{&arena}; ArenaVector instructions{&arena}; + uint64_t registration_version; }; + // Use to invalidate the render plan cache + static uint64_t registration_version; + static std::unique_ptr cached_plan; + // Phase 1: Compile phase - generate static text and instructions - static RenderPlan compile_render_plan() { + static std::unique_ptr compile_render_plan() { RenderPlan plan; + plan.registration_version = registration_version; Metric::LabelSets label_sets = Metric::build_label_sets(plan.arena); @@ -890,7 +893,7 @@ struct Metric { // Callback instructions and static text for (const auto &[labels_key, callback] : family->callbacks) { - plan.instructions.push_back(CallCounterCallback{&callback}); + plan.instructions.push_back(CallGaugeCallback{&callback}); plan.static_text.push_back(format( plan.arena, "%.*s\n%.*s%.*s ", static_cast(help_line.size()), help_line.data(), static_cast(name.length()), name.data(), @@ -965,7 +968,7 @@ struct Metric { } } - return plan; + return std::make_unique(std::move(plan)); } // Phase 2: Execute phase - run instructions and generate dynamic text @@ -1540,15 +1543,18 @@ std::span render(ArenaAllocator &arena) { std::unique_lock _{Metric::mutex}; // Phase 1: Compile - generate static text and instructions - Metric::RenderPlan plan = Metric::compile_render_plan(); + if (!Metric::cached_plan || Metric::cached_plan->registration_version != + Metric::registration_version) { + Metric::cached_plan = Metric::compile_render_plan(); + } // Phase 2: Execute - run instructions and generate dynamic text ArenaVector dynamic_text = - Metric::execute_render_plan(arena, plan.instructions); + Metric::execute_render_plan(arena, Metric::cached_plan->instructions); // Phase 3: Present - interleave static and dynamic text - ArenaVector output = - Metric::present_render_output(arena, plan.static_text, dynamic_text); + ArenaVector output = Metric::present_render_output( + arena, Metric::cached_plan->static_text, dynamic_text); return output; } @@ -1607,6 +1613,7 @@ void Family::register_callback( // Static member definitions std::mutex Metric::mutex; uint64_t Metric::registration_version; +std::unique_ptr Metric::cached_plan; thread_local Metric::ThreadInit Metric::thread_init; void reset_metrics_for_testing() {