Commit Graph

415 Commits

Author SHA1 Message Date
Pratik Mankawde
827525c86b feat(telemetry): wire A5-A7 and B1 signals through the pipeline
Registers the new gauges, renders them, asserts them and documents them, so
each signal reaches an operator rather than stopping at the emit site:

- MetricsRegistry: gauge registration for ledger_quorum_publish,
  nodestore_latency, peer_ledger_supply, peerfinder_slot_census and
  amendment_block, each guarded by the detached-callbacks check and
  tolerant of services that are not ready yet.
- Ledger Sync Health dashboard: panels for the new signals, filtered by
  the node template variable like every other board.
- Workload validation: the new series are asserted, so a signal that
  regresses to absent fails CI. Signals the local cluster structurally
  cannot produce, such as a replay fallback or an amendment block, are
  noted rather than asserted, which would fail red on a healthy run.
- Reference, runbook and glossary entries, including the diagnosis order
  for a node that has peers and validators but never validates.
- Regenerated levelization baseline: three new one-way edges from the
  telemetry and test modules, no new cycles.

Also drops an unused cstddef include from the macro tests, which the
include checker rejects.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 16:15:26 +01:00
Pratik Mankawde
4115617eb9 feat(telemetry): add job-queue occupancy and saturation gauges (WP-A4)
Sync-critical job types run at very low concurrency limits (ledgerRequest
and ledgerData allow 3 each), so a node can stall simply because those
jobs are held back behind other work. Nothing exposed that until now:
the existing job metrics are rates and quantiles of jobs that already
moved, or a single queue-wide depth.

- jobq_backlog{metric,job_type}: instantaneous waiting, running and
  deferred counts per job type. Deferred is the starvation signal and had
  no exposure anywhere; it is set when a type is at its concurrency limit.
- jobq_saturation{metric}: running tasks, worker-thread count and total
  waiting, so a slowdown spanning several subsystems can be attributed to
  worker-pool exhaustion instead of being diagnosed once per victim.

Both read through two new const accessors on JobQueue that take the
existing mutex once and copy integers, so a single reading is internally
consistent and no per-job cost is added. The job_type label reuses the
same JobTypes name helper the existing job counters use, so the two label
sets join.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 13:46:03 +01:00
Pratik Mankawde
3e2a1ea958 feat(telemetry): add ledger-acquire and SHAMap fetch diagnostics (WP-A3)
Signals that separate a sync that is merely slow from one that will never
finish:

- sync_acquire{missing_state_nodes_max, missing_tx_nodes_max, in_flight,
  received_data_depth}: how many SHAMap nodes each in-flight acquire is
  still waiting for. getMissingNodes already computed this and the callers
  discarded it after a trace log. A count that stays flat means the
  acquire is wedged; a shrinking count means it is progressing. Recorded
  once per sweep, never inside the per-node walk, and reset when a tree
  completes so a finished acquire does not read as stuck forever.
- shamap_cache_hit_rate{treenode}: hit rate of the in-memory tree-node
  cache, which sits above the node store, so it is distinct from the
  existing NuDB ratio. A cold cache on a fresh node sends every traversal
  step to disk.
- sync_acquire_no_progress_total: timer ticks where an acquire made no
  progress, previously only logged.
- sync_addnode_total{good,duplicate,invalid}: whether arriving nodes are
  useful, duplicated or rejected, so wasted fetch work is visible.
- sync_acquire_source_total{local,network}: whether a ledger was served
  from the local store or had to be fetched.

Adds getBad()/getDuplicate() to SHAMapAddNode and an acquireProgress()
accessor on InboundLedgers so the xrpld gauge can read these without
libxrpl depending on telemetry.

ledger_seq is deliberately not a metric label: it is unbounded. Per-ledger
identity stays on the ledger.acquire span; the metrics expose bounded
aggregates instead.

The full-below cache hit rate is not exported: KeyCache updates different
counters than getHitRate() reads, so it would always report zero. That
libxrpl bug is documented rather than papered over.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 10:18:08 +01:00
Pratik Mankawde
7c7509d01f feat(telemetry): add sync-state diagnostics (WP-A2)
Five signals that explain why a node is not advancing toward full, none of
which were observable before:

- state_changes_total now carries {from,to} mode labels, emitted at
  setMode using the existing strOperatingMode helper. A bare count could
  not distinguish a healthy climb from a node flapping between tracking
  and connected. Removes the now-unused incrementStateChanges wrapper.
- sync_state{initial_full_duration_us}: time to first reach full, which
  StateAccounting already computed but exposed only in server_info.
- sync_state{network_ledger_gate}: whether the node is still refusing to
  build ledgers because it has no network ledger.
- sync_state{server_stall_seconds} and server_stall_events_total: how
  long the main thread has been unresponsive. LoadManager computed this
  and only logged it, so a stall was invisible until the fatal threshold.
  The episode rule is a pure function so it can be tested without adding
  a test-only mutator to LoadManager.
- sync_state{ledgers_behind}: how far our validated sequence trails the
  best sequence any peer advertises, read from already-cached peer ranges
  so no extra network traffic is added.

Also fixes the naming checker: it derived only the first label of a
multi-label instrument, so a dashboard querying the second label was
wrongly rejected.

Note: the clang-tidy hook cannot run in this worktree (no build
directory); the remaining pre-commit hooks, the naming check, dashboard
schema and harness syntax all pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 09:02:03 +01:00
Pratik Mankawde
188de0a5f3 feat(telemetry): add pre-quorum bootstrap sync diagnostics (WP-A1)
A freshly started node most often stalls before it ever peers or reaches
quorum, and that whole chain had no telemetry. Adds the six signals that
make it observable:

- dns_resolve_total / dns_resolve_latency_ms: configured-peer hostname
  resolution, emitted from OverlayImpl so libxrpl stays independent.
- overlay_connect_total / overlay_dial_latency_ms: outbound dial outcome
  by terminal reason, plus dial duration.
- handshake_negotiation_fail_total: protocol and network-id negotiation
  rejections, labelled by reason, so a misconfigured network is no longer
  indistinguishable from unreachable peers.
- unl_fetch_total and the unl_quorum gauge: validator-list fetch outcome
  per site and trusted key count against the required quorum. Without
  these a bad validators.txt leaves the node syncing forever with no
  signal.
- clock_close_offset_seconds: network close-time offset, which server_info
  hides below 60s but which stalls consensus participation.

Panels land in the Bootstrap row of the Ledger Sync Health dashboard, the
metrics are asserted by the workload validator, and both the reference and
the runbook flow describe them.

Levelization baseline regenerated: overlay now includes MetricMacros.h, so
the overlay/telemetry pair is reported one-way instead of bidirectional.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 07:53:20 +01:00
Pratik Mankawde
96914b9f40 feat(telemetry): scaffold fresh-node sync diagnostics (WP-A0)
Adds the anchors the sync-diagnostics signals attach to, with no signals
emitted yet:

- New "Ledger Sync Health" dashboard (uid ledger-sync-health) with the
  standard template-variable block copied from an existing board, plus
  empty "Bootstrap (Domain 0)" and "Sync pipeline" rows.
- Signal index section in the data-collection reference, an operator-flow
  stub in the telemetry runbook, and a glossary anchor.
- A sync_diagnostics group in expected_metrics.json and a matching
  assertion helper in validate_telemetry.py so CI fails when a signal
  regresses to absent.

Also registers the new dashboard uid with the harness so the board is
covered by validation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 21:06:05 +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
f0df68ae2e docs(telemetry): add protocol span-flow diagrams to runbook
Add a "Protocol Span Flow" section to the telemetry operator runbook: 8
Mermaid diagrams that map every OTel span onto the real xrpld control flow
and XRPL protocol order (verified against code and docs/consensus.md), for
use as the canonical key when linking the span hierarchy.

- Master overview, client/peer ingress, shared apply pipeline, consensus
  round, accept/build/finalize, and pathfinding/ledger-acquire side flows.
- Every node/branch is labelled with the span that represents that state or
  transition (or explicit "(no span)"); drops/abandons are marked terminal.
- Shows real loops, retries, recovery, and drop branches: multi-round
  consensus settling (avalanche threshold rounds + MovedOn/Expired retry with
  wrong-ledger recovery), 3-pass tx apply retry, TxQ cross-ledger retry,
  quorum-gated async validation with abandoned-ledger, ingress backpressure
  drops, and cross-node context propagation.
- Adds a divergence table noting where OTel span parenting does not match the
  real protocol flow (deterministic/hash trace-id roots, JtAccept/JtUpdatePf
  job hand-offs, sequential peer->consensus receive stages).

Replace the stale planning-era diagram in OpenTelemetryPlan/08-appendix.md
(which named spans that were never built) with a pointer to the runbook.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 19:42:13 +01:00
Pratik Mankawde
48a5aad91d Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation
Brings the coroutine-aware OTel context storage refactor forward to phase-10:
CoroAwareContextStorage + install, ScopedSpanGuard same-store assertion,
non-owning ScopedActivation, scoped rpc.command spans, tx/consensus/ledger
worker-body activation, coro-store-swap tests, and the M1/M2 hardening.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 23:16:18 +01:00
Pratik Mankawde
28a8ab144b feat(telemetry): correlate ledger.acquire outcome log via span activation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:58:17 +01:00
Pratik Mankawde
68bf633955 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill
Brings coroutine-aware context storage + tx/consensus worker-body activation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:48:16 +01:00
Pratik Mankawde
31f6eee983 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation
Brings coroutine-aware context storage + tx/consensus worker-body activation.
The coro-aware storage keeps Log.cpp's ambient-context trace-id stamping correct
across coroutine yields, so RPC/tx/consensus log lines stay trace-correlated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:47:45 +01:00
Pratik Mankawde
3d495f9622 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics
Brings coroutine-aware context storage + tx/consensus worker-body activation.
Resolved: Telemetry.cpp keeps both meterProvider_ (phase-7) and contextStorage_
(coro-aware); doc-09 keeps phase-7 structure and applies the pathfind.request →
rpc.command.<name> correction to phase-7's own PathFind section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:46:54 +01:00
Pratik Mankawde
e0c4272f5b docs(otel): coro-aware context storage; RPC/tx/consensus log correlation retained
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:40:13 +01:00
Pratik Mankawde
1fc65db139 docs(telemetry): rename Ripple->XRPL / rippled->xrpld in telemetry docs
The check-rename CI gate requires all prose/comment references to use the
new naming. Fix the four remaining occurrences ("Ripple epoch",
"rippled's doAccept") introduced by this branch's dashboard/glossary
commits. Comment- and doc-only; no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 15:05:29 +01:00
Pratik Mankawde
0e02a67e81 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-22 13:46:45 +01:00
Pratik Mankawde
dd96d8ad34 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-22 13:28:44 +01:00
Pratik Mankawde
dad2dc2acb Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-22 13:28:24 +01:00
Pratik Mankawde
cef7a8b16c Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics
# Conflicts:
#	OpenTelemetryPlan/09-data-collection-reference.md
2026-07-22 13:28:15 +01:00
Pratik Mankawde
2f627e8e8e docs(telemetry): 09-doc — pathfind.request parents to rpc.process, not rpc.command
Reflects the C1 fix: rpc.command.* stays unscoped (its dispatch wraps
doRipplePathFind which yields), so pathfind.request nests under rpc.process.
The request -> compute -> discover sub-tree nests correctly via ScopedSpanGuard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 13:12:55 +01:00
Pratik Mankawde
f52673b6c1 feat(telemetry): correct ledger-close-time derivation on dashboards
The "ledger close time" was mis-derived and partly un-queryable:

- Build vs Close Duration derived close time from the consensus.ledger_close
  span, which only wraps the onClose() prologue (~0.8ms live) — not the close.
  Repoint the close series to consensus.round (full round, live P95 ~4.8s).
- The network close-time value (close_time) lived only as a span attribute,
  un-queryable in Prometheus and unfit as a spanmetrics label (monotonic
  timestamp -> unbounded cardinality). Expose it as last_close_time on the
  existing server_info observable gauge (native gauge, no new instrument).
- Add a "Ledger Close Interval & Age" panel to ledger-operations and
  node-health: interval = 1/rate(ledgers_closed_total) (counter-based,
  scrape-independent); age = time() - (last_close_time + epoch_offset).

A gauge delta is deliberately NOT used for the interval — a timestamp gauge's
delta aliases to the scrape period, not the close cadence (verified live).
Guardrail comments in both collector configs record why close_time must never
become a spanmetrics dimension. Docs (09-reference) and the operator runbook
updated to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 12:23:21 +01:00
Pratik Mankawde
f78bc433b0 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-22 10:58:55 +01:00
Pratik Mankawde
eec3062c9c Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics 2026-07-22 10:58:50 +01:00
Pratik Mankawde
7bdc14eee5 docs(telemetry): 09-doc — deterministic roots are true roots; rootSpan->freshRoot
Document that deterministic-trace_id spans (tx.* apply pipeline, tx.process,
tx.receive, consensus.round) are now genuine trace roots with empty
parent_span_id via the custom DeterministicIdGenerator, superseding the old
synthetic-parent behavior that showed 'root span not yet received' in Tempo.
Also update the fresh-root note: peer entry spans use ScopedSpanGuard::freshRoot().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 10:58:35 +01:00
Pratik Mankawde
ce3d806310 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation
Brings the 09-data-collection-reference doc-sync (rpc_in_flight_requests entry)
forward from phase9.
2026-07-21 20:34:12 +01:00
Pratik Mankawde
42615355be docs(telemetry): add rpc_in_flight_requests to metric-surface reference (09-doc) 2026-07-21 20:33:56 +01:00
Pratik Mankawde
f569440bd5 Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-20 12:19:59 +01:00
Pratik Mankawde
de49319b31 Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-20 12:19:45 +01:00
Pratik Mankawde
6203e46e8d Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-20 12:19:37 +01:00
Pratik Mankawde
4908b82077 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics 2026-07-20 12:19:28 +01:00
Pratik Mankawde
56c03ff24e Merge branch 'pratik/otel-phase5-docs-deployment' into pratik/otel-phase6-statsd
# Conflicts:
#	src/xrpld/overlay/detail/PeerImp.cpp
2026-07-20 12:19:11 +01:00
Pratik Mankawde
777aa9b467 Merge branch 'pratik/otel-phase4-consensus-tracing' into pratik/otel-phase5-docs-deployment 2026-07-20 12:17:52 +01:00
Pratik Mankawde
c3b1f69ba8 Merge branch 'pratik/otel-phase3-tx-tracing' into pratik/otel-phase4-consensus-tracing
# Conflicts:
#	include/xrpl/telemetry/SpanGuard.h
#	src/xrpld/app/consensus/RCLConsensus.h
#	src/xrpld/consensus/ConsensusTypes.h
2026-07-20 12:10:44 +01:00
Pratik Mankawde
ea7f585337 fix(telemetry): root peer.validation.receive and peer.proposal.receive spans
These inbound peer-message entry points (kConsumer) used span(), which
inherits whatever span is active on the peer thread — including a leaked
tx.receive scope — so validations/proposals were wrongly nested under
unrelated transaction traces. rootSpan() starts a fresh trace root.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 22:24:52 +01:00
Pratik Mankawde
6c4e0e6ed4 fix(telemetry): detach tx.receive and tx.process spans before job hand-off
Both spans are moved into job-queue lambdas and destroyed on a worker
thread. Detaching on the origin thread pops the thread-local OTel Scope
there, so later spans on the peer/RPC thread no longer inherit these as a
leaked ambient parent. Trace_id/parent are unchanged (both are hashSpan).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 22:24:38 +01:00
Pratik Mankawde
225afa9fe6 docs(telemetry): document perf-iac dashboard filter variables
Document the three perf-iac filter template variables (xrpl_work_item,
xrpl_branch, xrpl_node_role) in the telemetry runbook and the data-collection
reference: what they filter, their example values, and that perf-iac stamps
them as resource attributes from its own alloy pipeline (absent outside
perf comparison runs, so the filters default to All). Also record perf as a
network value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 15:44:40 +01:00
Pratik Mankawde
7231d450a4 fix(telemetry): correct job_count/network-traffic queries, 10s refresh, dashboard layouts
Dashboard audit against the live datasource surfaced two broken panel queries
and applied UX polish across all 14 dashboards.

- node-health "Job Queue Depth": job_count -> jobq_job_count. The JobQueue
  collector is wrapped in group("jobq") (Application.cpp), so the registered
  job_count gauge is emitted with the jobq_ prefix; the panel queried the
  unprefixed name and returned nothing.
- network-traffic "Overlay Traffic by Category" + "All Traffic Categories":
  topk(N, rate({__name__=~".*_bytes_in"}[...])) errors on Mimir ("vector
  cannot contain metrics with the same labelset") because rate() drops
  __name__ and the many counters collapse. Replaced with an enumerated
  label_replace form that re-attaches __name__ per metric, preserving the
  {{__name__}} legend and per-series display-name overrides.
- All 14 dashboards: refresh set to 10s.
- peer-quality: each panel full screen width.
- validator-health: at most two panels per row (row headers preserved).
- docs: telemetry-runbook and 06-implementation-phases updated for the
  jobq_ prefix and the network-traffic query pattern.

Verified end-to-end against a local mainnet xrpld node feeding the local
stack: jobq_job_count returns data (old job_count empty), both network-traffic
exprs execute (old form reproduces the labelset error), and panels render
through the Grafana proxy. All 14 pass validate_dashboards.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 19:08:12 +01:00
Pratik Mankawde
2348fc56ee Merge branch 'pratik/otel-phase9-metric-gap-fill' into pratik/otel-phase10-workload-validation 2026-07-10 18:49:24 +01:00
Pratik Mankawde
505dd360ee Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill 2026-07-10 18:49:14 +01:00
Pratik Mankawde
e9a0b49c5b Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-10 18:49:05 +01:00
Pratik Mankawde
cb413c18d3 docs(telemetry): correct jq_trans_overflow_total to ObservableCounter in 09-doc
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 18:48:48 +01:00
Pratik Mankawde
ae47ab08f0 docs(telemetry): note rpc_size ms-histogram instrument mismatch in 09-doc
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 18:48:43 +01:00
Pratik Mankawde
9fa9a34d49 Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-10 15:37:24 +01:00
Pratik Mankawde
d03128e2ed fix(telemetry): rename remaining category-placeholder metric names in 09-doc
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 15:37:14 +01:00
Pratik Mankawde
989c420a7a Merge branch 'pratik/otel-phase8-log-correlation' into pratik/otel-phase9-metric-gap-fill
# Conflicts:
#	OpenTelemetryPlan/09-data-collection-reference.md
#	docker/telemetry/grafana/dashboards/consensus-health.json
#	docker/telemetry/grafana/dashboards/ledger-operations.json
#	docker/telemetry/grafana/dashboards/node-health.json
#	docker/telemetry/grafana/dashboards/rpc-pathfinding.json
#	docker/telemetry/grafana/dashboards/rpc-performance.json
#	docker/telemetry/grafana/dashboards/transaction-overview.json
#	docs/telemetry-runbook.md
2026-07-10 15:35:34 +01:00
Pratik Mankawde
982e3cf9ef Merge branch 'pratik/otel-phase7-native-metrics' into pratik/otel-phase8-log-correlation 2026-07-10 14:31:07 +01:00