docs(telemetry): re-clean 5 reworked dashboards on phase9 structure, retag, strip suffixes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Pratik Mankawde
2026-07-03 22:23:25 +01:00
parent cc3cb31cd9
commit adb4c7cdb4
5 changed files with 74 additions and 71 deletions

View File

@@ -10,7 +10,7 @@
"panels": [
{
"title": "Ledger Build Rate",
"description": "Rate at which new ledgers are being built. The ledger.build span (BuildLedger.cpp) wraps the entire buildLedgerImpl() function which creates a new ledger from a parent, applies transactions, flushes SHAMap nodes, and sets the accepted state. Should match the consensus close rate (~0.25/sec on mainnet with ~4s rounds).",
"description": "**What:** How many new ledgers this node finishes building per second.\n**How it's computed:** Per-second rate of completed ledger-build operations, averaged over 5 minutes and split by node.\n**Reading it:** A steady flat line; the value should track the network close cadence.\n**Healthy range:** About 0.2-0.3 ledgers/sec on mainnet (roughly one every 3-5s); workload-dependent on test networks.\n**Watch for:** A drop toward zero (node fell out of sync or stalled) or a value well above the network rate (rebuilding history).\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:buildLedgerImpl",
"type": "stat",
"gridPos": {
"h": 8,
@@ -42,7 +42,7 @@
},
{
"title": "Ledger Build Duration",
"description": "p95 duration of ledger builds. Measures the full buildLedgerImpl() call including transaction application, SHAMap flushing, and ledger acceptance. The span records xrpl.ledger.seq as an attribute. Long build times indicate expensive transaction sets or I/O pressure from SHAMap flushes.",
"description": "**What:** The time taken to build a single ledger, at the 95th percentile.\n**How it's computed:** 95th-percentile of ledger-build durations over a 5-minute window, per node.\n**Reading it:** Lower is better; the line should stay well under the ledger interval.\n**Healthy range:** Typically tens to low hundreds of milliseconds; workload-dependent.\n**Watch for:** Sustained rises approaching the close interval, which indicate heavy transaction sets or disk/I/O pressure.\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:buildLedgerImpl",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -81,7 +81,7 @@
},
{
"title": "Ledger Validation Rate",
"description": "Rate at which ledgers pass the validation threshold and are accepted as fully validated. The ledger.validate span (LedgerMaster.cpp) fires in checkAccept() only after the ledger receives sufficient trusted validations (>= quorum). Records xrpl.ledger.seq and validations (the number of validations received).",
"description": "**What:** How often ledgers reach full validation (accepted by the trusted validator quorum) per second.\n**How it's computed:** Per-second rate of ledger-validation events over 5 minutes, per node.\n**Reading it:** Should closely match the build rate under normal, in-sync operation.\n**Healthy range:** About 0.2-0.3/sec on mainnet; workload-dependent elsewhere.\n**Watch for:** A validation rate that lags the build rate, signalling the node is building ahead of the network consensus it trusts.\n**Source:** src/xrpld/app/ledger/detail/LedgerMaster.cpp:LedgerMaster::checkAccept",
"type": "stat",
"gridPos": {
"h": 8,
@@ -113,7 +113,7 @@
},
{
"title": "Ledger Build Duration Heatmap",
"description": "Heatmap showing the distribution of ledger.build durations across histogram buckets over time. Each cell represents the count of ledger builds that fell into that duration bucket in a 5m window. Useful for spotting occasional slow ledger builds that may not appear in percentile charts.",
"description": "**What:** The full distribution of ledger-build times over the window, not just a single percentile.\n**How it's computed:** Counts of ledger builds falling in each duration band per 5-minute window, shown as color density.\n**Reading it:** A tight low band is healthy; scattered high cells mean occasional slow builds.\n**Healthy range:** Most mass concentrated in the low-millisecond bands; workload-dependent.\n**Watch for:** A second cluster of hot cells at high durations (bimodal build times) hidden by percentile charts.\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:buildLedgerImpl",
"type": "heatmap",
"gridPos": {
"h": 8,
@@ -149,7 +149,7 @@
},
{
"title": "Transaction Apply Duration",
"description": "p95 duration of applying the consensus transaction set during ledger building. The tx.apply span (BuildLedger.cpp) wraps applyTransactions() which iterates through the CanonicalTXSet with multiple retry passes. Records tx_count (successful) and tx_failed (failed) as attributes.",
"description": "**What:** The time spent applying the agreed transaction set into the new ledger, at the 95th percentile.\n**How it's computed:** 95th-percentile of transaction-apply durations over 5 minutes, per node.\n**Reading it:** Lower is better; this is a large share of total build time.\n**Healthy range:** A few to tens of milliseconds; scales with transaction volume per ledger.\n**Watch for:** Spikes during large or expensive transaction sets, which push out overall ledger build time.\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:applyTransactions",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -188,7 +188,7 @@
},
{
"title": "Transaction Apply Rate",
"description": "Rate of tx.apply span invocations, reflecting how frequently the transaction application phase runs during ledger building. Each ledger build triggers one tx.apply call. Should closely match the ledger build rate.",
"description": "**What:** How often the transaction-apply phase runs per second (once per ledger build).\n**How it's computed:** Per-second rate of transaction-apply operations over 5 minutes, per node.\n**Reading it:** Should track the ledger build rate almost exactly.\n**Healthy range:** About 0.2-0.3/sec on mainnet; workload-dependent.\n**Watch for:** Divergence from the build rate, which would indicate a metric or pipeline anomaly.\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:applyTransactions",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -227,7 +227,7 @@
},
{
"title": "Ledger Store Rate",
"description": "Rate at which ledgers are stored into the ledger history. The ledger.store span (LedgerMaster.cpp) wraps storeLedger() which inserts the ledger into the LedgerHistory cache. Records xrpl.ledger.seq. Should match the ledger build rate under normal operation.",
"description": "**What:** How often completed ledgers are written into ledger history per second.\n**How it's computed:** Per-second rate of ledger-store operations over 5 minutes, per node.\n**Reading it:** Should match the build rate during normal operation.\n**Healthy range:** About 0.2-0.3/sec on mainnet; can burst higher while backfilling history.\n**Watch for:** A store rate below the build rate (storage falling behind) or a stall at zero.\n**Source:** src/xrpld/app/ledger/detail/LedgerMaster.cpp:LedgerMaster::storeLedger",
"type": "stat",
"gridPos": {
"h": 8,
@@ -259,7 +259,7 @@
},
{
"title": "Build vs Close Duration",
"description": "Compares p95 durations of ledger.build (the actual ledger construction in BuildLedger.cpp) vs consensus.ledger_close (the consensus close event in RCLConsensus.cpp). Build time is a subset of close time. A large gap between them indicates overhead in the consensus pipeline outside of ledger construction itself.",
"description": "**What:** Ledger build time compared with the total consensus ledger-close time, both at the 95th percentile.\n**How it's computed:** Two 95th-percentile duration series over 5 minutes: ledger construction and the full consensus close, per node.\n**Reading it:** Build should sit below close; the gap is consensus overhead outside construction.\n**Healthy range:** Close a bit above build; both workload-dependent and under the round interval.\n**Watch for:** A widening gap (consensus-pipeline overhead growing) or build time approaching close time.\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:buildLedgerImpl; src/xrpld/app/consensus/RCLConsensus.cpp:RCLConsensus::Adaptor::onClose",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -371,7 +371,7 @@
{
"name": "node",
"label": "Node",
"description": "Filter by rippled node (service.instance.id \u2014 e.g. Node-1)",
"description": "Filter by rippled node (service.instance.id e.g. Node-1)",
"type": "query",
"query": "label_values(traces_span_metrics_calls_total, exported_instance)",
"datasource": {
@@ -396,5 +396,6 @@
},
"title": "Ledger Operations",
"uid": "xrpld-ledger-ops",
"refresh": "5s"
"refresh": "5s",
"description": "Ledger construction, validation, and storage activity and timing for this node."
}

View File

@@ -2,7 +2,7 @@
"annotations": {
"list": []
},
"description": "Requires trace_peer=1 in the [telemetry] config section.",
"description": "Consensus proposals and validations received from peers, and transaction relay efficiency for this node.",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 1,
@@ -11,7 +11,7 @@
"panels": [
{
"title": "Peer Proposal Receive Rate",
"description": "Rate of consensus proposals received from network peers. The peer.proposal.receive span (PeerImp.cpp) fires in onMessage(TMProposeSet) for each incoming proposal. Records xrpl.peer.id (sending peer) and proposal_trusted (whether the proposer is in our UNL). Requires trace_peer=1 in the telemetry config.",
"description": "**What:** How many consensus proposals this node receives from peers per second.\n**How it's computed:** Per-second rate of received proposals over 5 minutes, per node.\n**Reading it:** A steady rate roughly proportional to the number of proposing validators.\n**Healthy range:** Workload-dependent; scales with validator count and connectivity.\n**Watch for:** A drop toward zero (isolation from the network) or a sudden flood far above baseline (proposal spam).\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::onMessage(TMProposeSet)",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -50,7 +50,7 @@
},
{
"title": "Peer Validation Receive Rate",
"description": "Rate of ledger validations received from network peers. The peer.validation.receive span (PeerImp.cpp) fires in onMessage(TMValidation) for each incoming validation message. Records xrpl.peer.id (sending peer) and validation_trusted (whether the validator is trusted). Requires trace_peer=1 in the telemetry config.",
"description": "**What:** How many ledger validations this node receives from peers per second.\n**How it's computed:** Per-second rate of received validations over 5 minutes, per node.\n**Reading it:** Steady and proportional to the number of validators the node hears from.\n**Healthy range:** Workload-dependent; roughly one burst per validator per closed ledger.\n**Watch for:** A fall toward zero (loss of validator connectivity) or an abnormal surge from untrusted sources.\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::onMessage(TMValidation)",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -89,7 +89,7 @@
},
{
"title": "Proposals Trusted vs Untrusted",
"description": "Pie chart showing the ratio of proposals received from trusted validators (in our UNL) vs untrusted validators. Grouped by the proposal_trusted span attribute (true/false). A healthy node connected to a well-configured UNL should see a significant portion of trusted proposals. Note: proposals that fail early validation may not have the trusted attribute set.",
"description": "**What:** The share of received proposals that come from trusted (UNL) validators versus everyone else.\n**How it's computed:** Received-proposal rate split by trust status over 5 minutes, shown as proportions.\n**Reading it:** A healthy node with a good UNL shows a solid trusted slice.\n**Healthy range:** Workload-dependent; a meaningful trusted fraction is expected.\n**Watch for:** A collapsing trusted share or a large untrusted volume, consistent with proposal flooding from non-UNL peers.\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::onMessage(TMProposeSet)",
"type": "piechart",
"gridPos": {
"h": 8,
@@ -121,7 +121,7 @@
},
{
"title": "Validations Trusted vs Untrusted",
"description": "Pie chart showing the ratio of validations received from trusted validators (in our UNL) vs untrusted validators. Grouped by the validation_trusted span attribute (true/false). Monitoring this helps detect if the node is receiving validations from the expected set of trusted validators. Note: validations that fail early checks may not have the trusted attribute set.",
"description": "**What:** The share of received validations from trusted (UNL) validators versus untrusted sources.\n**How it's computed:** Received-validation rate split by trust status over 5 minutes, shown as proportions.\n**Reading it:** The trusted slice should dominate for a well-configured node.\n**Healthy range:** Workload-dependent; trusted validations expected to be the majority.\n**Watch for:** A shrinking trusted share or a spike of untrusted validations, which can indicate misconfiguration or abuse.\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::onMessage(TMValidation)",
"type": "piechart",
"gridPos": {
"h": 8,
@@ -153,7 +153,7 @@
},
{
"title": "Reduce-Relay Peer Selection",
"description": "Transaction reduce-relay efficiency: peers selected as relay sources vs suppressed, plus peers with the feature disabled. A high suppressed:selected ratio proves reduce-relay is saving bandwidth; a high not_enabled count means stale peers force full relay.",
"description": "**What:** How transaction relay picks peers: chosen relay sources, suppressed peers, and peers with the feature off.\n**How it's computed:** Current peer counts in each category (selected, suppressed, not-enabled), per node.\n**Reading it:** A high suppressed-to-selected ratio means relay is saving bandwidth as intended.\n**Healthy range:** Workload-dependent; suppressed should exceed selected in a well-connected mesh.\n**Watch for:** A large not-enabled count (older peers forcing full relay) or selected climbing while suppressed falls.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerReduceRelayGauge",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -206,7 +206,7 @@
},
{
"title": "Reduce-Relay Missing-Tx Frequency",
"description": "Frequency of on-demand transaction fetches triggered when a peer is missing a relayed transaction. A rising value means the suppression is too aggressive and the on-demand fetch path is growing.",
"description": "**What:** How often a peer has to fetch a transaction it missed because relay suppressed it.\n**How it's computed:** The reported frequency of on-demand missing-transaction fetches, per node.\n**Reading it:** Lower is better; near-flat means suppression is well tuned.\n**Healthy range:** Workload-dependent; a low, stable value is expected.\n**Watch for:** A rising trend, meaning suppression is too aggressive and the on-demand fetch path is growing.\n**Source:** src/xrpld/telemetry/MetricsRegistry.cpp:registerReduceRelayGauge",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -245,7 +245,7 @@
}
],
"schemaVersion": 39,
"tags": ["peer"],
"tags": ["network", "peer"],
"templating": {
"list": [
{
@@ -311,7 +311,7 @@
{
"name": "node",
"label": "Node",
"description": "Filter by rippled node (service.instance.id \u2014 e.g. Node-1)",
"description": "Filter by rippled node (service.instance.id e.g. Node-1)",
"type": "query",
"query": "label_values(traces_span_metrics_calls_total, exported_instance)",
"datasource": {

View File

@@ -10,7 +10,7 @@
"panels": [
{
"title": "RPC Request Rate by Command",
"description": "Per-second rate of RPC command executions, broken down by command name (e.g. server_info, submit). Calculated as rate(traces_span_metrics_calls_total{span_name=~\"rpc.command.*\"}) over a 5m window, grouped by the command span attribute.",
"description": "**What:** How many times each RPC command runs per second.\n**How it's computed:** Per-second rate of command executions over 5 minutes, grouped by command name and node.\n**Reading it:** Compare bars/lines across commands to see which endpoints drive load.\n**Healthy range:** Workload-dependent; dominated by whichever commands clients call most.\n**Watch for:** A single command spiking far above its norm, consistent with a client hammering one endpoint.\n**Source:** src/xrpld/rpc/detail/RPCHandler.cpp:callMethod",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -49,7 +49,7 @@
},
{
"title": "RPC Latency P95 by Command",
"description": "95th percentile response time for each RPC command. Computed from the spanmetrics duration histogram using histogram_quantile(0.95) over rpc.command.* spans, grouped by command. High values indicate slow commands that may need optimization.",
"description": "**What:** The 95th-percentile response time for each RPC command.\n**How it's computed:** 95th-percentile of per-command execution durations over 5 minutes, grouped by command and node.\n**Reading it:** Lower is better; watch the slowest commands.\n**Healthy range:** Fast lookups a few ms; heavy queries tens to hundreds of ms. Workload-dependent.\n**Watch for:** A command whose latency climbs steadily, pointing to an expensive or degrading query path.\n**Source:** src/xrpld/rpc/detail/RPCHandler.cpp:callMethod",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -88,7 +88,7 @@
},
{
"title": "RPC Error Rate",
"description": "Percentage of RPC commands that completed with an error status, per command. Calculated as (error calls / total calls) * 100, where errors have status_code=STATUS_CODE_ERROR. Thresholds: green < 1%, yellow 1-5%, red > 5%.",
"description": "**What:** The percentage of each command's calls that finished with an error.\n**How it's computed:** Error calls divided by total calls per command over 5 minutes, expressed as a percent.\n**Reading it:** Green under 1%, yellow 1-5%, red above 5%.\n**Healthy range:** Below 1% per command in normal operation.\n**Watch for:** A command sitting red, indicating malformed input, overload, or a broken handler.\n**Source:** src/xrpld/rpc/detail/RPCHandler.cpp:callMethod",
"type": "bargauge",
"gridPos": {
"h": 8,
@@ -136,7 +136,7 @@
},
{
"title": "RPC Latency Heatmap",
"description": "Distribution of RPC command response times across histogram buckets. Shows the density of requests at each latency level over time. Each cell represents the count of requests that fell into that duration bucket in a 5m window. Useful for spotting bimodal latency patterns.",
"description": "**What:** The full distribution of RPC response times over the window.\n**How it's computed:** Counts of requests in each latency band per 5-minute window, shown as color density.\n**Reading it:** A tight low band is healthy; multiple bands mean mixed fast/slow requests.\n**Healthy range:** Most mass in the low-latency bands; workload-dependent.\n**Watch for:** A distinct high-latency cluster (bimodal behavior) that percentiles alone would hide.\n**Source:** src/xrpld/rpc/detail/RPCHandler.cpp:callMethod",
"type": "heatmap",
"gridPos": {
"h": 8,
@@ -172,7 +172,7 @@
},
{
"title": "Overall RPC Throughput",
"description": "Aggregate RPC throughput showing two layers of the request pipeline. rpc.http_request is the outer HTTP handler (ServerHandler.cpp) that accepts incoming connections. rpc.process is the inner processing layer (ServerHandler.cpp) that parses and dispatches. A gap between the two indicates requests being queued or rejected before processing.",
"description": "**What:** Two layers of the request pipeline: connections accepted by the HTTP handler versus requests parsed and dispatched.\n**How it's computed:** Per-second rates of the outer request-accept layer and the inner processing layer over 5 minutes, per node.\n**Reading it:** The two lines should track each other closely.\n**Healthy range:** Workload-dependent; both lines roughly equal.\n**Watch for:** A gap between accept and process, meaning requests are queued or rejected before dispatch.\n**Source:** src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler::processSession; src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler::processRequest",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -218,7 +218,7 @@
},
{
"title": "RPC Success vs Error",
"description": "Aggregate rate of successful vs failed RPC commands across all command types. Success = status_code UNSET (OpenTelemetry default for OK spans). Error = status_code STATUS_CODE_ERROR. A sustained error rate warrants investigation via per-command breakdown above.",
"description": "**What:** Aggregate rate of successful versus failed RPC commands across all command types.\n**How it's computed:** Per-second rates of ok and errored command completions over 5 minutes, per node.\n**Reading it:** Success should dominate; the error line should stay near the floor.\n**Healthy range:** Error line near zero relative to success; workload-dependent.\n**Watch for:** A sustained error line, which warrants drilling into the per-command breakdown.\n**Source:** src/xrpld/rpc/detail/RPCHandler.cpp:callMethod",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -264,7 +264,7 @@
},
{
"title": "Top Commands by Volume",
"description": "Top 10 most frequently called RPC commands by total invocation count over the last 5 minutes. Uses topk(10, increase(calls_total)) to rank commands. Helps identify the hottest API endpoints driving load on the node.",
"description": "**What:** The ten most-called RPC commands over the recent window.\n**How it's computed:** Total invocation counts per command over the last 5 minutes, ranked and capped at ten.\n**Reading it:** The top bars are the hottest endpoints driving node load.\n**Healthy range:** Workload-dependent; typically led by lightweight status queries.\n**Watch for:** An unexpected command dominating the ranking, consistent with automated abuse.\n**Source:** src/xrpld/rpc/detail/RPCHandler.cpp:callMethod",
"type": "bargauge",
"gridPos": {
"h": 8,
@@ -296,7 +296,7 @@
},
{
"title": "WebSocket Message Rate",
"description": "Rate of incoming WebSocket RPC messages processed by the server. Sourced from the rpc.ws_message span (ServerHandler.cpp). Only active when clients connect via WebSocket instead of HTTP. Zero is normal if only HTTP RPC is in use.",
"description": "**What:** How many RPC messages arrive over WebSocket connections per second.\n**How it's computed:** Per-second rate of processed WebSocket RPC messages over 5 minutes, per node.\n**Reading it:** Non-zero only when clients use WebSocket; zero is normal for HTTP-only nodes.\n**Healthy range:** Workload-dependent; zero if no WebSocket clients.\n**Watch for:** A sudden surge from a single source, consistent with a chatty or abusive subscription client.\n**Source:** src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler::processSession",
"type": "stat",
"gridPos": {
"h": 8,
@@ -328,7 +328,7 @@
},
{
"title": "RPC Resource Cost by Command",
"description": "RPC commands grouped by load_type (resource cost category). High-cost categories like exception_rpc or malformed_rpc indicate problematic clients.",
"description": "**What:** RPC traffic grouped by resource-cost category rather than by command name.\n**How it's computed:** Per-second rate of commands over 5 minutes, grouped by load/cost category.\n**Reading it:** Cheap categories should dominate; costly ones should be a small slice.\n**Healthy range:** Workload-dependent; low-cost categories carry most traffic.\n**Watch for:** Growth in high-cost categories such as exception or malformed requests, which point to problematic clients.\n**Source:** src/xrpld/rpc/detail/RPCHandler.cpp:callMethod",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -372,7 +372,7 @@
},
{
"title": "Batch vs Single RPC Requests",
"description": "Rate of batch RPC requests vs single requests. High batch rate may indicate bulk automation clients.",
"description": "**What:** The rate of batched RPC requests versus single-command requests.\n**How it's computed:** Per-second rates of batch and single requests over 5 minutes, per node.\n**Reading it:** Single requests usually dominate; batch is used by bulk clients.\n**Healthy range:** Workload-dependent; batch typically a minority.\n**Watch for:** A batch rate climbing sharply, consistent with bulk automation or amplification attempts.\n**Source:** src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler::processRequest",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -484,7 +484,7 @@
{
"name": "node",
"label": "Node",
"description": "Filter by rippled node (service.instance.id \u2014 e.g. Node-1)",
"description": "Filter by rippled node (service.instance.id e.g. Node-1)",
"type": "query",
"query": "label_values(traces_span_metrics_calls_total, exported_instance)",
"datasource": {
@@ -529,5 +529,6 @@
},
"title": "RPC Performance",
"uid": "xrpld-rpc-perf",
"refresh": "5s"
"refresh": "5s",
"description": "RPC command traffic, latency, error rates, and request shape for this node."
}

View File

@@ -2,7 +2,7 @@
"annotations": {
"list": []
},
"description": "RPC and pathfinding metrics from beast::insight System Metrics. Requires [insight] server=otel in rippled config.",
"description": "RPC request throughput and response timing, pathfinding cost, gRPC read traffic, and resource-manager enforcement for this node.",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 1,
@@ -10,8 +10,8 @@
"links": [],
"panels": [
{
"title": "RPC Request Rate (System Metrics)",
"description": "Rate of RPC requests as counted by the beast::insight counter. Sourced from rpc.requests (ServerHandler.cpp) which increments on every HTTP and WebSocket RPC request. Compare with the span-based rpc.request rate in the RPC Performance dashboard for cross-validation.",
"title": "RPC Request Rate",
"description": "**What:** How many RPC requests the server counts per second.\n**How it's computed:** Per-second rate of the RPC request counter over 5 minutes, per node.\n**Reading it:** A steady line proportional to client demand; cross-checks the trace-based RPC dashboard.\n**Healthy range:** Workload-dependent; tracks client activity.\n**Watch for:** A sudden surge above baseline, consistent with a client flooding the RPC endpoint.\n**Source:** src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler ctor",
"type": "stat",
"gridPos": {
"h": 8,
@@ -42,8 +42,8 @@
}
},
{
"title": "RPC Response Time (System Metrics)",
"description": "P95 of RPC response time from the beast::insight timer. Sourced from the rpc.time event (ServerHandler.cpp) which records elapsed milliseconds for each RPC response. This measures the full HTTP handler time, not just command execution. Compare with span-based rpc.request duration.",
"title": "RPC Response Time",
"description": "**What:** The 95th-percentile end-to-end RPC response time, including HTTP handling.\n**How it's computed:** 95th-percentile of measured response times over 5 minutes, per node.\n**Reading it:** Lower is better; this is broader than command-only latency.\n**Healthy range:** A few to tens of milliseconds; workload-dependent.\n**Watch for:** A sustained climb, indicating handler overload or slow downstream work.\n**Source:** src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler ctor",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -82,7 +82,7 @@
},
{
"title": "RPC Response Size",
"description": "P95 of RPC response payload size in bytes. Sourced from the rpc.size event (ServerHandler.cpp) which records the byte length of each RPC JSON response. Large responses may indicate expensive queries (e.g. account_tx with many results) or API misuse.",
"description": "**What:** The 95th-percentile size of RPC response payloads in bytes.\n**How it's computed:** 95th-percentile of response payload sizes over 5 minutes, per node.\n**Reading it:** Smaller is cheaper; large responses cost bandwidth and memory.\n**Healthy range:** Workload-dependent; small for status queries, large for bulk data queries.\n**Watch for:** Growth in large responses, consistent with expensive queries or API misuse.\n**Source:** src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler ctor",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -121,7 +121,7 @@
},
{
"title": "RPC Response Time Distribution",
"description": "Distribution of RPC response times from the beast::insight timer showing P90, P95, and P99 quantiles. Sourced from the rpc.time event (ServerHandler.cpp). Useful for detecting bimodal latency or long-tail requests.",
"description": "**What:** RPC response time at the 90th, 95th, and 99th percentiles together.\n**How it's computed:** Three response-time quantiles over 5 minutes, per node.\n**Reading it:** Lower is better; the gap between P90 and P99 shows the long tail.\n**Healthy range:** Percentiles clustered low; workload-dependent.\n**Watch for:** A widening P99, revealing long-tail or bimodal slow requests.\n**Source:** src/xrpld/rpc/detail/ServerHandler.cpp:ServerHandler ctor",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -174,7 +174,7 @@
},
{
"title": "Pathfinding Fast Duration",
"description": "P95 of fast pathfinding execution time. Sourced from the pathfind_fast event (PathRequests.h) which records the duration of the fast pathfinding algorithm. Fast pathfinding uses a simplified search that trades accuracy for speed.",
"description": "**What:** The 95th-percentile time of the fast pathfinding search.\n**How it's computed:** 95th-percentile of fast pathfinding durations over 5 minutes, per node.\n**Reading it:** Lower is better; fast mode trades accuracy for speed.\n**Healthy range:** Typically a few to tens of milliseconds; workload-dependent.\n**Watch for:** A rising trend, indicating heavy pathfinding demand or an expensive order book.\n**Source:** src/xrpld/rpc/detail/PathRequestManager.h:ctor",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -213,7 +213,7 @@
},
{
"title": "Pathfinding Full Duration",
"description": "P95 of full pathfinding execution time. Sourced from the pathfind_full event (PathRequests.h) which records the duration of the exhaustive pathfinding search. Full pathfinding is more expensive and can take significantly longer than fast mode.",
"description": "**What:** The 95th-percentile time of the full, exhaustive pathfinding search.\n**How it's computed:** 95th-percentile of full pathfinding durations over 5 minutes, per node.\n**Reading it:** Lower is better; full mode is much more expensive than fast mode.\n**Healthy range:** Tens to hundreds of milliseconds; workload-dependent.\n**Watch for:** Sustained high durations, consistent with pathfinding-heavy clients straining the node.\n**Source:** src/xrpld/rpc/detail/PathRequestManager.h:ctor",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -252,7 +252,7 @@
},
{
"title": "Resource Warnings Rate",
"description": "Rate of resource warning events from the Resource Manager. Sourced from the warn meter (Logic.h) which increments when a consumer (peer or RPC client) exceeds the warning threshold for resource usage. A rising rate indicates aggressive clients that may need throttling. NOTE: This panel will show no data until the |m -> |c fix is applied in System MetricsCollector.cpp (Phase 6 Task 6.1).",
"description": "**What:** How often the resource manager warns a peer or client for excessive usage, per second.\n**How it's computed:** Per-second rate of resource-warning events over 5 minutes, per node.\n**Reading it:** Green near zero, yellow above 0.1/sec, red above 1/sec.\n**Healthy range:** Near zero in normal operation.\n**Watch for:** A rising rate, consistent with aggressive clients that may need throttling.\n**Source:** include/xrpl/resource/detail/Logic.h:Logic::Stats ctor",
"type": "stat",
"gridPos": {
"h": 8,
@@ -300,7 +300,7 @@
},
{
"title": "Resource Drops Rate",
"description": "Rate of resource drop events from the Resource Manager. Sourced from the drop meter (Logic.h) which increments when a consumer is disconnected or blocked due to excessive resource usage. Non-zero values mean the node is actively rejecting abusive connections. NOTE: This panel will show no data until the |m -> |c fix is applied in System MetricsCollector.cpp (Phase 6 Task 6.1).",
"description": "**What:** How often the resource manager drops or blocks a peer or client for abuse, per second.\n**How it's computed:** Per-second rate of resource-drop events over 5 minutes, per node.\n**Reading it:** Green near zero, yellow above 0.01/sec, red above 0.1/sec.\n**Healthy range:** Zero when no abusive consumers are present.\n**Watch for:** Non-zero values, meaning the node is actively rejecting abusive connections.\n**Source:** include/xrpl/resource/detail/Logic.h:Logic::Stats ctor",
"type": "stat",
"gridPos": {
"h": 8,
@@ -348,7 +348,7 @@
},
{
"title": "gRPC Request Rate by Method (Spans)",
"description": "Per-method gRPC call rate derived from the grpc.{Method} spans (GRPCServer.cpp). Covers the gRPC API used by reporting/Clio. Populated only when the node serves gRPC traffic.",
"description": "**What:** How many gRPC calls of each method the node serves per second.\n**How it's computed:** Per-second rate of gRPC calls over 5 minutes, grouped by method and node.\n**Reading it:** Non-zero only when reporting/Clio-style clients use the gRPC API.\n**Healthy range:** Workload-dependent; zero without gRPC traffic.\n**Watch for:** A single method spiking, consistent with a heavy or misbehaving gRPC consumer.\n**Source:** src/xrpld/app/main/GRPCServer.cpp:GRPCServerImpl::CallData::process",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -387,7 +387,7 @@
},
{
"title": "gRPC Latency P95 by Method (Spans)",
"description": "p95 latency per gRPC method from grpc.{Method} span durations. Identifies slow gRPC read paths.",
"description": "**What:** The 95th-percentile latency of each gRPC method.\n**How it's computed:** 95th-percentile of gRPC call durations over 5 minutes, grouped by method and node.\n**Reading it:** Lower is better; identifies slow gRPC read paths.\n**Healthy range:** Workload-dependent; scales with ledger data volume served.\n**Watch for:** A method whose latency climbs, indicating an expensive read path.\n**Source:** src/xrpld/app/main/GRPCServer.cpp:GRPCServerImpl::CallData::process",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -426,7 +426,7 @@
},
{
"title": "gRPC Error Rate by Status (Spans)",
"description": "Rate of gRPC spans broken down by grpc_status (success/error/resource_exhausted/failed_precondition). A rising error or resource_exhausted rate indicates gRPC clients hitting limits.",
"description": "**What:** gRPC call rate broken down by outcome status (success, error, resource-exhausted, failed-precondition).\n**How it's computed:** Per-second rate of gRPC calls over 5 minutes, grouped by status and node.\n**Reading it:** Success should dominate; error and resource-exhausted should stay low.\n**Healthy range:** Workload-dependent; errors near the floor.\n**Watch for:** A rising error or resource-exhausted rate, indicating gRPC clients hitting limits.\n**Source:** src/xrpld/app/main/GRPCServer.cpp:GRPCServerImpl::CallData::process",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -465,7 +465,7 @@
},
{
"title": "Pathfinding Compute Duration (Spans)",
"description": "p95 of the pathfind.compute span, the per-request path computation. Complements the StatsD pathfind_fast/full timers with span-level visibility. Populated under pathfinding (book/path) RPC load.",
"description": "**What:** The 95th-percentile time to compute paths for a single request.\n**How it's computed:** 95th-percentile of path-computation durations over 5 minutes, per node.\n**Reading it:** Lower is better; complements the fast/full pathfinding timers with span-level detail.\n**Healthy range:** Workload-dependent; grows with order-book depth and request complexity.\n**Watch for:** A rising trend under pathfinding load, indicating expensive path computation.\n**Source:** src/xrpld/rpc/detail/PathRequest.cpp:PathRequest::doUpdate",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -504,7 +504,7 @@
},
{
"title": "Pathfinding Request & Discovery Rate (Spans)",
"description": "Rate of pathfind.request (client path requests) and pathfind.discover (path-discovery passes) spans. Shows pathfinding demand and the discovery cost driver for subscription-heavy nodes.",
"description": "**What:** The rate of client path requests versus path-discovery passes.\n**How it's computed:** Per-second rates of path requests and discovery passes over 5 minutes, per node.\n**Reading it:** Discovery cost tracks request demand; useful for subscription-heavy nodes.\n**Healthy range:** Workload-dependent; both zero without pathfinding clients.\n**Watch for:** Discovery rate climbing out of proportion to requests, a cost driver for subscription-heavy nodes.\n**Source:** src/xrpld/rpc/handlers/orderbook/PathFind.cpp:doPathFind; src/xrpld/rpc/detail/PathRequest.cpp:PathRequest::findPaths",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -550,7 +550,7 @@
}
],
"schemaVersion": 39,
"tags": ["statsd", "rpc", "pathfinding"],
"tags": ["rpc", "pathfinding"],
"templating": {
"list": [
{
@@ -659,7 +659,7 @@
"from": "now-1h",
"to": "now"
},
"title": "RPC & Pathfinding (System Metrics)",
"title": "RPC & Pathfinding",
"uid": "xrpld-system-rpc",
"refresh": "5s"
}

View File

@@ -10,7 +10,7 @@
"panels": [
{
"title": "Transaction Apply Failed Rate",
"description": "Rate of tx.apply spans completing with error status, indicating transaction application failures during ledger building. The span records tx_failed as an attribute. Thresholds: green < 0.1/sec, yellow 0.1-1/sec, red > 1/sec. Some failures are normal (e.g. conflicting offers) but sustained high rates may indicate issues.",
"description": "**What:** How many transactions fail during application into a ledger, per second.\n**How it's computed:** Per-second rate of errored transaction-apply operations over 5 minutes, per node.\n**Reading it:** Green under 0.1/sec, yellow 0.1-1/sec, red above 1/sec.\n**Healthy range:** Some failures are normal (e.g. conflicting offers); a low steady rate is fine.\n**Watch for:** A sustained red rate, which can indicate a problem in transaction processing or a spam wave.\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:applyTransactions",
"type": "stat",
"gridPos": {
"h": 4,
@@ -60,7 +60,7 @@
},
{
"title": "Transaction Processing Latency by Type",
"description": "Per-transaction-type processing latency (p95). Filter with $tx_type variable above.",
"description": "**What:** The 95th-percentile time to process a transaction, broken down by transaction type.\n**How it's computed:** 95th-percentile of processing durations over 5 minutes, grouped by transaction type and node.\n**Reading it:** Lower is better; compare types to find the expensive ones.\n**Healthy range:** A few milliseconds for simple payments; workload- and type-dependent.\n**Watch for:** A type whose latency climbs, pointing to expensive processing or resource pressure.\n**Source:** src/xrpld/app/misc/NetworkOPs.cpp:NetworkOPsImp::processTransaction",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -106,7 +106,7 @@
},
{
"title": "Transaction Rate by Type",
"description": "Transaction processing rate broken down by tx_type (Payment, OfferCreate, AMMDeposit, etc.). Requires tx_type dimension in spanmetrics.",
"description": "**What:** How many transactions of each type enter processing per second.\n**How it's computed:** Per-second processing rate over 5 minutes, grouped by transaction type and node.\n**Reading it:** Shows the transaction mix; payments usually lead.\n**Healthy range:** Workload-dependent; mix reflects network activity.\n**Watch for:** A single type spiking far above baseline, consistent with a spam campaign of that type.\n**Source:** src/xrpld/app/misc/NetworkOPs.cpp:NetworkOPsImp::processTransaction",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -152,7 +152,7 @@
},
{
"title": "Transaction Results by Type",
"description": "Transaction result codes (ter_result) broken down by tx_type. Shows which transaction types fail most often.",
"description": "**What:** The non-success result codes transactions return, by transaction type.\n**How it's computed:** Per-second rate of failing transactions over 5 minutes, grouped by type and result code.\n**Reading it:** Fewer failures is better; use it to see which types fail and why.\n**Healthy range:** Workload-dependent; a modest background of expected failures is normal.\n**Watch for:** A surge of one failure code for one type, indicating a systemic issue or abusive submissions.\n**Source:** src/xrpld/app/misc/NetworkOPs.cpp:NetworkOPsImp::processTransaction",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -198,7 +198,7 @@
},
{
"title": "Transaction Receive vs Suppressed",
"description": "Total rate of raw transaction messages received from peers (tx.receive span from PeerImp.cpp). This fires before deduplication via the HashRouter, so the difference between tx.receive and tx.process reflects suppressed duplicate transactions.",
"description": "**What:** Raw transactions received from peers, split by whether they were duplicates suppressed before processing.\n**How it's computed:** Per-second rate of received transactions over the window, split by suppressed flag and node.\n**Reading it:** A large suppressed share is normal, since the same transaction arrives from many peers.\n**Healthy range:** Workload-dependent; suppressed typically exceeds newly processed.\n**Watch for:** A collapse in suppression (duplicate filtering failing) or an overall receive flood.\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::handleTransaction",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -239,7 +239,7 @@
},
{
"title": "Transaction Processing Rate",
"description": "Rate of transactions entering the processing pipeline. tx.process (NetworkOPs.cpp) fires when a transaction is submitted locally or received from a peer and enters processTransaction(). tx.receive (PeerImp.cpp) fires when a raw transaction message arrives from a peer before deduplication.",
"description": "**What:** Transactions entering the processing pipeline versus raw transactions arriving from peers.\n**How it's computed:** Per-second rates of processed transactions and received peer transactions over 5 minutes, per node.\n**Reading it:** Received sits above processed; the difference is deduplicated relay traffic.\n**Healthy range:** Workload-dependent; both scale with network volume.\n**Watch for:** A receive rate spiking well above processing, consistent with relay flooding.\n**Source:** src/xrpld/app/misc/NetworkOPs.cpp:NetworkOPsImp::processTransaction; src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::handleTransaction",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -287,7 +287,7 @@
},
{
"title": "Transaction Path Distribution",
"description": "Breakdown of transactions by origin path. The local attribute indicates whether the transaction was submitted locally (true) or received from a peer (false). Helps understand the ratio of locally-originated vs relayed transactions.",
"description": "**What:** The split of transactions by origin: submitted locally versus relayed from peers.\n**How it's computed:** Processed-transaction rate over 5 minutes, split by local-origin flag and shown as proportions.\n**Reading it:** Most traffic on a network node is peer-relayed; local dominates on a submission node.\n**Healthy range:** Workload-dependent on the node's role.\n**Watch for:** An unexpected surge in local submissions, consistent with a local client flooding the node.\n**Source:** src/xrpld/app/misc/NetworkOPs.cpp:NetworkOPsImp::processTransaction",
"type": "piechart",
"gridPos": {
"h": 8,
@@ -315,7 +315,7 @@
},
{
"title": "Transaction Processing Duration Heatmap",
"description": "Heatmap showing the distribution of tx.process span durations across histogram buckets over time. Each cell represents the count of transactions that completed within that latency bucket in a 5m window. Reveals whether processing times are consistent or exhibit multi-modal patterns.",
"description": "**What:** The full distribution of transaction processing times over the window.\n**How it's computed:** Counts of transactions in each latency band per 5-minute window, shown as color density.\n**Reading it:** A tight low band is healthy; spread bands mean uneven processing time.\n**Healthy range:** Most mass in the low-latency bands; workload-dependent.\n**Watch for:** A distinct slow cluster (multi-modal timing) hidden by percentile charts.\n**Source:** src/xrpld/app/misc/NetworkOPs.cpp:NetworkOPsImp::processTransaction",
"type": "heatmap",
"gridPos": {
"h": 8,
@@ -353,7 +353,7 @@
},
{
"title": "Peer Transaction Receive Rate",
"description": "Rate of transaction messages received from network peers. Sourced from the tx.receive span (PeerImp.cpp) which fires in the onMessage(TMTransaction) handler. High rates may indicate network-wide transaction volume spikes or peer flooding.",
"description": "**What:** How many transaction messages arrive from network peers per second.\n**How it's computed:** Per-second rate of received peer transactions over 5 minutes, per node.\n**Reading it:** Reflects network-wide transaction volume reaching this node.\n**Healthy range:** Workload-dependent; tracks overall network activity.\n**Watch for:** A sharp spike above baseline, consistent with network-wide volume surges or peer flooding.\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::handleTransaction",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -394,7 +394,7 @@
},
{
"title": "Transactor Duration by Type (p95)",
"description": "Per-transactor execution time (tx.transactor span). Shows which transaction types are most expensive to execute.",
"description": "**What:** The 95th-percentile execution time of the core transactor step, by transaction type.\n**How it's computed:** 95th-percentile of transactor durations over 5 minutes, grouped by type and node.\n**Reading it:** Lower is better; reveals which types are most expensive to execute.\n**Healthy range:** Sub-millisecond to a few ms for most types; workload-dependent.\n**Watch for:** A type whose execution time grows, indicating expensive logic or ledger contention.\n**Source:** src/libxrpl/tx/Transactor.cpp:Transactor::operator()",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -440,7 +440,7 @@
},
{
"title": "Tx Apply Pipeline Rate by Stage",
"description": "Span rate for each apply-pipeline stage (preflight, preclaim, apply). A drop between stages shows where transactions are filtered out. Requires the stage dimension in spanmetrics.",
"description": "**What:** How many transactions pass through each apply-pipeline stage (preflight, preclaim, apply) per second.\n**How it's computed:** Per-second rate over 5 minutes, grouped by pipeline stage and node.\n**Reading it:** Stages should step down slightly as invalid transactions are filtered out.\n**Healthy range:** Workload-dependent; preflight highest, apply lowest.\n**Watch for:** A large drop between stages, showing where most transactions are being rejected.\n**Source:** src/libxrpl/tx/applySteps.cpp:makeStageSpan; src/libxrpl/tx/Transactor.cpp:Transactor::operator()",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -486,7 +486,7 @@
},
{
"title": "Tx Apply Pipeline Latency by Stage (p95)",
"description": "95th-percentile duration of each apply-pipeline stage. Isolates which stage (preflight, preclaim, apply) dominates transaction processing time.",
"description": "**What:** The 95th-percentile duration of each apply-pipeline stage.\n**How it's computed:** 95th-percentile of per-stage durations over 5 minutes, grouped by stage and node.\n**Reading it:** Lower is better; isolates which stage dominates processing time.\n**Healthy range:** Each stage typically sub-millisecond to a few ms; workload-dependent.\n**Watch for:** One stage's latency rising, pinpointing the bottleneck in transaction handling.\n**Source:** src/libxrpl/tx/applySteps.cpp:makeStageSpan; src/libxrpl/tx/Transactor.cpp:Transactor::operator()",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -532,7 +532,7 @@
},
{
"title": "Tx Apply Pipeline Failure Rate by Stage",
"description": "Rate of apply-pipeline spans whose ter_result is not tesSUCCESS, split by stage. Shows whether failures concentrate in preflight, preclaim, or apply. Filters on ter_result rather than span status because a failing ter code completes the span normally; only thrown exceptions set an error status.",
"description": "**What:** How many transactions fail at each apply-pipeline stage per second.\n**How it's computed:** Per-second rate of non-success outcomes over 5 minutes, grouped by stage and node.\n**Reading it:** Shows whether rejections concentrate in preflight, preclaim, or apply.\n**Healthy range:** Workload-dependent; a modest background of expected rejections is normal.\n**Watch for:** A failure spike concentrated in one stage, consistent with malformed or spam submissions.\n**Source:** src/libxrpl/tx/applySteps.cpp:makeStageSpan; src/libxrpl/tx/Transactor.cpp:Transactor::operator()",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -578,7 +578,7 @@
},
{
"title": "Tx Apply Pipeline Latency by Type and Stage (p95)",
"description": "95th-percentile duration broken down by both transaction type and apply-pipeline stage. Shows, for each transaction type, which stage (preflight, preclaim, apply) dominates its latency. Higher cardinality than the by-stage view; filter with the $tx_type and $stage variables.",
"description": "**What:** The 95th-percentile stage duration broken down by both transaction type and pipeline stage.\n**How it's computed:** 95th-percentile durations over 5 minutes, grouped by type and stage; higher cardinality than the by-stage view.\n**Reading it:** Lower is better; shows which stage dominates each type's latency.\n**Healthy range:** Workload-dependent; most type/stage pairs sub-millisecond to a few ms.\n**Watch for:** A specific type/stage combination rising sharply, pinpointing a costly path.\n**Source:** src/libxrpl/tx/applySteps.cpp:makeStageSpan; src/libxrpl/tx/Transactor.cpp:Transactor::operator()",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -624,7 +624,7 @@
},
{
"title": "Transaction Apply Duration per Ledger",
"description": "p95 latency of applying the consensus transaction set to a new ledger. The tx.apply span (BuildLedger.cpp) wraps the applyTransactions() function that iterates through the CanonicalTXSet and applies each transaction to the OpenView. Long durations indicate heavy transaction sets or expensive transaction processing.",
"description": "**What:** The 95th-percentile time to apply the agreed transaction set into each new ledger.\n**How it's computed:** 95th-percentile of transaction-apply durations over 5 minutes, per node.\n**Reading it:** Lower is better; a major component of ledger build time.\n**Healthy range:** A few to tens of milliseconds; scales with transactions per ledger.\n**Watch for:** Rising durations during heavy or expensive transaction sets.\n**Source:** src/xrpld/app/ledger/detail/BuildLedger.cpp:applyTransactions",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -665,7 +665,7 @@
},
{
"title": "TxQ Enqueue Rate by Transaction Type",
"description": "Rate of txq.enqueue spans broken down by transaction type (tx_type). Shows what share of inbound demand is Payment vs OfferCreate vs other transactors, and how the mix shifts as the queue fills. A spam burst of one type is a leading indicator of fee escalation.",
"description": "**What:** How many transactions are queued (rather than applied immediately) per second, by type.\n**How it's computed:** Per-second rate of queue-enqueue operations over 5 minutes, grouped by transaction type and node.\n**Reading it:** Shows the demand mix hitting the queue and how it shifts as the queue fills.\n**Healthy range:** Workload-dependent; low or zero when the network is not congested.\n**Watch for:** A spam burst of one type, an early indicator of fee escalation.\n**Source:** src/xrpld/app/misc/detail/TxQ.cpp:TxQ::apply",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -706,7 +706,7 @@
},
{
"title": "TxQ Accept Status",
"description": "TxQ accept outcomes: applied (included in ledger), failed (removed), retried (kept for next round).",
"description": "**What:** The outcome of queued transactions when the queue drains into a ledger: applied, failed, or retried.\n**How it's computed:** Counts of queue-accept outcomes over the window, split by status and shown as proportions.\n**Reading it:** A high applied share is healthy; retries indicate the transaction stayed queued.\n**Healthy range:** Workload-dependent; applied should dominate when not congested.\n**Watch for:** A rising failed or retried share, indicating queue pressure or under-bidding.\n**Source:** src/xrpld/app/misc/detail/TxQ.cpp:TxQ::accept",
"type": "piechart",
"gridPos": {
"h": 8,
@@ -744,7 +744,7 @@
},
{
"title": "Queue Bypass Ratio (Direct Apply vs Enqueue)",
"description": "Ratio of transactions that applied directly to the open ledger (txq.apply_direct) versus those that had to be queued (txq.enqueue). A falling bypass ratio is the cleanest single signal the network has entered sustained fee escalation.",
"description": "**What:** The fraction of transactions that applied straight to the open ledger instead of being queued.\n**How it's computed:** Direct-apply rate divided by direct-apply plus enqueue rate over 5 minutes, per node.\n**Reading it:** Higher is better; near 1.0 means the network is not congested.\n**Healthy range:** Close to 1.0 when not congested; falls as demand exceeds capacity.\n**Watch for:** A falling ratio, the cleanest single signal the network has entered sustained fee escalation.\n**Source:** src/xrpld/app/misc/detail/TxQ.cpp:TxQ::tryDirectApply; src/xrpld/app/misc/detail/TxQ.cpp:TxQ::apply",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -785,7 +785,7 @@
},
{
"title": "Queue Accept (Drain) Duration per Ledger",
"description": "p95 duration of the txq.accept span, which drains queued transactions into a newly closed ledger. Rising drain time signals queue pressure at ledger close.",
"description": "**What:** The 95th-percentile time to drain queued transactions into a newly closed ledger.\n**How it's computed:** 95th-percentile of queue-drain durations over 5 minutes, per node.\n**Reading it:** Lower is better; rising time signals queue pressure at ledger close.\n**Healthy range:** A few milliseconds when the queue is light; workload-dependent.\n**Watch for:** A sustained climb, indicating a large or contended queue slowing ledger close.\n**Source:** src/xrpld/app/misc/detail/TxQ.cpp:TxQ::accept",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -826,7 +826,7 @@
},
{
"title": "Queue Cleanup Rate (Expired Entries)",
"description": "Rate of txq.cleanup spans, which remove expired transactions from the queue each ledger. A rising rate means submitters under-bid the escalating fee and abandoned their transactions \u2014 a demand-frustration signal distinct from acceptance throughput.",
"description": "**What:** How often expired transactions are removed from the queue each ledger, per second.\n**How it's computed:** Per-second rate of queue-cleanup operations over 5 minutes, per node.\n**Reading it:** Low is healthy; a rising rate means submitters are abandoning transactions.\n**Healthy range:** Near zero when not congested; workload-dependent.\n**Watch for:** A rising rate, a demand-frustration signal where submitters under-bid the escalating fee and gave up.\n**Source:** src/xrpld/app/misc/detail/TxQ.cpp:TxQ::processClosedLedger",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -933,7 +933,7 @@
{
"name": "node",
"label": "Node",
"description": "Filter by rippled node (service.instance.id \u2014 e.g. Node-1)",
"description": "Filter by rippled node (service.instance.id e.g. Node-1)",
"type": "query",
"query": "label_values(traces_span_metrics_calls_total, exported_instance)",
"datasource": {
@@ -1050,5 +1050,6 @@
},
"title": "Transaction Overview",
"uid": "xrpld-transactions",
"refresh": "5s"
"refresh": "5s",
"description": "Transaction flow through this node: receipt, processing, results, per-stage timing, and queue behavior."
}