mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-22 23:00:55 +00:00
docs(telemetry): align runbook and plan docs with the shipped phase-9/10 code
The reference docs had drifted from the code in ways that break the reader rather than merely misinform: PromQL examples that return no data, a rollback flag that is a no-op, a sampling knob that does not exist, and two span parents that moved. Code is treated as the truth throughout; where the code is the defective side, the doc now records it as a known issue instead of describing the bug as intent. Renames the docs missed: histogram names gain the exporter's unit suffix (ios_latency_milliseconds_bucket and four siblings), ledger_history_mismatch gains _total, the StatsD-era quantile label gives way to le buckets, rpc.request becomes rpc.http_request, traces_spanmetrics_calls_total becomes span_calls_total, and the nine dotted xrpl.* span attributes are recorded as renamed rather than left as live keys. Re-parenting: consensus.update_positions and consensus.check are children of consensus.establish, not of consensus.round. Units and labels: state_accounting_*_duration is microseconds, not seconds; cache_metrics label values are case-sensitive; object_count carries demangled C++ type names. Nodestore read and write latency stays microseconds -- the nanosecond accumulator change did not move the exported unit. Adds what shipped but was undocumented: the ledger.acquire span, seven consensus.round events, twelve span attributes, node_writes_duration_us, the 7-day validation-agreement window, the TxQ admission and reduce-relay metric families, metrics_endpoint, and the phase-10 validation workflow. Corrects claims that never held: 10% head sampling (it is fixed at 100%), configurable redaction (it is unconditional), -DXRPL_ENABLE_TELEMETRY=OFF (the flag is -Dtelemetry=OFF, default ON), FindOpenTelemetry.cmake and the xrpl_telemetry target (neither exists), Promtail and a StatsD exporter in the pipeline (neither exists), and Loki stream selection on job= (only service_name is a stream label). Phase 9 is marked complete, its provisioned alerting is attributed to the branch that shipped it, and Phase 11 stays at zero except the one prerequisite its code closes. Counts are reconciled repo-wide: 41 emitted span families, 15 dashboards on disk with 14 asserted, 13 alert rules in 5 groups. Hardens the gate that let this drift through: Rule E of the naming check now covers the reference docs, its allow-dotted marker is key-scoped and warns on stale or empty use, a missing checked file is reported instead of silently skipped, the test suite runs in CI, and doc paths trigger the check. C++ and CMake changes are comment-only: three MetricsRegistry instrument names, eight OTelCollector claims of a metric-name prefix that formatName never adds, and the telemetry option's inverted default.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* Compiled only when XRPL_ENABLE_TELEMETRY is defined (via CMake
|
||||
* telemetry=ON). Maps beast::insight instruments to OTel SDK instruments
|
||||
* created on the GLOBAL Meter published by the telemetry module. This class
|
||||
* is a legacy shim: it no longer owns an export pipeline. The MeterProvider,
|
||||
* is an adapter only: it owns no export pipeline. The MeterProvider,
|
||||
* PeriodicExportingMetricReader, OTLP exporter and histogram view all live in
|
||||
* xrpl::telemetry::Telemetry.
|
||||
*
|
||||
@@ -134,8 +134,8 @@ class OTelCounterImpl : public CounterImpl
|
||||
public:
|
||||
/**
|
||||
* @param name Export-ready metric name, already run through
|
||||
* formatName() by the collector: prefix prepended and
|
||||
* dots replaced with underscores (e.g. "rpc_size").
|
||||
* formatName() by the collector: lowercase, with `.` and
|
||||
* ` ` mapped to `_` (e.g. "rpc_size").
|
||||
* @param meter OTel Meter used to create the counter instrument.
|
||||
*/
|
||||
OTelCounterImpl(
|
||||
@@ -178,8 +178,8 @@ class OTelEventImpl : public EventImpl
|
||||
public:
|
||||
/**
|
||||
* @param name Export-ready metric name, already run through
|
||||
* formatName() by the collector: prefix prepended and
|
||||
* dots replaced with underscores (e.g. "rpc_size").
|
||||
* formatName() by the collector: lowercase, with `.` and
|
||||
* ` ` mapped to `_` (e.g. "rpc_size").
|
||||
* @param meter OTel Meter used to create the histogram instrument.
|
||||
*/
|
||||
OTelEventImpl(
|
||||
@@ -227,8 +227,8 @@ class OTelGaugeImpl : public GaugeImpl
|
||||
public:
|
||||
/**
|
||||
* @param name Export-ready metric name, already run through
|
||||
* formatName() by the collector: prefix prepended
|
||||
* and dots replaced with underscores.
|
||||
* formatName() by the collector: lowercase, with `.`
|
||||
* and ` ` mapped to `_`.
|
||||
* @param meter OTel Meter used to create the observable gauge.
|
||||
* @param collector Owning collector, used to invoke hooks before reads.
|
||||
*/
|
||||
@@ -310,8 +310,8 @@ class OTelMeterImpl : public MeterImpl
|
||||
public:
|
||||
/**
|
||||
* @param name Export-ready metric name, already run through
|
||||
* formatName() by the collector: prefix prepended and
|
||||
* dots replaced with underscores (e.g. "rpc_size").
|
||||
* formatName() by the collector: lowercase, with `.` and
|
||||
* ` ` mapped to `_` (e.g. "rpc_size").
|
||||
* @param meter OTel Meter used to create the counter instrument.
|
||||
*/
|
||||
OTelMeterImpl(
|
||||
@@ -340,7 +340,7 @@ private:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Main OTel Collector implementation (legacy shim).
|
||||
* @brief Main OTel Collector implementation (adapter over the global Meter).
|
||||
*
|
||||
* Obtains its Meter from the GLOBAL MeterProvider owned and published by the
|
||||
* telemetry module (xrpl::telemetry::Telemetry), rather than building its own
|
||||
@@ -380,8 +380,11 @@ private:
|
||||
* Caveats:
|
||||
* - Observable gauge callbacks run on the SDK's internal thread. Hook
|
||||
* handlers must be thread-safe.
|
||||
* - Metric names are formed as "prefix_name" with dots replaced by
|
||||
* underscores to match StatsD->Prometheus naming conventions.
|
||||
* - Metric names carry NO prefix. formatName() only lowercases the raw
|
||||
* name and turns dots and spaces into underscores, to match
|
||||
* StatsD->Prometheus naming conventions. The service is identified by
|
||||
* the OTel resource (service.name), so prefix_ is kept for logging
|
||||
* only and never affects an exported name.
|
||||
* - The OTel Prometheus exporter appends "_total" to counters. The
|
||||
* metric names we register do NOT include this suffix — Prometheus
|
||||
* adds it automatically.
|
||||
@@ -402,11 +405,14 @@ public:
|
||||
/**
|
||||
* @brief Construct the OTel collector over the global MeterProvider.
|
||||
*
|
||||
* @param endpoint OTLP/HTTP metrics endpoint URL. Informational only:
|
||||
* the global telemetry pipeline is authoritative for
|
||||
* the actual export endpoint. Retained for logging and
|
||||
* back-compat with the New() signature.
|
||||
* @param prefix Prefix for all metric names.
|
||||
* @param endpoint OTLP/HTTP metrics endpoint URL, recorded in the
|
||||
* collector's startup log line. Export uses the
|
||||
* endpoint configured on the global telemetry
|
||||
* pipeline.
|
||||
* @param prefix Label for the collector's startup log line
|
||||
* (e.g. "xrpld"). Exported metric names come from
|
||||
* formatName(); the service is identified by the
|
||||
* service.name resource attribute.
|
||||
* @param instanceId Value for the service.instance.id resource attribute.
|
||||
* When empty, the attribute is omitted.
|
||||
* @param serviceName Value for the service.name resource attribute.
|
||||
@@ -498,10 +504,12 @@ public:
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Format a metric name with the configured prefix.
|
||||
* @brief Format a raw metric name for export.
|
||||
*
|
||||
* Replaces dots with underscores to match StatsD->Prometheus naming.
|
||||
* Example: prefix="xrpld", name="LedgerMaster.Validated_Ledger_Age"
|
||||
* Lowercases the name and replaces dots and spaces with underscores to
|
||||
* match StatsD->Prometheus naming. Adds NO prefix: the service is
|
||||
* identified by the OTel resource (service.name).
|
||||
* Example: name="LedgerMaster.Validated_Ledger_Age"
|
||||
* -> "ledgermaster_validated_ledger_age"
|
||||
*
|
||||
* @param name Raw metric name from beast::insight callers.
|
||||
@@ -517,7 +525,8 @@ private:
|
||||
Journal journal_;
|
||||
|
||||
/**
|
||||
* Prefix for all metric names (e.g., "xrpld").
|
||||
* Configured metric-name prefix (e.g., "xrpld"). Log-only: it is
|
||||
* echoed in the startup log line and never applied to a metric name.
|
||||
*/
|
||||
std::string prefix_;
|
||||
|
||||
@@ -708,17 +717,17 @@ OTelCollectorImp::OTelCollectorImp(
|
||||
Journal journal)
|
||||
: journal_(journal), prefix_(std::move(prefix))
|
||||
{
|
||||
// instanceId/serviceName/networkType are retained on the New() signature
|
||||
// for back-compat but no longer used here: the telemetry module owns the
|
||||
// resource attributes for the shared metrics pipeline.
|
||||
// instanceId/serviceName/networkType are accepted but unused here: the
|
||||
// telemetry module owns the resource attributes for the shared metrics
|
||||
// pipeline, so setting them from this collector would have no effect.
|
||||
(void)instanceId;
|
||||
(void)serviceName;
|
||||
(void)networkType;
|
||||
|
||||
if (journal_.info())
|
||||
{
|
||||
// endpoint is informational: the global telemetry pipeline owns the
|
||||
// real exporter. It is logged here for back-compat and diagnostics.
|
||||
// endpoint is logged for diagnostics only: the global telemetry
|
||||
// pipeline owns the exporter that actually sends the metrics.
|
||||
journal_.info() << "OTelCollector starting: endpoint=" << endpoint << " prefix=" << prefix_;
|
||||
}
|
||||
|
||||
@@ -846,9 +855,9 @@ OTelCollectorImp::removeGauge(OTelGaugeImpl* gauge)
|
||||
std::string
|
||||
OTelCollectorImp::formatName(std::string const& name)
|
||||
{
|
||||
// Produce a clean, lowercase, Prometheus-compatible metric name.
|
||||
// No prefix — the OTel resource (service.name) identifies the service.
|
||||
// Dots and spaces become underscores; everything lowercased.
|
||||
// Produce a lowercase, Prometheus-compatible metric name: dots and
|
||||
// spaces become underscores. Service identity travels in the
|
||||
// service.name resource attribute, not in the metric name.
|
||||
std::string result;
|
||||
result.reserve(name.size());
|
||||
for (char const c : name)
|
||||
|
||||
@@ -786,7 +786,7 @@ private:
|
||||
*/
|
||||
opentelemetry::nostd::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> rpcErroredCounter_;
|
||||
/**
|
||||
* Histogram: rpc_method_duration_us{method="<name>"}
|
||||
* Histogram: rpc_method_us{method="<name>"}
|
||||
*/
|
||||
opentelemetry::nostd::unique_ptr<opentelemetry::metrics::Histogram<double>>
|
||||
rpcDurationHistogram_;
|
||||
@@ -807,12 +807,12 @@ private:
|
||||
*/
|
||||
opentelemetry::nostd::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> jobFinishedCounter_;
|
||||
/**
|
||||
* Histogram: job_queued_duration_us{job_type="<name>",handler="<name>"}
|
||||
* Histogram: job_queued_us{job_type="<name>",handler="<name>"}
|
||||
*/
|
||||
opentelemetry::nostd::unique_ptr<opentelemetry::metrics::Histogram<double>>
|
||||
jobQueuedDurationHistogram_;
|
||||
/**
|
||||
* Histogram: job_running_duration_us{job_type="<name>",handler="<name>"}
|
||||
* Histogram: job_running_us{job_type="<name>",handler="<name>"}
|
||||
*/
|
||||
opentelemetry::nostd::unique_ptr<opentelemetry::metrics::Histogram<double>>
|
||||
jobRunningDurationHistogram_;
|
||||
|
||||
Reference in New Issue
Block a user