mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-23 07:10:53 +00:00
fix(telemetry): carry the per-node id on spans, not only the resource
Consensus spans share one deterministic, ledger-derived trace_id, so a single trace holds spans from every node and the resource-level node id is not a reliable per-span discriminator in stored traces. Add transform/spanidentity to both collector configs, copying service.instance.id onto every span as service_instance_id so TraceQL can filter per node with the same value the $node dashboard variable already uses on the metrics side. Wired into the traces pipeline locally and into traces/store (after tail_sampling) on the Grafana Cloud variant.
This commit is contained in:
@@ -123,6 +123,15 @@ processors:
|
|||||||
- set(attributes["service_instance_id"], resource.attributes["service.instance.id"])
|
- set(attributes["service_instance_id"], resource.attributes["service.instance.id"])
|
||||||
- set(attributes["deployment_environment"], resource.attributes["deployment.environment"])
|
- set(attributes["deployment_environment"], resource.attributes["deployment.environment"])
|
||||||
- set(attributes["xrpl_network_type"], resource.attributes["xrpl.network.type"])
|
- set(attributes["xrpl_network_type"], resource.attributes["xrpl.network.type"])
|
||||||
|
# Copy the per-node id from the resource onto every span so TraceQL can
|
||||||
|
# filter by node (span.service_instance_id). The name matches the metric
|
||||||
|
# label written by transform/cloudlabels, so the dashboards' $node variable
|
||||||
|
# applies to both signals.
|
||||||
|
transform/spanidentity:
|
||||||
|
trace_statements:
|
||||||
|
- context: span
|
||||||
|
statements:
|
||||||
|
- set(attributes["service_instance_id"], resource.attributes["service.instance.id"])
|
||||||
|
|
||||||
connectors:
|
connectors:
|
||||||
spanmetrics:
|
spanmetrics:
|
||||||
@@ -256,9 +265,20 @@ service:
|
|||||||
exporters: [spanmetrics]
|
exporters: [spanmetrics]
|
||||||
# Trace-STORAGE branch: 0.5% probabilistic tail sampling before Tempo
|
# Trace-STORAGE branch: 0.5% probabilistic tail sampling before Tempo
|
||||||
# and Grafana Cloud, so stored trace volume is ~1/200 of ingested spans.
|
# and Grafana Cloud, so stored trace volume is ~1/200 of ingested spans.
|
||||||
|
# transform/spanidentity runs after tail_sampling so only retained spans
|
||||||
|
# pay for the copy. traces/metrics does not need it: spanmetrics already
|
||||||
|
# groups by the service.instance.id resource attribute
|
||||||
|
# (resource_metrics_key_attributes).
|
||||||
traces/store:
|
traces/store:
|
||||||
receivers: [otlp]
|
receivers: [otlp]
|
||||||
processors: [tail_sampling, resource/tier, resource/stripsdk, batch]
|
processors:
|
||||||
|
[
|
||||||
|
tail_sampling,
|
||||||
|
resource/tier,
|
||||||
|
resource/stripsdk,
|
||||||
|
transform/spanidentity,
|
||||||
|
batch,
|
||||||
|
]
|
||||||
exporters: [otlp/tempo, otlphttp/grafanacloud]
|
exporters: [otlp/tempo, otlphttp/grafanacloud]
|
||||||
# The local Prometheus scrape promotes tier/instance resource attrs to
|
# The local Prometheus scrape promotes tier/instance resource attrs to
|
||||||
# labels via resource_to_telemetry_conversion; Grafana Cloud (OTLP) does
|
# labels via resource_to_telemetry_conversion; Grafana Cloud (OTLP) does
|
||||||
|
|||||||
@@ -124,6 +124,14 @@ processors:
|
|||||||
action: hash
|
action: hash
|
||||||
- key: pathfind_dest_account
|
- key: pathfind_dest_account
|
||||||
action: hash
|
action: hash
|
||||||
|
# Copy the per-node id from the resource onto every span so TraceQL can
|
||||||
|
# filter by node (span.service_instance_id), matching the service_instance_id
|
||||||
|
# metric label the dashboards' $node variable already uses.
|
||||||
|
transform/spanidentity:
|
||||||
|
trace_statements:
|
||||||
|
- context: span
|
||||||
|
statements:
|
||||||
|
- set(attributes["service_instance_id"], resource.attributes["service.instance.id"])
|
||||||
|
|
||||||
connectors:
|
connectors:
|
||||||
spanmetrics:
|
spanmetrics:
|
||||||
@@ -241,7 +249,14 @@ service:
|
|||||||
pipelines:
|
pipelines:
|
||||||
traces:
|
traces:
|
||||||
receivers: [otlp]
|
receivers: [otlp]
|
||||||
processors: [resource/tier, resource/stripsdk, attributes/hash, batch]
|
processors:
|
||||||
|
[
|
||||||
|
resource/tier,
|
||||||
|
resource/stripsdk,
|
||||||
|
attributes/hash,
|
||||||
|
transform/spanidentity,
|
||||||
|
batch,
|
||||||
|
]
|
||||||
exporters: [debug, otlp/tempo, spanmetrics]
|
exporters: [debug, otlp/tempo, spanmetrics]
|
||||||
metrics:
|
metrics:
|
||||||
receivers: [otlp, spanmetrics]
|
receivers: [otlp, spanmetrics]
|
||||||
|
|||||||
@@ -144,6 +144,16 @@ curl -s http://localhost:5015 -d '{"method":"server_info"}' |
|
|||||||
| `tls_client_cert` | (empty) | Client cert (PEM) for mutual TLS; empty = one-way TLS |
|
| `tls_client_cert` | (empty) | Client cert (PEM) for mutual TLS; empty = one-way TLS |
|
||||||
| `tls_client_key` | (empty) | Private key (PEM) for `tls_client_cert` |
|
| `tls_client_key` | (empty) | Private key (PEM) for `tls_client_cert` |
|
||||||
|
|
||||||
|
> **`service_instance_id` reaches traces as a span attribute too.** xrpld sends
|
||||||
|
> it as the `service.instance.id` resource attribute; the collector's
|
||||||
|
> `transform/spanidentity` processor copies it onto every span as
|
||||||
|
> `service_instance_id`, so TraceQL can filter per node
|
||||||
|
> (`{span.service_instance_id="validator-0"}`) with the same value the `$node`
|
||||||
|
> dashboard variable uses for metrics. Spans recorded before that processor was
|
||||||
|
> added do not carry it, and a TraceQL regex does **not** match a missing
|
||||||
|
> attribute — so a `$node` filter on a trace panel returns nothing for older
|
||||||
|
> data.
|
||||||
|
|
||||||
> **`consensus_trace_strategy` is not validated.** The parser copies the raw
|
> **`consensus_trace_strategy` is not validated.** The parser copies the raw
|
||||||
> string through (`TelemetryConfig.cpp:155-156`) and the only equality test in
|
> string through (`TelemetryConfig.cpp:155-156`) and the only equality test in
|
||||||
> the code is `strategy == "attribute"` (`RCLConsensus.cpp:1296`). Any other
|
> the code is `strategy == "attribute"` (`RCLConsensus.cpp:1296`). Any other
|
||||||
|
|||||||
Reference in New Issue
Block a user