Overview
High-performance, header-only C++23 Prometheus client library optimized for metric update throughput. Values stored as int64_t atomics (LOCK XADD on x86) — not double (CAS loop). Doubles produced only at scrape time.
See ARCHITECTURE.md for full design.
Implementation Phases
Phase 1: Core Primitives
Phase 2: Label System
Phase 3: Histogram
Phase 4: Storage & Metric Family
Phase 5: Registry & Exposition
Phase 6: Examples & Polish
Key Design Decisions
| Decision |
Choice |
Why |
| Value type |
int64_t |
LOCK XADD (1 instruction) vs double CAS loop |
| Memory ordering |
relaxed everywhere |
Prometheus scraping is best-effort; no cross-metric ordering needed |
| Label keys |
enum class (power-of-two) |
Bitmask operations for required/optional/forbidden checks |
| Label values |
std::optional in aggregate |
C++20 designated initializers: {.service = "api", .method = "GET"} |
| Histogram observe |
Single fetch_add per call |
Cumulative sums computed at scrape time (off hot path) |
| Metric lookup |
shared_mutex + unordered_map |
Contention only on first-seen label combo; cached handles bypass map entirely |
| Build |
Header-only, CMake |
Zero dependencies at runtime; GoogleTest for tests only |
Non-Goals (for v0.1)
- No built-in HTTP server (bring your own)
- No push gateway support
- No Summary metric type (rarely needed; histograms preferred)
- No OpenMetrics format (Prometheus text format only)
- No dynamic label registration (labels are fixed at compile time per app)
Overview
High-performance, header-only C++23 Prometheus client library optimized for metric update throughput. Values stored as
int64_tatomics (LOCK XADDon x86) — notdouble(CAS loop). Doubles produced only at scrape time.See ARCHITECTURE.md for full design.
Implementation Phases
Phase 1: Core Primitives
include/prometheus/detail/assert.hpp—PROMETHEUS_ASSERTmacro (debug vs release)include/prometheus/counter.hpp—Counterclass (atomic<int64_t>,inc(),load(),to_double())include/prometheus/gauge.hpp—Gaugeclass (set(),inc(),dec(),load())tests/test_counter.cpp— unit tests incl. concurrent stress testtests/test_gauge.cpp— unit tests incl. concurrent stress testPhase 2: Label System
include/prometheus/label_mask.hpp—LabelMask<T>alias,make_mask()consteval helperinclude/prometheus/label_def.hpp—PROMETHEUS_DEFINE_LABELSmacro generating:Keyenum (power-of-two values)LabelSetstruct withstd::optionalfieldskey_name(),populated_mask(),format_value(),all_keys()constexpr functionstests/test_label_def.cpp— macro expansion, mask arithmetic, key name mappingPhase 3: Histogram
include/prometheus/histogram.hpp—Histogramclass templateobserve()— binary search + singlefetch_addtests/test_histogram.cpp— bucket assignment, sum, count, edge casesPhase 4: Storage & Metric Family
include/prometheus/detail/label_key.hpp— canonical key string fromLabelSet+ allowed maskinclude/prometheus/detail/metric_store.hpp—shared_mutex+unordered_map<string, unique_ptr<MetricT>>include/prometheus/metric_family.hpp—MetricFamily<LabelTraits, MetricT>withget()returning stable referencesinclude/prometheus/metric_family_builder.hpp— fluent builder withrequired(),optional(),const_label(),buckets(),build()tests/test_metric_family.cpp— builder API, required/optional/forbidden label validation, handle stabilityPhase 5: Registry & Exposition
include/prometheus/text_serializer.hpp— Prometheus text format 0.0.4 writerinclude/prometheus/registry.hpp—Registrywithcounter<T>(),gauge<T>(),histogram<T>()entry points,serialize()include/prometheus/prometheus.hpp— convenience all-in-one includetests/test_text_serializer.cpp— format correctness (counter, gauge, histogram, const labels, scale)tests/test_registry.cpp— end-to-end registration + serializationPhase 6: Examples & Polish
examples/basic_usage.cpp— minimal working exampleexamples/http_server_example.cpp— with cpp-httplib integration.clang-formatand.clang-tidyconfigsKey Design Decisions
int64_tLOCK XADD(1 instruction) vsdoubleCAS looprelaxedeverywhereenum class(power-of-two)std::optionalin aggregate{.service = "api", .method = "GET"}fetch_addper callshared_mutex+unordered_mapNon-Goals (for v0.1)