Commit Graph

1105 Commits

Author SHA1 Message Date
Pratik Mankawde
f7e65949b8 Merge branch 'pratik/otel-sync-diagnostics' into pratik/otel-sync-diagnostics-freshen-fix 2026-09-22 21:31:17 +01:00
Pratik Mankawde
c8a4634cb4 Merge branch 'pratik/otel-phase10-workload-validation' into pratik/otel-sync-diagnostics
expected_spans.json kept both sides' relationship entries: this branch's
eight nodestore.rotate phase children and the upstream branch's three
cross-node pairs. Both sides appended at the same list position.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:31:09 +01:00
Pratik Mankawde
7272ea078c test(telemetry): Assert the cross-node span relationships
The harness checked parentage only within a node. Every declared
relationship named two spans from one process, so a receive span that
lost its cross-node parent still satisfied the contract: it is created
either way, with all its normal attributes, and only its parent differs.

Declare the three pairs that cross a node boundary, so a send side that
stops propagating context fails the run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:30:23 +01:00
Pratik Mankawde
ec9af37796 Merge branch 'pratik/otel-sync-diagnostics' into pratik/otel-sync-diagnostics-freshen-fix 2026-09-22 21:22:37 +01:00
Pratik Mankawde
881faf5620 Merge branch 'pratik/otel-phase10-workload-validation' into pratik/otel-sync-diagnostics
The runbook's nodestore_state table kept AppMetricGauges.cpp as the source
column, which is where those gauges are actually registered on every branch
in the chain; the incoming side named MetricsRegistry.cpp, which registers
none of them. Took the incoming side's clearer wording for the sweep row.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:19:08 +01:00
Pratik Mankawde
c381d05bb8 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-09-22 21:17:58 +01:00
Pratik Mankawde
aeac95b1d7 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-09-22 21:17:58 +01:00
Pratik Mankawde
fcdc4f9f66 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-09-22 21:17:58 +01:00
Pratik Mankawde
e48b0286c2 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics
StatsDCollector test kept both sides: this branch's onCollectionReady() call,
which enables polling and only exists from here on, followed by the upstream
branch's control assertion that reads the resulting datagram.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:17:48 +01:00
Pratik Mankawde
e9d9cffe3b Merge branch 'pratik/otel-phase5-docs-deployment' into pratik/otel-phase6-statsd
Both doc indexes kept this branch's 09-data-collection-reference.md rows,
which only exist here, and dropped every secure-OTel.md reference because
the upstream branch removed that file. No dangling link remains.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:16:44 +01:00
Pratik Mankawde
aea4f56505 Merge branch 'pratik/otel-phase3-tx-tracing' into pratik/otel-phase4-consensus-tracing
SpanGuardScope.cpp kept both includes: each side added one and both symbols
are used in the merged test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:15:05 +01:00
Pratik Mankawde
bba92767a6 Merge branch 'pratik/otel-phase2-rpc-tracing' into pratik/otel-phase3-tx-tracing
tempo.yaml kept both sides' filter blocks: phase-2's six path-finding
filters ahead of this branch's three transaction filters, matching chain
order, and both header comment lines.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 21:14:20 +01:00
Pratik Mankawde
3cfe8d139e feat(telemetry): Add Tempo search filters for the path-finding attributes
This branch emits nine pathfind attributes and the datasource offered a dropdown
for none of them, so the signal was there but not searchable in Explore. The
file's own header states that each phase adds filters for what it introduces.

Six filters, for the attributes that select a request. The three counts are
measurements read off a span rather than things an operator searches by, so they
get none. ledger_index is dynamic because it takes a new value every ledger.
2026-09-22 20:31:14 +01:00
Pratik Mankawde
68a805563f fix(telemetry): Reject a JSON reply or a weights argument that is not an object
Both workload scripts decoded JSON and went straight to .get() or .items().
An array or a scalar decodes fine and then raises AttributeError, which is not a
ValueError, so the handler around the weights parsing could not catch it and the
operator saw a traceback naming neither the command nor what arrived.

Four sites across the two files, all four guarded, and the weights handler now
also catches TypeError for a non-numeric weight value.

Negative weights are left alone: they do not raise, the type is dropped from the
mix silently, and changing that changes accepted input.
2026-09-22 20:30:53 +01:00
Pratik Mankawde
331a453c9d fix(telemetry): Read RPC success from the absence of an error, not from Ok
This board's own copy of the Success series selected status_code=STATUS_CODE_OK.
Successful rpc.command spans no longer carry Ok: the specification reserves it
for an operator asserting verified success and warns a tool may read it as
suppressing errors, so instrumentation leaves a successful span Unset.

The blob differs from phase-9's, so merging forward would not have corrected it.
2026-09-22 20:30:51 +01:00
Pratik Mankawde
c3673f51cd fix(telemetry): Read RPC success from the absence of an error, not from Ok
The Success series selected status_code="STATUS_CODE_OK". Successful
rpc.command spans no longer carry Ok, because the specification reserves it for
an operator asserting verified success and warns a tool may read it as
suppressing errors, so instrumentation leaves a successful span Unset.

Selecting on the absence of an error keeps the panel correct either way, rather
than pinning it to whichever status a successful span happens to have.
2026-09-22 20:15:18 +01:00
Pratik Mankawde
35c7f9be4c docs(telemetry): use a placeholder zone in the cloud env example
The example endpoint named a concrete zone, which reads as the stack this repo
pushes to. The two sibling files already write <zone>, so match them.
2026-09-22 19:09:16 +01:00
Pratik Mankawde
2d3eb7a981 fix(telemetry): Stop unl_expiry_days wrapping, and count only unfinished sweep evictions
unl_expiry_days subtracted two NetClock time points, whose rep is uint32_t, so
the subtraction wrapped before the duration_cast ran. A list expired by one day
read about +49709 days. The panel is green above 30 while its own description
promises red at expiry, so an expired validator list rendered healthy.

daysUntil() widens both endpoints to int64_t first, which makes the wrap
impossible rather than checked for. It deliberately does not clamp at zero: a
negative reading is the signal that expiry has passed. A config-listed list,
which uses time_point::max(), now reports positive infinity, because any finite
sentinel could not be told apart from the wrap this removes. -1 keeps its
existing meaning of no published list fetched.

The sweep counter told a second story it could not support. It counted every
entry the 1-minute sweep evicted, including acquisitions that had already
completed or failed and were merely still in the map. Those were counted when
they ended, so the metric buried the wasteful case in ordinary cleanup while
the runbook, the reference doc and the panel description all described only the
unfinished population. It now counts what those three already claimed.

isComplete()/isFailed() are used rather than isDone(), which is protected on
TimeoutCounter and not callable here.
2026-09-22 19:07:41 +01:00
Pratik Mankawde
cbed889f4b fix(telemetry): Accept every legitimate unl_expiry_days reading in the validator
The sanity bound required the value to be strictly positive, which rejected
three of the four readings the gauge can legitimately produce: a negative
count once the validator list has expired, the -1 sentinel for "no published
list fetched", and +inf for a config-listed list that never expires.

The negative case is the one that matters. It is the signal that expiry has
already passed, so the gauge deliberately does not clamp at zero, and a gate
that rejects it would fail exactly when an operator most needs the reading.
The -1 sentinel already violated the bound and had simply never been hit,
because the validation cluster always fetches a published list.

The floor is now a century, which still catches a broken clock. Detecting the
unsigned wrap this bound used to hide moves to the MetricsRegistry::daysUntil
unit tests, which are deterministic and do not need a running cluster.
2026-09-22 19:04:48 +01:00
Pratik Mankawde
f81ef31b0e Merge branch 'pratik/otel-sync-diagnostics' into pratik/otel-sync-diagnostics-freshen-fix 2026-09-22 15:43:12 +01:00
Pratik Mankawde
6b1ced940e Merge branch 'pratik/otel-phase10-workload-validation' into pratik/otel-sync-diagnostics 2026-09-22 15:43:12 +01:00
Pratik Mankawde
406e38275a Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-09-22 15:42:55 +01:00
Pratik Mankawde
e53569e696 fix(telemetry): Split the job queue p99 bargauge into wait and exec
The panel fused queue-wait and execution p99 into a single bargauge, so
every job type drew two bars and neither measure could be read on its
own. It is now two panels side by side, one measure each, with its own
title and description.

The panel also ran an instant query over a fixed 5 minute rate window.
An instant query always evaluates at "now", so the dashboard time picker
had no effect and a network with no samples in the last few minutes
rendered empty at every range. The window is now $__range, which ties it
to the picker.

Repeat direction is vertical. Horizontal repeat with maxPerRow set makes
Grafana widen each copy to the full row, which would break the pair.
2026-09-22 15:42:21 +01:00
Pratik Mankawde
b3eba92e27 Merge branch 'pratik/otel-sync-diagnostics' into pratik/otel-sync-diagnostics-freshen-fix 2026-09-22 15:17:36 +01:00
Pratik Mankawde
082cef20af Merge branch 'pratik/otel-phase10-workload-validation' into pratik/otel-sync-diagnostics 2026-09-22 15:14:08 +01:00
Pratik Mankawde
7be7274196 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-09-22 15:14:02 +01:00
Pratik Mankawde
e94e37b7c2 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-09-22 15:14:02 +01:00
Pratik Mankawde
87fad43d9a Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation
Conflict in docker/telemetry/docker-compose.yml, on the collector service's
command key. This branch layers a second --config for file_log offset
persistence; upstream added a comment above the ports block explaining the
loopback binding.

Kept both. The two changes are unrelated: one is the command list, the other is
a comment. The layered --config and all nine loopback-bound ports are present,
and the file still parses.
2026-09-22 15:13:54 +01:00
Pratik Mankawde
4308f967f3 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics
Conflict in docker/telemetry/docker-compose.yml, in the collector's ports
block. Upstream bound every port to the host loopback, including the StatsD
UDP port. This branch had already retired that port, because beast::insight
moved to native OTLP, leaving it commented out as a fallback example.

Not resolved as a union, which would have resurrected the retired port.
Composed instead: this branch's shape is kept, so StatsD stays commented, and
the loopback binding is applied to the active ports and to the commented
example, so uncommenting it yields the safe form.
2026-09-22 15:13:14 +01:00
Pratik Mankawde
18df80c5ec Merge branch 'pratik/otel-phase5-docs-deployment' into pratik/otel-phase6-statsd
Conflict in docker/telemetry/docker-compose.yml, in the collector's ports
block. Both sides bound ports to the host loopback: upstream did 4317, 4318
and 13133, this branch did 8125, 8889 and 9090.

Resolved as the union. All eight published ports are loopback-bound, and both
explanatory comments are kept: upstream's, which covers the whole block and
cites the upstream guidance, and this branch's, which is specific to the
unauthenticated StatsD receiver.
2026-09-22 15:12:32 +01:00
Pratik Mankawde
6ecd5f24a9 Merge branch 'pratik/otel-phase3-tx-tracing' into pratik/otel-phase4-consensus-tracing 2026-09-22 15:11:47 +01:00
Pratik Mankawde
0e1e335f42 Merge branch 'pratik/otel-phase2-rpc-tracing' into pratik/otel-phase3-tx-tracing 2026-09-22 15:11:47 +01:00
Pratik Mankawde
5a148ff55e Merge branch 'pratik/otel-phase1c-rpc-integration' into pratik/otel-phase2-rpc-tracing 2026-09-22 15:11:47 +01:00
Pratik Mankawde
4bf76ce2ff metrics_flush_interval = "15s"
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
2026-09-22 15:11:28 +01:00
Pratik Mankawde
6ed6189ba9 docs(telemetry): re-apply the comment rewrite lost to a concurrent commit
Commit 54809960ff removed the site measurements from the three collector
comment blocks, but a later commit on this branch was built from an index
holding the pre-rewrite blobs, so the tree reverted while the commit stayed in
the log. History is append-only, so this re-applies the same three blocks.

No non-comment line changes. The bucket lists are untouched and still agree
across the two collector configs and the Alloy config.
2026-09-22 15:07:10 +01:00
Pratik Mankawde
d3f9fa1f67 fix(telemetry): make the job latency panel readable at any time range
The gauge showed a p99 pooled across every job type, so a slow rare job could
not surface: sweep sat at 5 s while the dial read 20 ms, because a
count-weighted p99 follows the frequent jobs and those are fast.

It is now a bar gauge over per-job-type p99, which is what the panel is for,
and a bar gauge holds tens of values where a dial holds one. The series keep
job_type so each bar names its job.

max is set to the red threshold, so every bar shares one 0 to 1 s scale
instead of each dial auto-scaling to its own data.

The targets are instant queries. Left as range queries the bar count followed
the dashboard's time range rather than the current series count, reaching 531
series over a week.
2026-09-22 15:04:40 +01:00
Pratik Mankawde
54809960ff docs(telemetry): remove site measurements from the collector comments
The repo is public, so a comment must not carry one-site measurements or
claim a prior state of the source. Three comments did both.

The tail-sampling comment called itself "Box-only (uncommitted)", which names
our deployment and was untrue. It now states what the sampling does, and adds
the consequence that matters: Log.cpp writes a trace id only for a sampled
span, so sampling after that decision leaves log-to-trace links resolving to
nothing.

The histogram bucket comments justified each edge with measured percentages
and durations, and said what the buckets "used to" do. The mechanism is
unchanged and now stated without the figures. Also drops a duplicated line in
the Alloy copy. The bucket lists themselves are untouched and still agree
across all three files.
2026-09-22 15:00:30 +01:00
Pratik Mankawde
4758165aa4 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-sync-diagnostics-freshen-fix 2026-09-22 14:57:24 +01:00
Pratik Mankawde
e929a38e98 Merge branch 'pratik/otel-phase10-workload-validation' into pratik/otel-sync-diagnostics 2026-09-22 14:57:24 +01:00
Pratik Mankawde
d011a95a51 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-09-22 14:57:24 +01:00
Pratik Mankawde
a1b3b4486a docs(telemetry): stop tracking the validator list files
The two xrpld-telemetry configs name a file in [validators_file], and xrpld
exits at startup when that file is missing. Neither list ships now: each
developer creates their own from cfg/validators-example.txt.

The runbook says so in "Run against a live network", ahead of the run command.
2026-09-22 14:56:57 +01:00
Pratik Mankawde
5f44af7e2c Merge branch 'pratik/otel-sync-diagnostics' into pratik/otel-sync-diagnostics-freshen-fix 2026-09-22 14:07:19 +01:00
Pratik Mankawde
46ca2daf2f Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-09-22 14:07:04 +01:00
Pratik Mankawde
fb59dfc27a Merge branch 'pratik/otel-phase10-workload-validation' into pratik/otel-sync-diagnostics 2026-09-22 14:07:04 +01:00
Pratik Mankawde
39b7344380 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-09-22 14:07:04 +01:00
Pratik Mankawde
318fe0d10d Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-09-22 14:07:04 +01:00
Pratik Mankawde
2de992f334 fix(telemetry): give Ledger Data & Sync an auto-refresh interval
The dashboard had no top-level refresh key at all, so auto-refresh was off
while every other dashboard refreshes at 30s.
2026-09-22 14:07:02 +01:00
Pratik Mankawde
07ec48d717 fix(telemetry): point template variables at the datasource variable
Sixteen template variables named a datasource by the literal uid "prometheus"
or "loki". Neither exists on the Grafana instance, so those variables resolved
to nothing and their pickers offered only All.

That also broke the panels. With an empty variable the selector becomes
job_type=~"" rather than job_type=~".*", which matches no series, so the
Current Job Latency gauge had no data and its renderer raised the plugin error
banner on every refresh.

Every working dashboard already references ${DS_PROMETHEUS} or ${DS_LOKI},
which the dashboard declares in templating.list. These now match.

job-queue 6, ledger-data-sync 5, log-derived-insights 3, overlay-traffic-detail 2.
2026-09-22 14:06:49 +01:00
Pratik Mankawde
850ed7ec2e fix(telemetry): slow the Job Queue dashboard refresh to 30s
Every other dashboard refreshes at 30s. This one was at 5s, which re-ran all
of its queries twelve times a minute for no benefit.
2026-09-22 14:06:47 +01:00
Pratik Mankawde
74706020e8 docs(telemetry): drop the site figure from the rotation keep-policy comment
The comment stated a measured rotation interval. The repo is public, so a
one-site measurement belongs in an internal note, and it rots the day the
config changes. The reason for keeping every rotation trace is unchanged and
now stated without the number.
2026-09-22 13:58:33 +01:00