From 580ee5ede725108f5f33c6a60ce605f8acdaeb33 Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Wed, 13 May 2026 14:40:58 +0100 Subject: [PATCH] fix(telemetry): StatsD gauge and io_latency first-sample emit Two fixes so gauges register in Prometheus (via StatsD) even when their initial/steady-state value is 0: 1. StatsDGaugeImpl m_dirty: default-init to true so the initial value (0) is emitted on the first flush. Previously, gauges whose value never changed from 0 were never flushed and never appeared downstream. 2. io_latency_sampler firstSample_: new atomic, init true. m_event.notify now fires when either firstSample_ is true (exchanged to false) or lastSample >= 10 ms. This guarantees the io_latency metric is registered on startup; subsequent sub-10 ms samples are still suppressed to avoid flooding. --- src/libxrpl/beast/insight/StatsDCollector.cpp | 5 ++++- src/xrpld/app/main/Application.cpp | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libxrpl/beast/insight/StatsDCollector.cpp b/src/libxrpl/beast/insight/StatsDCollector.cpp index d11e85830f..6116987447 100644 --- a/src/libxrpl/beast/insight/StatsDCollector.cpp +++ b/src/libxrpl/beast/insight/StatsDCollector.cpp @@ -166,7 +166,7 @@ private: std::string m_name; GaugeImpl::value_type m_last_value{0}; GaugeImpl::value_type m_value{0}; - bool m_dirty{false}; + bool m_dirty{true}; }; //------------------------------------------------------------------------------ @@ -583,6 +583,9 @@ StatsDEventImpl::do_notify(EventImpl::value_type const& value) StatsDGaugeImpl::StatsDGaugeImpl(std::string name, std::shared_ptr const& impl) : m_impl(impl), m_name(std::move(name)) { + // Start dirty so the initial value (0) is emitted on the first flush. + // Without this, gauges whose value never changes from 0 would never + // appear in downstream metric stores (e.g. Prometheus via StatsD). m_impl->add(*this); } diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index 29fb2dd0e9..bb43349eb9 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -149,6 +149,7 @@ private: beast::Journal m_journal; beast::io_latency_probe m_probe; std::atomic lastSample_; + std::atomic firstSample_; public: io_latency_sampler( @@ -156,7 +157,7 @@ private: beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context& ios) - : m_event(std::move(ev)), m_journal(journal), m_probe(interval, ios) + : m_event(std::move(ev)), m_journal(journal), m_probe(interval, ios), firstSample_(true) { } @@ -175,7 +176,10 @@ private: lastSample_ = lastSample; - if (lastSample >= 10ms) + // Always emit the first sample so the metric is registered in + // downstream stores (Prometheus via StatsD). After that, only + // report latency >= 10 ms to avoid flooding with sub-ms values. + if (firstSample_.exchange(false) || lastSample >= 10ms) m_event.notify(lastSample); if (lastSample >= 500ms) {