fix(telemetry): preserve deterministic trace_id in round spans

Remove the span-replacement logic in startRoundTracing() that was
discarding the hash-derived round span and replacing it with a linked
span (which gets a random trace_id). The deterministic trace_id from
the ledger hash is the key feature enabling cross-node correlation —
replacing it broke correlation on all rounds after the first.

Also: use thread_local mt19937 for hashSpan() span IDs (same fix as
phase-3 txSpan), add Doxygen to establish tracing method declarations
in Consensus.h, and update SpanGuard.h diagram with hashSpan/addEvent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pratik Mankawde
2026-04-27 14:37:00 +01:00
parent 8fb33b0818
commit 53d0daf3b4
3 changed files with 9 additions and 14 deletions

View File

@@ -316,10 +316,9 @@ SpanGuard::hashSpan(
otel_trace::TraceId traceId(opentelemetry::nostd::span<std::uint8_t const, 16>(hashData, 16));
auto const rval = default_prng()();
std::uint8_t spanIdBytes[8];
std::random_device rd;
for (auto& b : spanIdBytes)
b = static_cast<std::uint8_t>(rd());
std::memcpy(spanIdBytes, &rval, sizeof(spanIdBytes));
otel_trace::SpanId spanId(opentelemetry::nostd::span<std::uint8_t const, 8>(spanIdBytes, 8));
otel_trace::SpanContext syntheticCtx(

View File

@@ -1183,17 +1183,6 @@ RCLConsensus::Adaptor::startRoundTracing(RCLCxLedger const& prevLgr)
if (!*roundSpan_)
return;
if (prevRoundContext_.isValid())
{
// Create a linked span to establish follows-from relationship
// between consecutive rounds, then transfer to roundSpan_.
auto linked = SpanGuard::linkedSpan(cons_span::round, prevRoundContext_);
if (linked)
{
roundSpan_.emplace(std::move(linked));
}
}
roundSpan_->setAttribute(cons_span::attr::ledgerId, to_string(prevLgr.id()).c_str());
roundSpan_->setAttribute(cons_span::attr::ledgerSeq, static_cast<int64_t>(prevLgr.seq() + 1));
roundSpan_->setAttribute(cons_span::attr::mode, to_string(mode_.load()).c_str());

View File

@@ -609,12 +609,19 @@ private:
*/
std::optional<xrpl::telemetry::SpanGuard> establishSpan_;
/** Create the establish-phase span if not yet active.
* Called on each phaseEstablish() invocation; no-op while span is live.
*/
void
startEstablishTracing();
/** Overwrite convergence metrics on the establish span each iteration.
* Final span attributes always reflect the last state before consensus.
*/
void
updateEstablishTracing();
/** End the establish span when transitioning to the accepted phase. */
void
endEstablishTracing();