feat(telemetry): add peer-supply, serve and amendment diagnostics (WP-A7)

Whether the network can even serve this node, and whether the node is
about to be shut out of validation, were both invisible:

- peer_ledger_supply: how many connected peers advertise a range covering
  the sequence being fetched. Peers each track a range from status
  changes, but nothing aggregated them, so "nobody has what I need" looked
  identical to "peers are slow".
- peerfinder_slot_census: outbound active against capacity, connection
  attempts, inbound, fixed configured against active, and the bootcache
  and livecache sizes. All were computed already; only two were exported,
  read at unrelated instants, so they could not be compared.
- peer_disconnect_total{reason,direction} and peer_accept_total{outcome}:
  every disconnect previously collapsed into one number, so our own
  backpressure could not be told from topology or network faults. Reasons
  are a fixed set of literals recorded on the peer and emitted once at
  close, never data supplied by the remote end.
- serve_refused_total{request,reason}: the other half of the sync
  exchange, when this node declines to serve a peer.
- amendment_block: whether an unsupported amendment is expected and how
  long until it activates. Amendment-blocked is terminal for validation,
  so the countdown is the only leading indicator. The amendment id is
  deliberately not a label, since the network can vote an id this build
  has never heard of; it is already logged.
- ledger_jump_total: repeated last-closed-ledger switches, which mean the
  node is thrashing between chains.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pratik Mankawde
2026-07-25 16:14:45 +01:00
parent 4115617eb9
commit e99370d433
9 changed files with 541 additions and 0 deletions

View File

@@ -2164,6 +2164,17 @@ NetworkOPsImp::switchLastClosedLedger(std::shared_ptr<Ledger const> const& newLC
// set the newLCL as our last closed ledger -- this is abnormal code
JLOG(journal_.error()) << "JUMP last closed ledger to " << newLCL->header().hash;
// This node was told the network's last closed ledger is not the one it
// built on, and is discarding its own chain tip to follow. Log-only until
// now, so a node repeatedly thrashing between chains left no time series
// to correlate against the rest of the sync pipeline. Rare event, one
// counter Add, no labels: the ledger hash and sequence would both be
// unbounded as label values, and the log line above already carries them.
XRPL_METRIC_COUNTER_INC(
registry_.get(),
"ledger_jump_total",
"Forced jumps of the last closed ledger to a divergent chain");
clearNeedNetworkLedger();
// Update fee computations.