diff --git a/docker/telemetry/grafana/dashboards/xrpld-fee-market.json b/docker/telemetry/grafana/dashboards/xrpld-fee-market.json index 7863725185..9e1ae6b26e 100644 --- a/docker/telemetry/grafana/dashboards/xrpld-fee-market.json +++ b/docker/telemetry/grafana/dashboards/xrpld-fee-market.json @@ -2,7 +2,7 @@ "annotations": { "list": [] }, - "description": "Fee market dynamics: TxQ depth/capacity, fee escalation levels, and load factor breakdown. Sourced from OTel MetricsRegistry observable gauges (Phase 9).", + "description": "Transaction queue depth and capacity, fee-escalation levels, and load-factor breakdown that together set the minimum fee to enter the open ledger.", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, @@ -11,7 +11,7 @@ "panels": [ { "title": "Transaction Queue Depth", - "description": "Current number of transactions waiting in the queue vs. maximum capacity. Sourced from MetricsRegistry txq_metrics observable gauge with metric=txq_count and metric=txq_max_size.", + "description": "**What:** Transactions currently waiting in the transaction queue versus the queue's maximum capacity.\n**How it's computed:** Instantaneous gauge readings of current queue count and configured max size.\n**Reading it:** Queue depth well below capacity is normal; depth approaching capacity means the node is saturating.\n**Healthy range:** Depth near 0 in quiet periods; workload-dependent under load.\n**Watch for:** Depth pinned at capacity for sustained periods, which signals demand exceeding throughput or a fee-spam burst.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerTxqGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -59,7 +59,7 @@ }, { "title": "Transactions Per Ledger", - "description": "Transactions in the current open ledger vs. expected per-ledger count. Sourced from txq_metrics with metric=txq_in_ledger and metric=txq_per_ledger.", + "description": "**What:** Transactions already placed in the current open ledger versus the expected per-ledger target.\n**How it's computed:** Instantaneous gauge readings of in-ledger count and the target count that governs fee escalation.\n**Reading it:** Staying at or below the expected target is normal; exceeding it triggers open-ledger fee escalation.\n**Healthy range:** At or under the expected per-ledger target.\n**Watch for:** In-ledger count persistently above target, indicating sustained congestion pushing fees up.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerTxqGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -107,7 +107,7 @@ }, { "title": "Fee Escalation Levels", - "description": "Fee levels that control transaction queue admission. Reference fee level is the baseline; open ledger fee level triggers escalation. Sourced from txq_metrics observable gauge.", + "description": "**What:** The fee levels that govern queue admission: reference (baseline), minimum processing, median, and open-ledger levels.\n**How it's computed:** Instantaneous gauge readings of each fee level, shown on a log scale.\n**Reading it:** Open-ledger level near the reference level means cheap entry; a large gap above reference means escalation is active.\n**Healthy range:** Open-ledger level at or near reference during normal traffic.\n**Watch for:** Open-ledger level spiking far above reference, the hallmark of congestion or a fee-bidding war.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerTxqGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -173,7 +173,7 @@ }, { "title": "Load Factor Breakdown", - "description": "Decomposed load factor components: server (max of local, net, cluster), fee escalation, fee queue, and combined. Values are unitless multipliers where 1.0 = no load. Sourced from load_factor_metrics observable gauge.", + "description": "**What:** The combined load factor and its server, fee-escalation, and fee-queue contributors as unitless fee multipliers (1.0 = no load).\n**How it's computed:** Instantaneous gauge readings of each load-factor component.\n**Reading it:** Values at 1.0 mean base fees; higher values raise the fee to transact.\n**Healthy range:** Around 1.0 under normal conditions.\n**Watch for:** Combined factor climbing well above 1.0, showing the node is charging premium fees due to congestion or overload.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerLoadFactorGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -251,7 +251,7 @@ }, { "title": "Load Factor Components", - "description": "Individual load factor contributors: local server load, network load, and cluster load. Only differ from 1.0 under load conditions. Sourced from load_factor_metrics observable gauge.", + "description": "**What:** The individual load-factor inputs, local server load, network load, and cluster load, as unitless multipliers.\n**How it's computed:** Instantaneous gauge readings of each component.\n**Reading it:** All at 1.0 means no load pressure from any source; a raised component identifies where load originates.\n**Healthy range:** Around 1.0 for each component.\n**Watch for:** A single component rising sharply, which pinpoints whether the pressure is local, network-wide, or cluster-driven.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerLoadFactorGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -306,7 +306,7 @@ }, { "title": "Load Factor Attribution (Stacked Components)", - "description": "Stacked contribution of each load-factor component (fee escalation, queue, local, net, cluster) to the effective transaction cost. Shows WHICH component is driving the fee at any moment, which the aggregate load_factor hides.", + "description": "**What:** The stacked contribution of each load-factor component (fee escalation, queue, local, net, cluster) to the effective transaction cost.\n**How it's computed:** Instantaneous gauge readings of each component stacked to show relative share.\n**Reading it:** The tallest band identifies which component is driving the fee, detail the aggregate load factor hides.\n**Healthy range:** Thin bands near 1.0 total under normal traffic.\n**Watch for:** One band dominating during a fee spike, revealing the specific driver of elevated cost.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerLoadFactorGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -378,7 +378,7 @@ }, { "title": "Queue Abandonment Rate (Expired)", - "description": "Rate of transactions expired out of the queue (LastLedgerSequence passed). Rising expiry means submitters under-bid the escalating fee and gave up \u2014 a demand-frustration signal.", + "description": "**What:** Transactions dropped from the queue because their last-ledger deadline passed before they could be included.\n**How it's computed:** Per-second rate of the cumulative expired-transaction counter over a 5-minute window.\n**Reading it:** Near zero is healthy; a rising rate means submitters under-bid the escalating fee and their transactions timed out.\n**Healthy range:** Near 0 expirations per second.\n**Watch for:** Sustained expiry rate, a demand-frustration signal often coinciding with fee spikes or spam that crowds out honest traffic.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:incrementTxqExpired (caller src/xrpld/app/misc/detail/TxQ.cpp)", "type": "timeseries", "gridPos": { "h": 8, @@ -417,7 +417,7 @@ }, { "title": "Queue Admission Rejections (Dropped)", - "description": "Rate of transactions refused admission to the queue, by reason. queue_full means the queue is at capacity \u2014 admission-control backpressure distinct from expiry and from job-queue overflow.", + "description": "**What:** Transactions refused entry to the queue, broken down by reason such as queue_full.\n**How it's computed:** Per-second rate of the cumulative dropped-transaction counter over a 5-minute window, split by reason.\n**Reading it:** Near zero is healthy; queue_full rejections mean the queue is at capacity and applying backpressure.\n**Healthy range:** Near 0 rejections per second.\n**Watch for:** A burst of queue_full drops, distinct from expiry, indicating the node is being flooded faster than it can drain.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:incrementTxqDropped (caller src/xrpld/app/misc/detail/TxQ.cpp)", "type": "timeseries", "gridPos": { "h": 8, @@ -456,7 +456,7 @@ } ], "schemaVersion": 39, - "tags": ["fee-market"], + "tags": ["transactions", "fees"], "templating": { "list": [ { diff --git a/docker/telemetry/grafana/dashboards/xrpld-job-queue.json b/docker/telemetry/grafana/dashboards/xrpld-job-queue.json index e3027ebc8b..5f07d326b9 100644 --- a/docker/telemetry/grafana/dashboards/xrpld-job-queue.json +++ b/docker/telemetry/grafana/dashboards/xrpld-job-queue.json @@ -2,7 +2,7 @@ "annotations": { "list": [] }, - "description": "Job queue analysis: per-job-type throughput rates, queue wait times, and execution times. Sourced from OTel MetricsRegistry synchronous counters and histograms (Phase 9).", + "description": "Per-job-type throughput, queue wait times, and execution times for the node's internal worker job queue.", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, @@ -11,7 +11,7 @@ "panels": [ { "title": "Current Job Latency (p99 Gauge)", - "description": "At-a-glance p99 job queue wait and execution time over the last 5 minutes. Green < 100ms, yellow 100ms-1s, red > 1s.", + "description": "**What:** At-a-glance p99 of how long jobs wait in the queue and how long they run once started.\n**How it's computed:** 99th percentile derived from the job wait-time and run-time histograms over the last 5 minutes.\n**Reading it:** Lower is better; green under 100ms, yellow to 1s, red beyond 1s.\n**Healthy range:** Wait and exec p99 under 100ms.\n**Watch for:** p99 wait climbing into the red, meaning worker threads are saturated and jobs are backing up.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:recordJobStarted / recordJobFinished", "type": "gauge", "gridPos": { "h": 8, @@ -47,7 +47,7 @@ ], "fieldConfig": { "defaults": { - "unit": "\u00b5s", + "unit": "µs", "min": 0, "thresholds": { "mode": "absolute", @@ -73,7 +73,7 @@ }, { "title": "Job Throughput Rate (Per Second)", - "description": "Rate of jobs queued, started, and finished across all job types. Computed as rate() over the OTel counter values. High queue rates with low finish rates indicate backlog.", + "description": "**What:** Rate of jobs queued, started, and finished across all job types.\n**How it's computed:** Per-second rate of each cumulative job counter over a 5-minute window.\n**Reading it:** Queued, started, and finished tracking together means the queue keeps up.\n**Healthy range:** Workload-dependent; the three rates should stay roughly equal.\n**Watch for:** Queued rate persistently above finished rate, which indicates a growing backlog.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:recordJobQueued / recordJobStarted / recordJobFinished", "type": "timeseries", "gridPos": { "h": 8, @@ -133,7 +133,7 @@ }, { "title": "Per-Job-Type Queued Rate", - "description": "Rate of jobs queued broken down by job_type label. Identifies which job types contribute most to queue activity.", + "description": "**What:** Rate of jobs entering the queue, broken down by job type (top 10).\n**How it's computed:** Per-second rate of the queued-job counter per job_type over a 5-minute window.\n**Reading it:** Identifies which job types generate the most queue activity.\n**Healthy range:** Workload-dependent.\n**Watch for:** A single job type surging unexpectedly, which can point to a flood of a particular request or peer message.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:recordJobQueued", "type": "timeseries", "gridPos": { "h": 8, @@ -184,7 +184,7 @@ }, { "title": "Per-Job-Type Finish Rate", - "description": "Rate of jobs completing broken down by job_type. Compare with queued rate to identify backlog per type.", + "description": "**What:** Rate of jobs completing, broken down by job type (top 10).\n**How it's computed:** Per-second rate of the finished-job counter per job_type over a 5-minute window.\n**Reading it:** Compare against the queued rate per type to spot which types are falling behind.\n**Healthy range:** Workload-dependent; should match the per-type queued rate.\n**Watch for:** A type whose finish rate lags its queued rate, revealing where the backlog concentrates.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:recordJobFinished", "type": "timeseries", "gridPos": { "h": 8, @@ -235,7 +235,7 @@ }, { "title": "Job Queue Wait Time", - "description": "Job queue wait time distribution (p75 typical, p99 tail). How long jobs sit in the queue before a worker picks them up.", + "description": "**What:** Distribution of how long jobs sit in the queue before a worker picks them up (p75 typical, p99 tail).\n**How it's computed:** Percentiles derived from the job wait-time histogram over a 5-minute window.\n**Reading it:** Lower is better; a widening gap between p75 and p99 signals occasional stalls.\n**Healthy range:** Sub-millisecond to low-millisecond waits on an unloaded node.\n**Watch for:** Rising p99 wait, an early sign of worker-thread saturation.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:recordJobStarted", "type": "timeseries", "gridPos": { "h": 8, @@ -267,12 +267,12 @@ ], "fieldConfig": { "defaults": { - "unit": "\u00b5s", + "unit": "µs", "custom": { "drawStyle": "line", "lineWidth": 2, "fillOpacity": 5, - "axisLabel": "Duration (\u03bcs)", + "axisLabel": "Duration (μs)", "spanNulls": true, "insertNulls": false, "showPoints": "auto", @@ -288,7 +288,7 @@ }, { "title": "Job Execution Time", - "description": "Job execution time distribution (p75 typical, p99 tail). How long jobs run once started.", + "description": "**What:** Distribution of how long jobs run once started (p75 typical, p99 tail).\n**How it's computed:** Percentiles derived from the job run-time histogram over a 5-minute window.\n**Reading it:** Lower is better; stable p75 with a controlled p99 is healthy.\n**Healthy range:** Workload-dependent, but stable over time.\n**Watch for:** Growing execution times, which point to CPU pressure or expensive individual jobs.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:recordJobFinished", "type": "timeseries", "gridPos": { "h": 8, @@ -320,12 +320,12 @@ ], "fieldConfig": { "defaults": { - "unit": "\u00b5s", + "unit": "µs", "custom": { "drawStyle": "line", "lineWidth": 2, "fillOpacity": 5, - "axisLabel": "Duration (\u03bcs)", + "axisLabel": "Duration (μs)", "spanNulls": true, "insertNulls": false, "showPoints": "auto", @@ -341,7 +341,7 @@ }, { "title": "Per-Job-Type Execution Time (p99)", - "description": "Top 10 slowest job types by p99 execution time.", + "description": "**What:** The 10 slowest job types ranked by p99 execution time.\n**How it's computed:** p99 derived from the run-time histogram per job_type over a 5-minute window, top 10 selected.\n**Reading it:** Highlights which job types cost the most CPU time at the tail.\n**Healthy range:** Workload-dependent.\n**Watch for:** A job type whose p99 grows over time, indicating a slow or degrading operation.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:recordJobFinished", "type": "timeseries", "gridPos": { "h": 8, @@ -371,12 +371,12 @@ ], "fieldConfig": { "defaults": { - "unit": "\u00b5s", + "unit": "µs", "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 5, - "axisLabel": "Duration (\u03bcs)", + "axisLabel": "Duration (μs)", "spanNulls": true, "insertNulls": false, "showPoints": "auto", @@ -392,7 +392,7 @@ }, { "title": "Transaction Overflow Rate", - "description": "Rate of job queue transaction overflows per minute. Overflows occur when the job queue's transaction limit is exceeded, causing transactions to be dropped. Non-zero values indicate the node is under heavy transaction load.", + "description": "**What:** Rate at which transaction jobs are shed because the queue's transaction limit is exceeded.\n**How it's computed:** Per-second rate of the overflow counter over a 5-minute window, scaled to per minute.\n**Reading it:** Zero is healthy; any non-zero value means transaction jobs are being dropped under load.\n**Healthy range:** 0 overflows per minute under normal operation.\n**Watch for:** Non-zero overflows, which mark heavy transaction load or a flood; note this counter is typically absent when the node is healthy.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp (job-queue transaction overflow counter)", "type": "timeseries", "gridPos": { "h": 8, @@ -454,7 +454,7 @@ } ], "schemaVersion": 39, - "tags": ["job-queue"], + "tags": ["node", "jobqueue"], "templating": { "list": [ { diff --git a/docker/telemetry/grafana/dashboards/xrpld-peer-quality.json b/docker/telemetry/grafana/dashboards/xrpld-peer-quality.json index 3d5f0a5a06..ed44737867 100644 --- a/docker/telemetry/grafana/dashboards/xrpld-peer-quality.json +++ b/docker/telemetry/grafana/dashboards/xrpld-peer-quality.json @@ -2,7 +2,7 @@ "annotations": { "list": [] }, - "description": "Peer network quality metrics: latency, divergence, version distribution, upgrade recommendations, disconnects, and connection direction balance. Requires push_metrics.py or equivalent OTel metric source.", + "description": "Peer connection quality: latency, divergence, version distribution and upgrade guidance, resource disconnects, and inbound/outbound balance.", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, @@ -11,7 +11,7 @@ "panels": [ { "title": "P90 Peer Latency", - "description": "90th percentile peer-to-peer latency in milliseconds over time. High latency indicates network congestion or geographically distant peers.", + "description": "**What:** 90th-percentile round-trip latency to connected peers, in milliseconds.\n**How it's computed:** Instantaneous gauge reading of the p90 peer latency.\n**Reading it:** Lower is better; green under 200ms, yellow to 500ms, red above.\n**Healthy range:** Under 200ms.\n**Watch for:** Rising latency, which points to network congestion or geographically distant, poorly performing peers.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerPeerQualityGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -72,7 +72,7 @@ }, { "title": "Insane/Diverged Peers", - "description": "Count of peers whose ledger state is considered insane or diverged from the network. Non-zero values suggest those peers are misbehaving or on a fork.", + "description": "**What:** Count of connected peers whose ledger state is insane or diverged from the network.\n**How it's computed:** Instantaneous gauge reading of the diverged-peer count.\n**Reading it:** Zero is healthy; any count means those peers disagree on ledger state.\n**Healthy range:** 0 diverged peers.\n**Watch for:** A persistent non-zero count, which can indicate peers on a fork or misbehaving/malicious peers.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerPeerQualityGauge", "type": "stat", "gridPos": { "h": 8, @@ -121,7 +121,7 @@ }, { "title": "Higher Version Peers %", - "description": "Percentage of connected peers running a higher rippled version. A high percentage suggests this node should be upgraded.", + "description": "**What:** Percentage of connected peers running a newer rippled version than this node.\n**How it's computed:** Instantaneous gauge reading of the higher-version peer percentage.\n**Reading it:** A high percentage suggests this node is behind and should be upgraded.\n**Healthy range:** Under 30%.\n**Watch for:** A majority of peers on a newer version, a strong upgrade signal.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerPeerQualityGauge", "type": "stat", "gridPos": { "h": 8, @@ -172,7 +172,7 @@ }, { "title": "Upgrade Recommended", - "description": "Whether an upgrade is recommended based on peer version analysis (1=recommended, 0=not needed). Triggered when a majority of peers run a newer version.", + "description": "**What:** A flag indicating whether an upgrade is advised based on peer version analysis (Yes/No).\n**How it's computed:** Instantaneous gauge reading of the upgrade-recommended flag.\n**Reading it:** No is healthy; Yes means most peers run a newer version.\n**Healthy range:** No.\n**Watch for:** A Yes state, indicating the node risks falling out of step with the network.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerPeerQualityGauge", "type": "stat", "gridPos": { "h": 8, @@ -237,7 +237,7 @@ }, { "title": "Resource Disconnects", - "description": "Cumulative peer disconnections due to resource limit violations over time. Rising values indicate aggressive or misbehaving peers being dropped.", + "description": "**What:** Cumulative count of peers dropped for exceeding resource (load) limits.\n**How it's computed:** Instantaneous gauge reading of the resource-disconnect total over time.\n**Reading it:** A flat line is healthy; a rising line means peers are being dropped for overuse.\n**Healthy range:** Flat / near constant.\n**Watch for:** A steep climb, which flags aggressive or misbehaving peers being shed as backpressure.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerServerInfoGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -282,7 +282,7 @@ }, { "title": "Inbound vs Outbound Peers", - "description": "Comparison of active inbound and outbound peer connections. A healthy node should have a balanced mix. All-inbound may indicate NAT/firewall issues preventing outbound connections.", + "description": "**What:** Active inbound versus outbound peer connection counts.\n**How it's computed:** Instantaneous gauge readings of active inbound and outbound peer counts.\n**Reading it:** A balanced mix is healthy for connectivity and resilience.\n**Healthy range:** A mix of both; some outbound connections present.\n**Watch for:** All-inbound with no outbound, which usually means NAT or firewall issues block outbound peering.\n**Source:** src/xrpld/peerfinder/detail/PeerfinderManager.cpp:Logic Stats ctor", "type": "bargauge", "gridPos": { "h": 8, @@ -363,7 +363,7 @@ } ], "schemaVersion": 39, - "tags": ["peer", "network"], + "tags": ["network", "peer"], "templating": { "list": [ { diff --git a/docker/telemetry/grafana/dashboards/xrpld-validator-health.json b/docker/telemetry/grafana/dashboards/xrpld-validator-health.json index f8f5e59f04..b6ca482e10 100644 --- a/docker/telemetry/grafana/dashboards/xrpld-validator-health.json +++ b/docker/telemetry/grafana/dashboards/xrpld-validator-health.json @@ -2,7 +2,7 @@ "annotations": { "list": [] }, - "description": "Validator health metrics: agreement rates, validation counts, amendment status, UNL expiry, server state tracking, and ledger close rates. Requires push_metrics.py or equivalent OTel metric source.", + "description": "Validator agreement rates, validation counts, amendment and UNL status, server state tracking, and ledger close rate.", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, @@ -23,7 +23,7 @@ }, { "title": "Agreement % (1h)", - "description": "Validation agreement percentage over the last 1 hour. Values below 80% indicate the validator is frequently disagreeing with the network consensus.", + "description": "**What:** Share of ledgers over the last hour where this validator agreed with the network consensus.\n**How it's computed:** Instantaneous gauge reading of the 1-hour agreement percentage.\n**Reading it:** Higher is better; green at 95%+, yellow from 80%, red below.\n**Healthy range:** 95-100%.\n**Watch for:** Values below 80%, meaning the validator frequently disagrees with consensus.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidationAgreementGauge", "type": "stat", "gridPos": { "h": 8, @@ -74,7 +74,7 @@ }, { "title": "Agreement % (24h)", - "description": "Validation agreement percentage over the last 24 hours. A sustained value below 90% may indicate configuration drift or network partition.", + "description": "**What:** Share of ledgers over the last 24 hours where this validator agreed with consensus.\n**How it's computed:** Instantaneous gauge reading of the 24-hour agreement percentage.\n**Reading it:** Higher is better; a smoother, longer-term view than the 1h stat.\n**Healthy range:** 95-100%.\n**Watch for:** A sustained dip below 90%, which can indicate configuration drift or a network partition.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidationAgreementGauge", "type": "stat", "gridPos": { "h": 8, @@ -125,7 +125,7 @@ }, { "title": "Agreements vs Missed (1h)", - "description": "Comparison of successful agreements and missed validations over 1 hour. High missed count indicates the validator is not participating in consensus rounds.", + "description": "**What:** Counts of agreed versus missed validations over the last hour.\n**How it's computed:** Instantaneous gauge readings of the 1-hour agreed and missed counts.\n**Reading it:** Agreements should dominate; missed should be small.\n**Healthy range:** Missed near 0.\n**Watch for:** A high missed count, meaning the validator is skipping consensus rounds.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidationAgreementGauge", "type": "bargauge", "gridPos": { "h": 8, @@ -191,7 +191,7 @@ }, { "title": "Agreements vs Missed (24h)", - "description": "Comparison of successful agreements and missed validations over 24 hours. Provides a longer-term view of validator reliability.", + "description": "**What:** Counts of agreed versus missed validations over the last 24 hours.\n**How it's computed:** Instantaneous gauge readings of the 24-hour agreed and missed counts.\n**Reading it:** Agreements should dominate over the full day.\n**Healthy range:** Missed a small fraction of agreements.\n**Watch for:** A growing missed share, signalling longer-term reliability problems.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidationAgreementGauge", "type": "bargauge", "gridPos": { "h": 8, @@ -269,7 +269,7 @@ }, { "title": "Validation Rate", - "description": "Rate of validations sent per minute (5m average). Indicates how actively this node is producing validations. Expected ~10-12/min on mainnet (one per ledger close).", + "description": "**What:** Validations this node sends per minute.\n**How it's computed:** Per-second rate of the sent-validations counter over 5 minutes, scaled to per minute.\n**Reading it:** Should track the ledger close cadence; roughly one validation per closed ledger.\n**Healthy range:** About 10-12 per minute on mainnet.\n**Watch for:** A drop toward zero, meaning the validator has stopped participating.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:incrementValidationsSent (caller src/xrpld/app/consensus/RCLConsensus.cpp)", "type": "stat", "gridPos": { "h": 8, @@ -318,7 +318,7 @@ }, { "title": "Validations Checked Rate", - "description": "Rate of validations checked (received from peers) per minute (5m average). Indicates how many validations from the network are being processed.", + "description": "**What:** Validations received from peers and checked per minute.\n**How it's computed:** Per-second rate of the checked-validations counter over 5 minutes, scaled to per minute.\n**Reading it:** Reflects how much validation traffic the network is delivering to this node.\n**Healthy range:** Workload-dependent; scales with trusted validator count.\n**Watch for:** A sudden collapse, which suggests peer connectivity loss or network isolation.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:incrementValidationsChecked (caller src/xrpld/app/misc/NetworkOPs.cpp)", "type": "stat", "gridPos": { "h": 8, @@ -351,7 +351,7 @@ }, { "title": "Amendment Blocked", - "description": "Whether the node is amendment-blocked (1=blocked, 0=normal). An amendment-blocked node cannot validate and needs a software upgrade.", + "description": "**What:** Whether the node is amendment-blocked (OK/BLOCKED).\n**How it's computed:** Instantaneous gauge reading of the amendment-blocked flag.\n**Reading it:** OK is healthy; BLOCKED means an enabled amendment is unsupported by this build.\n**Healthy range:** OK.\n**Watch for:** A BLOCKED state, which halts validation and requires a software upgrade.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidatorHealthGauge", "type": "stat", "gridPos": { "h": 8, @@ -416,7 +416,7 @@ }, { "title": "UNL Expiry (days)", - "description": "Days until the UNL (Unique Node List) expires. A value below 7 requires attention to renew the UNL before it expires and the validator stops trusting peers.", + "description": "**What:** Days remaining until the current UNL (trusted validator list) expires.\n**How it's computed:** Instantaneous gauge reading of days-to-expiry.\n**Reading it:** Higher is safer; green at 30+, yellow under 7, red at expiry.\n**Healthy range:** 30+ days.\n**Watch for:** Fewer than 7 days, after which the node loses its trusted validator set if not renewed.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidatorHealthGauge", "type": "stat", "gridPos": { "h": 8, @@ -465,7 +465,7 @@ }, { "title": "UNL Blocked", - "description": "Whether the node's UNL (Unique Node List) is blocked (1=blocked, 0=normal). A UNL-blocked node cannot determine validator trust and may stop participating in consensus.", + "description": "**What:** Whether the node's UNL is blocked (OK/BLOCKED).\n**How it's computed:** Instantaneous gauge reading of the UNL-blocked flag.\n**Reading it:** OK is healthy; BLOCKED means validator trust cannot be established.\n**Healthy range:** OK.\n**Watch for:** A BLOCKED state, which can stop the node participating in consensus.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidatorHealthGauge", "type": "stat", "gridPos": { "h": 8, @@ -530,7 +530,7 @@ }, { "title": "Agreement/Missed Counters (Rate)", - "description": "Rate of cumulative validation agreements and misses per minute. These monotonic counters complement the rolling window percentages above.", + "description": "**What:** Rate of cumulative agreement and missed-validation counters per minute.\n**How it's computed:** Per-second rate of each monotonic counter over 5 minutes, scaled to per minute.\n**Reading it:** Agreements should dominate; the missed line should stay low.\n**Healthy range:** Missed rate near 0.\n**Watch for:** A rising missed rate, complementing the windowed agreement percentages above.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidationTotalsCounters", "type": "timeseries", "gridPos": { "h": 8, @@ -610,7 +610,7 @@ }, { "title": "Validation Quorum", - "description": "Minimum number of trusted validations needed to declare a ledger validated. Tracks the current quorum requirement from the validator list.", + "description": "**What:** Minimum number of trusted validations required to declare a ledger fully validated.\n**How it's computed:** Instantaneous gauge reading of the current quorum requirement.\n**Reading it:** Tracks the quorum derived from the active validator list; changes when the list changes.\n**Healthy range:** Stable at the network-appropriate value.\n**Watch for:** An unexpected drop, which can weaken consensus safety guarantees.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidatorHealthGauge", "type": "stat", "gridPos": { "h": 8, @@ -643,7 +643,7 @@ }, { "title": "State Value Timeline", - "description": "Numeric encoding of the server operating state over time. Useful for correlating state changes with other metrics.", + "description": "**What:** Numeric encoding of the server operating state (disconnected, connected, syncing, tracking, full) over time.\n**How it's computed:** Instantaneous gauge reading of the encoded state value.\n**Reading it:** A flat line at the full-operation state is healthy; steps show transitions.\n**Healthy range:** Steady at the highest (full) state.\n**Watch for:** Frequent transitions, useful for correlating state flapping with other metrics.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerStateTrackingGauge", "type": "timeseries", "gridPos": { "h": 8, @@ -688,7 +688,7 @@ }, { "title": "Time in Current State", - "description": "How long the server has been in its current operating state, in seconds. Short durations with frequent changes indicate instability.", + "description": "**What:** How long the server has held its current operating state, in seconds.\n**How it's computed:** Instantaneous gauge reading of the time-in-state value.\n**Reading it:** Long, growing durations indicate stability.\n**Healthy range:** Long and increasing while in the full-operation state.\n**Watch for:** Short durations resetting often, a sign of state instability; this value may read 0 where not yet populated.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerStateTrackingGauge", "type": "stat", "gridPos": { "h": 8, @@ -721,7 +721,7 @@ }, { "title": "State Changes Rate", - "description": "Rate of server state changes per hour. A healthy node should have near-zero state changes. Frequent transitions indicate network or configuration issues.", + "description": "**What:** Rate of server operating-state changes per hour.\n**How it's computed:** Per-second rate of the state-change counter over a 1-hour window.\n**Reading it:** Near zero is healthy; each increment is one state transition.\n**Healthy range:** Near 0 changes per hour.\n**Watch for:** Frequent transitions, which point to network instability or configuration problems.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:incrementStateChanges (caller src/xrpld/app/misc/NetworkOPs.cpp)", "type": "stat", "gridPos": { "h": 8, @@ -770,7 +770,7 @@ }, { "title": "Ledgers Closed Rate", - "description": "Rate of ledgers closed per minute (5m average). On mainnet, expect roughly 10-12/min. Deviations indicate consensus timing issues.", + "description": "**What:** Ledgers closed per minute by this node.\n**How it's computed:** Per-second rate of the ledgers-closed counter over 5 minutes, scaled to per minute.\n**Reading it:** Should match the network's steady close cadence.\n**Healthy range:** About 10-12 per minute on mainnet.\n**Watch for:** Deviation from the expected cadence, which indicates consensus timing trouble or the node falling behind.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:incrementLedgersClosed (caller src/xrpld/app/consensus/RCLConsensus.cpp)", "type": "stat", "gridPos": { "h": 8, @@ -819,7 +819,7 @@ }, { "title": "Agreement % (7d)", - "description": "Validation agreement percentage over the trailing 7 days \u2014 the long-term reliability window used by external validator dashboards. Complements the 1h/24h stats.", + "description": "**What:** Share of ledgers over the trailing 7 days where this validator agreed with consensus.\n**How it's computed:** Instantaneous gauge reading of the 7-day agreement percentage.\n**Reading it:** The long-term reliability window; higher is better.\n**Healthy range:** 95-100%.\n**Watch for:** A gradual decline, which reflects chronic rather than transient disagreement.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidationAgreementGauge", "type": "stat", "gridPos": { "h": 8, @@ -870,7 +870,7 @@ }, { "title": "Agreements vs Missed (7d)", - "description": "Agreed vs missed validation counts over the trailing 7 days. A rising missed trend signals sustained validator unreliability.", + "description": "**What:** Agreed versus missed validation counts over the trailing 7 days.\n**How it's computed:** Instantaneous gauge readings of the 7-day agreed and missed counts.\n**Reading it:** Agreements should dominate across the week.\n**Healthy range:** Missed a small fraction of agreements.\n**Watch for:** A rising missed trend, signalling sustained validator unreliability.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerValidationAgreementGauge", "type": "timeseries", "gridPos": { "h": 8,