Commit Graph

15985 Commits

Author SHA1 Message Date
Pratik Mankawde
a30494fbbd docs(telemetry): align new panels with the dashboard conventions
The eight panels added for the GetObject and job-queue metrics did not
follow the conventions the rest of the dashboards use.

- Descriptions go from seven sections to the ten used by the other 159
  panels, adding Keywords, Computation boundary and References. The
  existing diagnostic guidance is kept; only the format changed.
- Six glossary entries added for the terms those References link to
  (concurrency limit, deferred job, handler label, NodeStore lookup
  hit/miss, resource charge), so no link is dead.
- displayName becomes `${series} ${xrpl_ident}`, the form 122 of 143
  panels use. This needs the label_join wrapper that builds xrpl_ident,
  which these queries lacked, so it is added to ten targets; without it
  the legend would render an unresolved label.
- Legend blocks now match each dashboard's own convention rather than
  being split three-with and four-without across the new panels.

Job Queue Wait Time and Job Execution Time dropped job_type from their
aggregation, so every queue collapsed into one line and the legend could
not say which queue was slow. Both now split by type, capped with topk
to stay readable, matching the per-type panel already on that dashboard.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 13:05:08 +01:00
Pratik Mankawde
9956b9b651 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation
Resolved five files. In each case both sides had content worth keeping,
so nothing was taken wholesale:

- MetricsRegistry.cpp: kept the incoming `handler` label on the job
  instruments and re-applied this branch's `queuedDurUs >= 0` guard,
  which the incoming side does not have.
- telemetry-runbook.md: took the incoming gauge table, which adds the
  three per-job-type rows, and re-applied this branch's corrected
  `jobq_job_count` name.
- 09-data-collection-reference.md: kept this branch's validation
  inventory (newer counts, extra Config File column) and inserted the
  incoming call-site and per-job-type gauge rows plus their explanation.
- node-health.json: merged structurally rather than by text. This
  branch's panels are authoritative; only the two incoming job-queue
  panels were appended, below the existing layout. The
  `Validated Ledger Seq` panels added directly in Grafana are preserved.
- job-queue.json, ledger-data-sync.json: panel sets were identical, so
  took the incoming side for its `$handler` variable, the handler filter
  on existing queries, and the new panels. Verified no panel was lost.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 12:06:29 +01:00
Pratik Mankawde
a27d4d65c5 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill
Resolved OpenTelemetryPlan/09-data-collection-reference.md: both sides
document the same new metrics, reached by different routes. The incoming
sections came from the phase-6 edit merged forward; this branch already
documents the same surface in its own layout, with the job lifecycle
metrics and the GetObject request path under the MetricsRegistry
section rather than a separate 2a.

Kept this branch's sections to avoid duplicate entries for every metric.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 12:03:02 +01:00
Pratik Mankawde
a8bfc6927c Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-25 12:02:03 +01:00
Pratik Mankawde
49d2edfe61 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics
Resolved OpenTelemetryPlan/09-data-collection-reference.md: this branch
replaced the StatsD-shaped Section 2 with OTel-native naming, so the
incoming StatsD tables and the StatsD per-job timer section do not apply
here. Kept this branch's names throughout.

The incoming per-job-type saturation gauge section is new content and is
retained, renumbered to 2.5 and rewritten for the OTel naming: bare
lowercase `jobq_<jobtype>_{waiting,running,deferred}` derived through
OTelCollector rather than the case-preserving `xrpld_`-prefixed StatsD
form.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 12:01:58 +01:00
Pratik Mankawde
15596f5b8d feat(telemetry): pinpoint root cause of slow TMGetObjectByHash service
Slowness on the peer object-fetch path could be observed but not
attributed. Job duration metrics carry only `job_type`, and both
`RcvGetLedger` and `RcvGetObjByHash` report as `ledgerRequest`, so a
queue-wait spike could not be traced to a handler. Nothing measured
NodeStore cost, request size, or the differential charge.

Latency now decomposes into three additive parts, each separately
measurable:

    end-to-end = queue wait + NodeStore lookup + everything else

- `handler` label on job_queued_total/_started_total/_finished_total and
  job_queued_us/job_running_us. The value is sanitised: a name passes
  through only if non-empty and all ASCII letters, else "other". Two job
  names embed a ledger sequence, so a raw label would mint one series
  per ledger; the rule bounds the domain at 43 names plus "other".
- getobject_lookup_us, _request_objects, _lookups_total{result},
  _rejected_total{reason} and _charge, recorded at their call sites.
  All three histograms get explicit bucket views: the SDK default stops
  at 10,000, which every one of them exceeds.
- Per-job-type waiting/running/deferred gauges for the 35 non-special
  job types. `deferred` is the leading indicator, since addJob never
  rejects -- it defers, so backpressure otherwise shows up only as
  latency after the fact.

`JobQueue::collect()` snapshots the counters under the queue lock and
publishes gauges after releasing it. Writing them while holding the lock
would invert a lock order against the collector's own lock, which the
collector's flush thread already holds when it calls this hook.

Tests assert exact values, including that the charge is priced on the
requested count rather than the capped iteration count.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 11:59:16 +01:00
Pratik Mankawde
6768aa4c07 docs(telemetry): document handler label, GetObject and queue-saturation metrics
Add reference entries for the observability surface introduced on
phase-9: the `handler` label on the job instruments, the five
`getobject_*` request metrics, and the per-job-type queue saturation
gauges.

Names here follow this branch's StatsD pipeline, which preserves case
and carries the `xrpld_` prefix, so they differ from the lowercased
OTel-native names used from phase-7 onward. The sections state where
the implementing code lives, since it is introduced downstream.

Also correct pre-existing entries: `job_count` exports as
`jobq_job_count` via the collector group prefix, the non-special job
type count is 35 (not 36), and `JtLedgerData` has five producers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 11:58:16 +01:00
Pratik Mankawde
69c3bb5bdf Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-24 21:06:31 +01:00
Pratik Mankawde
3cf24e1888 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 21:06:30 +01:00
Pratik Mankawde
92fc2daff6 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 21:06:30 +01:00
Pratik Mankawde
8fe00536e7 fix(telemetry): Size the overlay traffic bar gauge for 20 bars
Match the panel height the operator settled on in Grafana (18 rows) so
all 20 ranked bars render without an inner scrollbar, and reflow the
Sync Diagnostics row and the panels below it accordingly.
2026-07-24 21:06:20 +01:00
Pratik Mankawde
bbc318fb6d Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation
# Conflicts:
#	docker/telemetry/grafana/dashboards/ledger-data-sync.json
2026-07-24 21:03:26 +01:00
Pratik Mankawde
8f09dc2906 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 21:02:43 +01:00
Pratik Mankawde
fe1c4db29c Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 21:02:39 +01:00
Pratik Mankawde
97ed918e16 fix(telemetry): Make overlay traffic bar-gauge labels readable
The bar labels on 'Overlay Traffic Heatmap (All Categories, Bytes In)'
were raw metric names carrying a redundant '_bytes_in' suffix, and the
half-width 8-row panel truncated both the category and the node
identity.

- Strip the '_bytes_in' suffix from the derived series label; the panel
  title already states the metric is inbound bytes.
- Widen the panel to full width and grow it to 12 rows so 20 bars render
  with their full category and node labels.
- Shift the Sync Diagnostics row and the panels below it down by 4 to
  keep the layout gap-free.
- Note the label derivation in the panel description.
2026-07-24 21:02:31 +01:00
Pratik Mankawde
ffeb82ab63 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation
# Conflicts:
#	docker/telemetry/grafana/dashboards/node-health.json
2026-07-24 20:51:15 +01:00
Pratik Mankawde
9c54020322 fix(telemetry): plot all five states in State Duration Rate panel
The panel plotted only Full and Tracking, so the states a node actually
passes through while catching up were invisible. On the dev box's cold
sync the node spent ~19 minutes in Connected and ~3 seconds in Syncing,
while Tracking totalled 2 microseconds -- the one non-Full line the
panel did draw was the least informative of the five.

Add Syncing, Connected and Disconnected series (state-ladder order,
matching the Operating Mode Transitions panel) and rename the panel to
"State Duration Rate (All States)". Because the node is always in
exactly one state, the five rates sum to ~1.0, so the panel now reads as
"which state is time going into right now", and a handover between two
lines marks a state change with its width showing the dwell time.

Description expanded to the full section set (keywords, computation
boundary, references) used by the other panels on this dashboard.

Verified live: rate(state_accounting_connected_duration)/1e6 reaches
1.0 then 0.387 across the catch-up window and syncing reaches 0.0103 --
both previously undrawable.
2026-07-24 20:50:39 +01:00
Pratik Mankawde
3eae98fa85 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation
# Conflicts:
#	docker/telemetry/grafana/dashboards/node-health.json
2026-07-24 20:45:29 +01:00
Pratik Mankawde
0d9533270a Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 20:44:27 +01:00
Pratik Mankawde
b0168f92a7 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 20:44:23 +01:00
Pratik Mankawde
a80cccb05a feat(telemetry): add Node Health verdict panel to Node Health dashboard
The dashboard showed 54 individual signals but no single answer to
"is this node healthy and doing its job?". A reader had to correlate
server state, ledger age and peer counts by eye.

Add a stat panel at the top that reduces the two conditions that define
a healthy observer node to one green/red verdict:

  server_state == 4 (Full)  AND  validated_ledger_age < 30s

Both terms use `== bool` so each yields 0/1, joined with
`* on(service_instance_id)` so the verdict is per node. Value mappings
render 1 as "Healthy" (green) and 0 as "Not Healthy" (red) with
background colouring, so the state is readable at a glance.

Placed at y=0 per the dashboard convention that gauges/stats lead;
existing panels shift down by 4 rows with no other change.

Verified live against Grafana Cloud: returns 1 for aws-dev-xrpl-1
(Full, validated seq 105,824,596).
2026-07-24 20:44:23 +01:00
Pratik Mankawde
a30c08240b fix(telemetry): drop xrpl_work_item from Sync Diagnostics sum-by clauses
The four aggregated Sync Diagnostics panels grouped by xrpl_work_item,
which no layer in this repo emits (it is injected by the perf-iac
harness). That tripped Rule D of the telemetry naming check:

  D  ledger-data-sync.json  xrpl_work_item
     must exist in L1, a metric label, or be a builtin

Align with the convention used by every other aggregated panel in the
dashboard set: group by (service_instance_id, xrpl_branch,
xrpl_node_role) and leave the xrpl_ident label_join untouched. The
legend is unaffected -- label_join over a label dropped by the
aggregation contributes an empty segment, which the trailing
label_replace already strips.

Verified live: both the NuDB ratio and the job-queue p95 queries still
return per-node series rendering as "[aws-dev-xrpl-1]".
2026-07-24 20:44:13 +01:00
Pratik Mankawde
6cd2d3f280 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-24 19:57:13 +01:00
Pratik Mankawde
75cc3785ad Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 19:57:13 +01:00
Pratik Mankawde
63474c510d Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 19:57:13 +01:00
Pratik Mankawde
5533dde43d fix(telemetry): Sync State axis label "State (0-4)" -> "Server State"
The 0-4 values now render as named states via value mappings, so the numeric
axis label is misleading. Rename to "Server State".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 19:57:11 +01:00
Pratik Mankawde
5bc49683a5 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-24 19:51:37 +01:00
Pratik Mankawde
5718ebbdd6 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 19:51:37 +01:00
Pratik Mankawde
8f8ce40a21 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 19:51:36 +01:00
Pratik Mankawde
ecfaab9f85 feat(telemetry): map Sync State 0-4 to named states with threshold colors
Add value mappings (0 Disconnected, 1 Connected, 2 Syncing, 3 Tracking,
4 Full) and matching red->green thresholds to the Sync State panel, so the
line, tooltip, and legend render state names and colors instead of bare 0-4.
Keeps the minimal custom-key convention; only the Sync State panel changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 19:51:25 +01:00
Pratik Mankawde
cab0bc4f7d Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-24 19:26:23 +01:00
Pratik Mankawde
3c9935c0df Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 19:26:14 +01:00
Pratik Mankawde
e8aac409be Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 19:26:06 +01:00
Pratik Mankawde
794b5f43eb style(telemetry): align Sync Diagnostics legends with dashboard xrpl_ident format
Rework the 10 Sync Diagnostics panels' legends to match the format used by the
existing panels: wrap each query in label_join + label_replace to build the
xrpl_ident label ([service_instance_id, xrpl_branch, xrpl_work_item] with empty
values stripped) and set displayName to "${series} ${xrpl_ident}". Verified
against a live node: renders as "Series [aws-dev-xrpl-1]" with no empty-label
gaps, identical mechanism to the original 15 panels. Only the new panels change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 19:25:54 +01:00
Pratik Mankawde
c1dcb9b218 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation
# Conflicts:
#	docker/telemetry/grafana/dashboards/ledger-data-sync.json
2026-07-24 18:57:07 +01:00
Pratik Mankawde
c7243b57b5 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 18:54:59 +01:00
Pratik Mankawde
c0daf55f59 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 18:54:52 +01:00
Pratik Mankawde
eba21104c0 feat(telemetry): add Sync Diagnostics panels to Ledger Data & Sync dashboard
Add a 10-panel "Sync Diagnostics" row that shows ledger-sync slowdown and its
causes, laid out top-to-bottom as symptom -> latency -> root cause:

- Red flags: Sync State, Validated Ledger Age, Ledger Close Rate
- Latency: Job Queue Wait p95 by type, NuDB Read Latency, I/O Scheduler p95
- Root cause: NuDB Cache Hit Ratio, NuDB Read Pressure, Job Queue Depth,
  Load Factor & Peers

All panels use native beast::insight metrics introduced on this branch
(nodestore_state, ledgermaster_*, jobq_*_q, ios_latency, load_factor_metrics,
peer_finder_*) plus the consensus.mode_change span metric. Queries filter by
the dashboard's $node and tier variables and were verified against a live
node. Nodestore ratio panels use sum-by(identity) matching to bridge the
metric= sub-label.

Format matches the dashboard convention: minimal custom keys, ${DS_PROMETHEUS}
datasource uid, and the standard What/How/Reading/Healthy/Watch/Source/Function
description structure. Pure-append; existing panels untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 18:53:53 +01:00
Pratik Mankawde
694062d8fd Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-24 16:15:41 +01:00
Pratik Mankawde
2d7f3792bf Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill
# Conflicts:
#	docs/telemetry-runbook.md
2026-07-24 16:15:27 +01:00
Pratik Mankawde
380a7160c6 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-24 16:14:30 +01:00
Pratik Mankawde
dee90b7c01 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics
# Conflicts:
#	OpenTelemetryPlan/09-data-collection-reference.md
2026-07-24 16:14:16 +01:00
Pratik Mankawde
21d9b2f8f9 docs(telemetry): add current_ledger_seq/hash to 09 attribute inventory
Document the two new ledger-correlation attributes in the data-collection
reference: add them to the transaction and TxQ attribute tables (with per-span
coverage), update the attribute count, and correct the txq.enqueue parent note
(parents to tx.process on the submission path via explicit context; a root on
the open-ledger rebuild path, correlated via current_ledger_seq).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 16:11:18 +01:00
Pratik Mankawde
944a8df1c0 Merge branch 'pratik/otel-phase5-docs-deployment' into pratik/otel-phase6-statsd
# Conflicts:
#	docs/telemetry-runbook.md
2026-07-24 16:10:11 +01:00
Pratik Mankawde
17a1e1b142 docs(telemetry): document current_ledger_seq correlation in runbook
Add current_ledger_seq / current_ledger_hash to the tx.process, tx.receive,
and txq.enqueue span-reference rows, correct the txq.enqueue parent note
(parents to tx.process on the submission path via explicit context; a root on
the open-ledger rebuild path), and add a "Correlating a transaction to the
ledger it was worked on" recipe joining the txID-keyed tx/txq spans to the
ledger trace via current_ledger_seq.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 16:08:41 +01:00
Pratik Mankawde
7338ed8feb Merge branch 'pratik/otel-phase4-consensus-tracing' into pratik/otel-phase5-docs-deployment 2026-07-24 16:07:14 +01:00
Pratik Mankawde
ffa782ca96 Merge branch 'pratik/otel-phase3-tx-tracing' into pratik/otel-phase4-consensus-tracing
# Conflicts:
#	include/xrpl/telemetry/SpanNames.h
2026-07-24 16:07:03 +01:00
Pratik Mankawde
fb76c43307 feat(telemetry): correlate tx spans to the ledger being worked on
Add shared current_ledger_seq / current_ledger_hash span attributes so a
transaction's work can be joined to the ledger trace that produced it, and
fix discrepancy D1 (txq.enqueue was a detached trace root).

- Define current_ledger_seq / current_ledger_hash once in SpanNames.h and
  re-export via `using` from TxQ/TxApply/Tx span-name headers. These name the
  ledger being worked on (open/tentative apply or in-flight consensus build),
  distinct from ledger_seq (the built/validated ledger on ledger.build /
  consensus.round). Named after the RPC field ledger_current_index.
- txq.enqueue: set current_ledger_seq/hash from the view, and parent the span
  to the caller's tx.process span via an explicit captured SpanContext (new
  trailing TxQ::apply param) instead of a detached root. The parent is
  explicit, not ambient-inherited, and the ScopedSpanGuard scope is RAII-bound
  to the synchronous apply, so it cannot leak onto a reused worker (D1 fix).
  On the open-ledger rebuild path no tx.process context exists, so it stays a
  root and the attribute provides the correlation.
- tx.preclaim / tx.transactor: set both attributes from their ledger view.
  tx.preflight is stateless (no view) and is the documented exception.
- tx.process / tx.receive: set current_ledger_seq from the current open ledger
  index at submit/receive time (no hash: not yet applied to a ledger).
- Contract test pins the two new attribute key strings.

Neither key is a spanmetrics dimension, so there is no metric-cardinality
impact. Dashboards/collector/docs land on the later phases per the chain split.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 16:03:42 +01:00
Pratik Mankawde
98077347fd Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-24 15:34:31 +01:00
Pratik Mankawde
e1e175cc88 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-24 15:34:31 +01:00