diff --git a/docker/telemetry/TESTING.md b/docker/telemetry/TESTING.md index 2a6cfac9f2..723371a888 100644 --- a/docker/telemetry/TESTING.md +++ b/docker/telemetry/TESTING.md @@ -372,28 +372,28 @@ See the "Verification Queries" section below. ## Expected Span Catalog -All 16 production span names instrumented across Phases 2-5: +All 16 production span names: -| Span Name | Source File | Phase | Key Attributes | How to Trigger | -| --------------------------- | ----------------- | ----- | ---------------------------------------------------------------------------------------- | ------------------------- | -| `rpc.http_request` | ServerHandler.cpp | 2 | -- | Any HTTP RPC call | -| `rpc.ws_upgrade` | ServerHandler.cpp | 2 | -- | WebSocket upgrade | -| `rpc.ws_message` | ServerHandler.cpp | 2 | -- | WebSocket RPC message | -| `rpc.process` | ServerHandler.cpp | 2 | -- | RPC processing | -| `rpc.command.` | RPCHandler.cpp | 2 | `xrpl.rpc.command`, `xrpl.rpc.version`, `xrpl.rpc.role` | Any RPC command | -| `tx.process` | NetworkOPs.cpp | 3 | `xrpl.tx.hash`, `xrpl.tx.local`, `xrpl.tx.path` | Submit transaction | -| `tx.receive` | PeerImp.cpp | 3 | `xrpl.peer.id` | Peer relays transaction | -| `consensus.proposal.send` | RCLConsensus.cpp | 4 | `xrpl.consensus.round` | Consensus proposing phase | -| `consensus.ledger_close` | RCLConsensus.cpp | 4 | `xrpl.consensus.ledger.seq`, `xrpl.consensus.mode` | Ledger close event | -| `consensus.accept` | RCLConsensus.cpp | 4 | `xrpl.consensus.proposers`, `xrpl.consensus.round_time_ms` | Ledger accepted | -| `consensus.validation.send` | RCLConsensus.cpp | 4 | `xrpl.consensus.ledger.seq`, `xrpl.consensus.proposing` | Validation sent | -| `consensus.accept.apply` | RCLConsensus.cpp | 4 | `xrpl.consensus.close_time`, `close_time_correct`, `close_resolution_ms`, `state` | Ledger apply + close time | -| `tx.apply` | BuildLedger.cpp | 5 | `xrpl.ledger.tx_count`, `xrpl.ledger.tx_failed` | Ledger close (tx set) | -| `ledger.build` | BuildLedger.cpp | 5 | `xrpl.ledger.seq`, `xrpl.ledger.close_time`, `close_time_correct`, `close_resolution_ms` | Ledger build | -| `ledger.validate` | LedgerMaster.cpp | 5 | `xrpl.ledger.seq`, `xrpl.ledger.validations` | Ledger validated | -| `ledger.store` | LedgerMaster.cpp | 5 | `xrpl.ledger.seq` | Ledger stored | -| `peer.proposal.receive` | PeerImp.cpp | 5 | `xrpl.peer.id`, `xrpl.peer.proposal.trusted` | Peer sends proposal | -| `peer.validation.receive` | PeerImp.cpp | 5 | `xrpl.peer.id`, `xrpl.peer.validation.trusted` | Peer sends validation | +| Span Name | Source File | Key Attributes | How to Trigger | +| --------------------------- | ----------------- | ---------------------------------------------------------------------------------------- | ------------------------- | +| `rpc.http_request` | ServerHandler.cpp | -- | Any HTTP RPC call | +| `rpc.ws_upgrade` | ServerHandler.cpp | -- | WebSocket upgrade | +| `rpc.ws_message` | ServerHandler.cpp | -- | WebSocket RPC message | +| `rpc.process` | ServerHandler.cpp | -- | RPC processing | +| `rpc.command.` | RPCHandler.cpp | `xrpl.rpc.command`, `xrpl.rpc.version`, `xrpl.rpc.role` | Any RPC command | +| `tx.process` | NetworkOPs.cpp | `xrpl.tx.hash`, `xrpl.tx.local`, `xrpl.tx.path` | Submit transaction | +| `tx.receive` | PeerImp.cpp | `xrpl.peer.id` | Peer relays transaction | +| `consensus.proposal.send` | RCLConsensus.cpp | `xrpl.consensus.round` | Consensus proposing phase | +| `consensus.ledger_close` | RCLConsensus.cpp | `xrpl.consensus.ledger.seq`, `xrpl.consensus.mode` | Ledger close event | +| `consensus.accept` | RCLConsensus.cpp | `xrpl.consensus.proposers`, `xrpl.consensus.round_time_ms` | Ledger accepted | +| `consensus.validation.send` | RCLConsensus.cpp | `xrpl.consensus.ledger.seq`, `xrpl.consensus.proposing` | Validation sent | +| `consensus.accept.apply` | RCLConsensus.cpp | `xrpl.consensus.close_time`, `close_time_correct`, `close_resolution_ms`, `state` | Ledger apply + close time | +| `tx.apply` | BuildLedger.cpp | `xrpl.ledger.tx_count`, `xrpl.ledger.tx_failed` | Ledger close (tx set) | +| `ledger.build` | BuildLedger.cpp | `xrpl.ledger.seq`, `xrpl.ledger.close_time`, `close_time_correct`, `close_resolution_ms` | Ledger build | +| `ledger.validate` | LedgerMaster.cpp | `xrpl.ledger.seq`, `xrpl.ledger.validations` | Ledger validated | +| `ledger.store` | LedgerMaster.cpp | `xrpl.ledger.seq` | Ledger stored | +| `peer.proposal.receive` | PeerImp.cpp | `xrpl.peer.id`, `xrpl.peer.proposal.trusted` | Peer sends proposal | +| `peer.validation.receive` | PeerImp.cpp | `xrpl.peer.id`, `xrpl.peer.validation.trusted` | Peer sends validation | --- diff --git a/docker/telemetry/integration-test.sh b/docker/telemetry/integration-test.sh index 9b9a7ab3b6..256c95a106 100755 --- a/docker/telemetry/integration-test.sh +++ b/docker/telemetry/integration-test.sh @@ -409,7 +409,7 @@ for attempt in $(seq 1 60); do done # --------------------------------------------------------------------------- -# Step 7: Exercise RPC spans (Phase 2) +# Step 7: Exercise RPC spans # --------------------------------------------------------------------------- log "Exercising RPC spans..." @@ -424,7 +424,7 @@ log "RPC commands sent. Waiting 5s for batch export..." sleep 5 # --------------------------------------------------------------------------- -# Step 8: Submit transaction (Phase 3) +# Step 8: Submit transaction # --------------------------------------------------------------------------- log "Submitting Payment transaction..." @@ -477,7 +477,7 @@ else fi log "" -log "--- Phase 2: RPC Spans ---" +log "--- RPC Spans ---" check_span "rpc.request" check_span "rpc.process" check_span "rpc.command.server_info" @@ -485,26 +485,26 @@ check_span "rpc.command.server_state" check_span "rpc.command.ledger" log "" -log "--- Phase 3: Transaction Spans ---" +log "--- Transaction Spans ---" check_span "tx.process" check_span "tx.receive" check_span "tx.apply" log "" -log "--- Phase 4: Consensus Spans ---" +log "--- Consensus Spans ---" check_span "consensus.proposal.send" check_span "consensus.ledger_close" check_span "consensus.accept" check_span "consensus.validation.send" log "" -log "--- Phase 5: Ledger Spans ---" +log "--- Ledger Spans ---" check_span "ledger.build" check_span "ledger.validate" check_span "ledger.store" log "" -log "--- Phase 5: Peer Spans (trace_peer=1) ---" +log "--- Peer Spans (trace_peer=1) ---" check_span "peer.proposal.receive" check_span "peer.validation.receive" @@ -512,7 +512,7 @@ check_span "peer.validation.receive" # Step 10: Verify Prometheus spanmetrics # --------------------------------------------------------------------------- log "" -log "--- Phase 5: Spanmetrics ---" +log "--- Spanmetrics ---" log "Waiting 20s for Prometheus scrape cycle..." sleep 20 diff --git a/include/xrpl/proto/xrpl.proto b/include/xrpl/proto/xrpl.proto index 468034ad3a..16bd7d2e12 100644 --- a/include/xrpl/proto/xrpl.proto +++ b/include/xrpl/proto/xrpl.proto @@ -95,9 +95,8 @@ message TMPublicKey { // Older peers that do not understand field 1001 will simply ignore it // per protobuf wire-format rules, preserving backwards compatibility. // -// trace_state is reserved for future use (secure tracing pipeline, -// OpenTelemetryPlan/secure-OTel.md). It is currently neither populated -// on inject nor read on extract; consumers must not rely on it. +// trace_state is reserved for future use. It is currently neither +// populated on inject nor read on extract; consumers must not rely on it. message TraceContext { optional bytes trace_id = 1; // 16-byte trace identifier optional bytes span_id = 2; // 8-byte parent span identifier diff --git a/include/xrpl/telemetry/TraceContextPropagator.h b/include/xrpl/telemetry/TraceContextPropagator.h index e8d851e53e..9933e79292 100644 --- a/include/xrpl/telemetry/TraceContextPropagator.h +++ b/include/xrpl/telemetry/TraceContextPropagator.h @@ -101,13 +101,10 @@ injectToProtobuf(opentelemetry::context::Context const& ctx, protocol::TraceCont // Serialize flags proto.set_trace_flags(spanCtx.trace_flags().flags()); - // TODO(observability/secure-OTel): the protobuf TraceContext message - // also carries `trace_state` (field 4), which is currently neither - // populated here nor read by extractFromProtobuf above. The field is - // reserved for the secure tracing pipeline outlined in - // OpenTelemetryPlan/secure-OTel.md, where an authenticated token in - // tracestate will let receivers reject spoofed/poisoned trace context. - // Wire trace_state through inject/extract once the consumer lands. + // TODO: the protobuf TraceContext message also carries `trace_state` + // (field 4), which is currently neither populated here nor read by + // extractFromProtobuf above. The field is reserved for future use; + // wire it through inject/extract once a consumer lands. } } // namespace xrpl::telemetry diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index 35f5ed2131..5d8fb2ae5f 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -274,9 +274,9 @@ RCLConsensus::Adaptor::propose(RCLCxPeerPos::Proposal const& proposal) app_.getHashRouter().addSuppression(suppression); - // Inject the current thread's active span context (e.g. the - // consensus round span from Phase 4) so receiving peers can link - // their proposal.receive span as a child of this trace. + // Inject the current thread's active span context (e.g. the consensus + // round span) so receiving peers can link their proposal.receive span + // as a child of this trace. telemetry::SpanGuard::injectCurrentContextToProtobuf(*prop.mutable_trace_context()); app_.getOverlay().broadcast(prop); diff --git a/src/xrpld/app/consensus/RCLConsensus.h b/src/xrpld/app/consensus/RCLConsensus.h index 1ada9e7ee9..a7057e2f3a 100644 --- a/src/xrpld/app/consensus/RCLConsensus.h +++ b/src/xrpld/app/consensus/RCLConsensus.h @@ -127,9 +127,9 @@ class RCLConsensus * * Captured in makeAcceptSpan() and consumed by createValidationSpan() * on the jtACCEPT worker thread so the validation.send span can be - * follows-from linked to consensus.accept (matching the design doc - * and span hierarchy diagram). Reset on each startRoundTracing() - * to prevent a stale prior-round context from being linked. + * follows-from linked to consensus.accept. Reset on each + * startRoundTracing() to prevent a stale prior-round context from + * being linked. * * Thread safety: same model as roundSpanContext_. The write in * makeAcceptSpan happens on the main consensus thread under diff --git a/src/xrpld/telemetry/ConsensusReceiveTracing.h b/src/xrpld/telemetry/ConsensusReceiveTracing.h index 03974c5473..0a1a4458dc 100644 --- a/src/xrpld/telemetry/ConsensusReceiveTracing.h +++ b/src/xrpld/telemetry/ConsensusReceiveTracing.h @@ -34,7 +34,8 @@ * * @note Span names come from the canonical constants in * ConsensusSpanNames.h (consensus::span::proposalReceive / - * validationReceive) so they stay in sync with the rest of Phase 4. + * validationReceive) so they stay in sync with the rest of the + * consensus tracing surface. */ #include