From e87432fe3c773f6c0f74b99c82bc3cbf0cb9331a Mon Sep 17 00:00:00 2001
From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Date: Fri, 18 Sep 2026 09:24:56 +0100
Subject: [PATCH 1/4] fix(telemetry): drop the suppressed references the span
no longer emits
tx.receive is created after the duplicate check, so it never carries a
suppressed attribute. The Tempo tag filter and the dashboard panel still
referenced it, and check_otel_naming rules C and D fail on a reference with no
constant behind it.
The panel keeps its remaining signal as a plain receive rate. How many relayed
copies were dropped is the transactions_duplicate traffic category, which does
not depend on a span.
The spanmetrics dimension goes too; a dimension for an attribute nothing sets
only widens the label set.
---
.../grafana/dashboards/transaction-overview.json | 8 ++++----
.../telemetry/grafana/provisioning/datasources/tempo.yaml | 5 -----
docker/telemetry/otel-collector-config.yaml | 1 -
3 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/docker/telemetry/grafana/dashboards/transaction-overview.json b/docker/telemetry/grafana/dashboards/transaction-overview.json
index 94cc8be828..3fb01f7cd8 100644
--- a/docker/telemetry/grafana/dashboards/transaction-overview.json
+++ b/docker/telemetry/grafana/dashboards/transaction-overview.json
@@ -140,8 +140,8 @@
}
},
{
- "title": "Transaction Receive vs Suppressed",
- "description": "**What:** Raw transaction messages received from peers, split by whether they were suppressed as duplicates before processing.\n**How it's computed:** Per-second rate split by suppressed flag over a 5-minute window, per node.\n**Reading it:** A healthy relay network produces a steady suppressed share as duplicates are filtered.\n**Healthy range:** Workload-dependent; suppression is expected and normal.\n**Watch for:** A sharp rise in the suppressed line can reflect gossip amplification or a peer replaying transactions.\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::handleTransaction",
+ "title": "Transaction Receive Rate",
+ "description": "**What:** Transactions received from peers that this node went on to process.\n**How it's computed:** Per-second rate of the tx.receive span over a 5-minute window, per node.\n**Reading it:** Tracks the useful inbound transaction load. Copies dropped as duplicates are not counted here, because the span starts after the duplicate check; their volume is the transactions_duplicate traffic category.\n**Healthy range:** Workload-dependent.\n**Watch for:** A fall to zero while peers are connected means inbound relay has stopped.\n**Source:** src/xrpld/overlay/detail/PeerImp.cpp:PeerImp::handleTransaction",
"type": "timeseries",
"gridPos": {
"h": 8,
@@ -161,8 +161,8 @@
"datasource": {
"type": "prometheus"
},
- "expr": "sum by (suppressed, service_instance_id) (rate(traces_span_metrics_calls_total{span_name=\"tx.receive\", tx_type=~\"$tx_type\", service_instance_id=~\"$node\", deployment_environment=~\"$deployment_environment\", xrpl_network_type=~\"$xrpl_network_type\", service_name=~\"$service_name\"}[$__rate_interval]))",
- "legendFormat": "Suppressed={{suppressed}} [{{service_instance_id}}]"
+ "expr": "sum by (service_instance_id) (rate(traces_span_metrics_calls_total{span_name=\"tx.receive\", tx_type=~\"$tx_type\", service_instance_id=~\"$node\", deployment_environment=~\"$deployment_environment\", xrpl_network_type=~\"$xrpl_network_type\", service_name=~\"$service_name\"}[$__rate_interval]))",
+ "legendFormat": "Tx Receive [{{service_instance_id}}]"
}
],
"fieldConfig": {
diff --git a/docker/telemetry/grafana/provisioning/datasources/tempo.yaml b/docker/telemetry/grafana/provisioning/datasources/tempo.yaml
index 3497c287ab..dfb0440dd7 100644
--- a/docker/telemetry/grafana/provisioning/datasources/tempo.yaml
+++ b/docker/telemetry/grafana/provisioning/datasources/tempo.yaml
@@ -186,11 +186,6 @@ datasources:
operator: "="
scope: span
type: dynamic
- - id: tx-suppressed
- tag: suppressed
- operator: "="
- scope: span
- type: dynamic
- id: peer-version
tag: peer_version
operator: "="
diff --git a/docker/telemetry/otel-collector-config.yaml b/docker/telemetry/otel-collector-config.yaml
index 806df58449..87892939b6 100644
--- a/docker/telemetry/otel-collector-config.yaml
+++ b/docker/telemetry/otel-collector-config.yaml
@@ -100,7 +100,6 @@ connectors:
- name: consensus_mode
- name: close_time_correct
- name: local
- - name: suppressed
- name: proposal_trusted
- name: validation_trusted
- name: tx_type
From 675dffdc718a3f12bb79bfeb2dce26c6e274d42d Mon Sep 17 00:00:00 2001
From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Date: Fri, 18 Sep 2026 09:31:23 +0100
Subject: [PATCH 2/4] docs(telemetry): drop suppressed from the tx.receive
attribute list
The span is created after the duplicate check, so it never carries the
attribute, and the row now says which transactions it covers.
---
docs/telemetry-runbook.md | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/docs/telemetry-runbook.md b/docs/telemetry-runbook.md
index c1234abc67..e0a3b3e7cf 100644
--- a/docs/telemetry-runbook.md
+++ b/docs/telemetry-runbook.md
@@ -88,14 +88,14 @@ All spans instrumented in xrpld, grouped by subsystem:
### Transaction Spans
-| Span Name | Source File | Attributes | Description |
-| --------------- | --------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------- |
-| `tx.process` | NetworkOPs.cpp | `tx_hash`, `local`, `path`, `tx_type`, `fee`, `sequence`, `ter_result`, `applied`, `current_ledger_seq` | Transaction submission and processing |
-| `tx.receive` | PeerImp.cpp | `peer_id`, `tx_hash`, `tx_type`, `peer_version`, `suppressed`, `tx_status`, `current_ledger_seq` | Transaction received from peer relay |
-| `tx.apply` | BuildLedger.cpp | `ledger_seq`, `tx_count`, `tx_failed` | Transaction set applied per ledger |
-| `tx.preflight` | applySteps.cpp | `stage`, `tx_type`, `ter_result` | Stateless checks stage |
-| `tx.preclaim` | applySteps.cpp | `stage`, `tx_type`, `ter_result`, `current_ledger_seq`, `current_ledger_hash` | Ledger-aware checks stage |
-| `tx.transactor` | Transactor.cpp | `stage`, `tx_type`, `ter_result`, `applied`, `current_ledger_seq`, `current_ledger_hash` | Apply stage (transactor runs) |
+| Span Name | Source File | Attributes | Description |
+| --------------- | --------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
+| `tx.process` | NetworkOPs.cpp | `tx_hash`, `local`, `path`, `tx_type`, `fee`, `sequence`, `ter_result`, `applied`, `current_ledger_seq` | Transaction submission and processing |
+| `tx.receive` | PeerImp.cpp | `peer_id`, `tx_hash`, `tx_type`, `peer_version`, `tx_status`, `current_ledger_seq` | Transaction this node will process, received from peer relay |
+| `tx.apply` | BuildLedger.cpp | `ledger_seq`, `tx_count`, `tx_failed` | Transaction set applied per ledger |
+| `tx.preflight` | applySteps.cpp | `stage`, `tx_type`, `ter_result` | Stateless checks stage |
+| `tx.preclaim` | applySteps.cpp | `stage`, `tx_type`, `ter_result`, `current_ledger_seq`, `current_ledger_hash` | Ledger-aware checks stage |
+| `tx.transactor` | Transactor.cpp | `stage`, `tx_type`, `ter_result`, `applied`, `current_ledger_seq`, `current_ledger_hash` | Apply stage (transactor runs) |
The three apply-pipeline spans (`tx.preflight`, `tx.preclaim`, `tx.transactor`)
share a deterministic `trace_id` from `txID[0:16]`, so they group under one
From 3b60a190de9e02cfd8737aebf3b8547224fc18a8 Mon Sep 17 00:00:00 2001
From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Date: Fri, 18 Sep 2026 09:32:29 +0100
Subject: [PATCH 3/4] fix(telemetry): drop the remaining suppressed dimensions
and diagram values
Alloy and the Grafana Cloud collector still declared a spanmetrics dimension
for an attribute tx.receive no longer sets, which only widens the label set.
The runbook's drop-path diagram still listed two tx_status values that no
longer exist, because the paths that set them now run before the span starts.
---
docker/telemetry/alloy/config.alloy | 1 -
docker/telemetry/otel-collector-config.grafanacloud.yaml | 1 -
docs/telemetry-runbook.md | 2 +-
3 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/docker/telemetry/alloy/config.alloy b/docker/telemetry/alloy/config.alloy
index 3135b6149a..e5d5f613de 100644
--- a/docker/telemetry/alloy/config.alloy
+++ b/docker/telemetry/alloy/config.alloy
@@ -349,7 +349,6 @@ otelcol.connector.spanmetrics "xrpld" {
// Overlay / peer dimensions.
dimension { name = "local" }
- dimension { name = "suppressed" }
dimension { name = "proposal_trusted" }
dimension { name = "validation_trusted" }
diff --git a/docker/telemetry/otel-collector-config.grafanacloud.yaml b/docker/telemetry/otel-collector-config.grafanacloud.yaml
index 21ea1804c7..01722e383a 100644
--- a/docker/telemetry/otel-collector-config.grafanacloud.yaml
+++ b/docker/telemetry/otel-collector-config.grafanacloud.yaml
@@ -223,7 +223,6 @@ connectors:
- name: close_time_correct
- name: consensus_state
- name: local
- - name: suppressed
- name: proposal_trusted
- name: validation_trusted
- name: tx_type
diff --git a/docs/telemetry-runbook.md b/docs/telemetry-runbook.md
index ea56ec3d5f..0f8b527f36 100644
--- a/docs/telemetry-runbook.md
+++ b/docs/telemetry-runbook.md
@@ -588,7 +588,7 @@ flowchart TB
RELAYOUT(["Overlay::relay fan-out to N peers
(no span; if applied / terQUEUED,
shouldRelay, not tfInnerBatchTxn)"]):::plain
PREDROP(["Diverged / needNetworkLedger
(no span — dropped before tx.receive)"]):::drop
RCV["tx.receive
(peer TMTransaction in)"]:::span
- RCVDROP["tx.receive
tx_status = rejected_inner_batch /
suppressed / dropped_no_sync /
dropped_queue_full"]:::drop
+ RCVDROP["tx.receive
tx_status = dropped_no_sync /
dropped_queue_full"]:::drop
CHK(["checkTransaction
(JtTransaction worker, no span)"]):::plain
PRELAY_IN(["TMTransaction in (no span)"]):::plain
From b54109201695033aeccdbbe8be0928af9e3dc611 Mon Sep 17 00:00:00 2001
From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Date: Fri, 18 Sep 2026 09:33:04 +0100
Subject: [PATCH 4/4] test(telemetry): drop suppressed from the mirrored
dimension list
The list mirrors the collector's spanmetrics dimensions, and that dimension is
gone. The reduce-relay and squelch counters keep their own names, which are a
different thing.
---
docker/telemetry/workload/expected_metrics.json | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/docker/telemetry/workload/expected_metrics.json b/docker/telemetry/workload/expected_metrics.json
index 34a4b55fad..fe5b32a0b9 100644
--- a/docker/telemetry/workload/expected_metrics.json
+++ b/docker/telemetry/workload/expected_metrics.json
@@ -26,8 +26,7 @@
"stage",
"txq_status",
"close_time_correct",
- "consensus_state",
- "suppressed"
+ "consensus_state"
],
"_dimension_labels_note": "Bare label names as configured in otel-collector-config.yaml spanmetrics dimensions. Informational only (not asserted by the validator)."
},