From b6809d87004d9606a26d146bfca8b67be33573a7 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Sun, 31 Aug 2025 14:20:29 -0400 Subject: [PATCH] Add arena usage documentation --- src/metric.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/metric.cpp b/src/metric.cpp index 4920e1a..dc8be70 100644 --- a/src/metric.cpp +++ b/src/metric.cpp @@ -55,6 +55,61 @@ namespace metric { +// ARENA OWNERSHIP AND MEMORY MANAGEMENT DOCUMENTATION +// +// The metrics system uses multiple arena allocators with distinct ownership +// patterns: +// +// 1. GLOBAL ARENA (get_global_arena()): +// - Lifetime: Application lifetime (never destroyed) +// - Purpose: Persistent storage for metric families, interned labels, and +// global state +// - Owner: Static storage - automatically managed +// - Content: Family names, help text, LabelsKey instances, global +// accumulated values +// +// 2. THREAD-LOCAL ARENA (get_thread_local_arena()): +// - Lifetime: Per-thread lifetime (destroyed on thread exit) +// - Purpose: Storage for per-thread metric instances (Counter::State, +// Histogram::State) +// - Owner: thread_local ThreadInit instance +// - Content: Thread-specific metric instance state +// +// 3. TEMPORARY ARENAS: +// a) Caller-Provided Arenas (ArenaAllocator& parameters): +// - Lifetime: Controlled by caller (function parameter) +// - Purpose: Output formatting where caller controls result lifetime +// - Owner: Caller owns arena and controls string lifetime +// - Example: render(ArenaAllocator& arena) - caller manages arena +// lifecycle +// +// b) Stack-Owned Temporary Arenas: +// - Lifetime: Function/scope lifetime (automatic destruction) +// - Purpose: Internal temporary allocations for lookups and processing +// - Owner: Function owns arena on stack, destroyed at scope exit +// - Example: intern_labels() creates ArenaAllocator lookup_arena(1024) +// +// CRITICAL OWNERSHIP RULES: +// +// - LabelsKey Arena Dependency: LabelsKey instances store string_views pointing +// to arena-allocated memory. The arena MUST outlive any LabelsKey that +// references its memory. LabelsKey constructor copies input strings into the +// provided arena. +// +// - Render Function: render(arena) allocates ALL output strings in the provided +// arena. Callers own the arena and control string lifetime. String_views +// become invalid after arena.reset() or arena destruction. +// +// - Thread Cleanup: ThreadInit destructor accumulates thread-local +// counter/histogram +// values into global storage before thread exit. This copies VALUES (not +// ownership) to prevent metric data loss when threads are destroyed. +// +// - Family Creation: Uses placement new in global arena without explicit +// destructors. +// This is acceptable because Family::State instances persist for application +// lifetime and the global arena is never destroyed. + // Validation helper that works in both debug and release builds static void validate_or_abort(bool condition, const char *message, std::string_view value) {