fix(telemetry): emit consensus.mode_change only on a real transition

MonitoredMode::set calls onModeChange on every round start, so the span was
created whether or not the mode moved. A node with a steady mode therefore
emitted one mode_change per round carrying mode_old == mode_new, which a live
sweep confirmed on every round of both instrumented builds. The round span's
own consensus_mode attribute is still written on every call, since that is
where the round learns the mode it is running in.
This commit is contained in:
Pratik Mankawde
2026-09-23 13:49:54 +01:00
parent 59bae37688
commit 6fadd0e2ee
2 changed files with 11 additions and 4 deletions

View File

@@ -73,7 +73,7 @@
* | Attrs: ledger_seq, proposing
* |
* +-- consensus.mode_change [main thread]
* Created: Adaptor::onModeChange()
* Created: Adaptor::onModeChange(), only when the mode moves
* Attrs: mode_old, mode_new
*
* Standalone spans (no parent, created per-message in overlay):

View File

@@ -1135,9 +1135,16 @@ RCLConsensus::Adaptor::onModeChange(ConsensusMode before, ConsensusMode after)
// thread-free SpanGuard, so parent explicitly via its context). A mode
// change outside a round leaves roundSpanContext_ invalid, yielding a null
// guard (no-op).
auto span = telemetry::SpanGuard::childSpan(cs::modeChange, roundSpanContext_);
span.setAttribute(cs::attr::modeOld, toDisplayString(before).c_str());
span.setAttribute(cs::attr::modeNew, toDisplayString(after).c_str());
//
// Only a real transition gets a span. MonitoredMode::set also calls this
// on every round start; the round's mode attribute below still needs that
// call, the span does not.
if (before != after)
{
auto span = telemetry::SpanGuard::childSpan(cs::modeChange, roundSpanContext_);
span.setAttribute(cs::attr::modeOld, toDisplayString(before).c_str());
span.setAttribute(cs::attr::modeNew, toDisplayString(after).c_str());
}
JLOG(j_.info()) << "Consensus mode change before=" << to_string(before)
<< ", after=" << to_string(after);