Two tracers have namespaces that disagree between what is emitted, what is documented, and what a trace configuration is allowed to name. Both come from the same root cause: a tracer's type is written out by hand in Documentation.hs and Consistency.hs, and neither is type-checked against the tracer actually wired in Tracers.hs, so the three can drift apart silently.
Verified on 39d586694 against released ouroboros-consensus-4.1.0.0.
1. BlockFetch.Decision — three phantom namespaces, two missing ones
Consensus.Tracers.blockFetchDecisionTracer has carried TraceDecisionEvent since ouroboros-consensus-4.1.0.0:
-- ouroboros-consensus-4.1.0.0, Ouroboros/Consensus/Node/Tracers.hs:73
, blockFetchDecisionTracer :: f (TraceDecisionEvent remotePeer (Header blk))
Tracers.hs wires that field, so what the node emits under BlockFetch.Decision is TraceDecisionEvent, whose namespaces are PeersFetch and PeerStarvedUs (Tracers/Consensus.hs:671).
But both declaration sites still name the pre-TraceDecisionEvent type:
-- Tracing/Documentation.hs:322
blockFetchDecisionTrDoc <- documentTracer (blockFetchDecisionTr ::
Logging.Trace IO [BlockFetch.TraceLabelPeer remotePeer
(FetchDecision [Point (Header blk)])])
-- Tracing/Consistency.hs:174
blockFetchDecisionNS = map (nsGetTuple . nsReplacePrefix ["BlockFetch", "Decision"])
(allNamespaces :: [Namespace [BlockFetch.TraceLabelPeer remotePeer
(FetchDecision [Point (Header blk)])]])
whose namespaces are EmptyPeersFetch, Accept and Decline.
Effect
bench/trace-schemas/newNamespaces.txt:10-12 lists BlockFetch.Decision.Accept, .Decline and .EmptyPeersFetch. None of them can ever be emitted.
BlockFetch.Decision.PeersFetch and .PeerStarvedUs are emitted but appear in no documentation, and checkTraceConfiguration rejects them as unknown namespaces — so the two real messages cannot be re-levelled or silenced from a config file.
2. BlockFetch.Client.ClientMetrics — documented and emitted, but rejected by the config check
ClientMetrics is folded from blockfetch events and composed onto the blockfetch client tracer in Tracers.hs, and documented at the ["BlockFetch","Client"] prefix:
-- Tracing/Documentation.hs:341
blockFetchClientMetricsDoc <- documentTracer (blockFetchClientMetricsTr ::
Logging.Trace IO ClientMetrics)
so BlockFetch.Client.ClientMetrics is in newNamespaces.txt:3. But Consistency.hs has no ClientMetrics entry — getAllNamespaces never mentions it.
Effect
The namespace is emitted and documented, yet naming it in a trace configuration produces a Config namespace error from checkTraceConfiguration.
Suggested fix
- In
Documentation.hs and Consistency.hs, annotate the blockfetch decision tracer as TraceDecisionEvent remotePeer (Header blk), matching the record field.
- Add a
ClientMetrics entry to getAllNamespaces at prefix ["BlockFetch","Client"], alongside the existing blockFetchClientNS.
- Regenerate
bench/trace-schemas/newNamespaces.txt and the trace schemas.
Worth confirming whether the now-unused MetaTrace/LogFormatting instances for FetchDecision [Point header] and [TraceLabelPeer peer (FetchDecision [Point header])] still have a consumer; if not, they can go with (1).
Root cause, and preventing recurrence
Each tracer's type is stated three times — once by the Consensus.Tracers field, once in Documentation.hs, once in Consistency.hs — and only the first is checked by the compiler. The other two build their own tracer values purely to enumerate namespaces, so a wrong annotation there compiles cleanly and surfaces only as a wrong name in the generated docs or a rejected config entry.
Anything that derives all three from one place would close this off. Failing that, a test asserting that the namespace set from getAllNamespaces matches the set docTracersFirstPhase produces would have caught both of these, since they disagree in opposite directions.
Two tracers have namespaces that disagree between what is emitted, what is documented, and what a trace configuration is allowed to name. Both come from the same root cause: a tracer's type is written out by hand in
Documentation.hsandConsistency.hs, and neither is type-checked against the tracer actually wired inTracers.hs, so the three can drift apart silently.Verified on
39d586694against releasedouroboros-consensus-4.1.0.0.1.
BlockFetch.Decision— three phantom namespaces, two missing onesConsensus.Tracers.blockFetchDecisionTracerhas carriedTraceDecisionEventsinceouroboros-consensus-4.1.0.0:Tracers.hswires that field, so what the node emits underBlockFetch.DecisionisTraceDecisionEvent, whose namespaces arePeersFetchandPeerStarvedUs(Tracers/Consensus.hs:671).But both declaration sites still name the pre-
TraceDecisionEventtype:whose namespaces are
EmptyPeersFetch,AcceptandDecline.Effect
bench/trace-schemas/newNamespaces.txt:10-12listsBlockFetch.Decision.Accept,.Declineand.EmptyPeersFetch. None of them can ever be emitted.BlockFetch.Decision.PeersFetchand.PeerStarvedUsare emitted but appear in no documentation, andcheckTraceConfigurationrejects them as unknown namespaces — so the two real messages cannot be re-levelled or silenced from a config file.2.
BlockFetch.Client.ClientMetrics— documented and emitted, but rejected by the config checkClientMetricsis folded from blockfetch events and composed onto the blockfetch client tracer inTracers.hs, and documented at the["BlockFetch","Client"]prefix:so
BlockFetch.Client.ClientMetricsis innewNamespaces.txt:3. ButConsistency.hshas noClientMetricsentry —getAllNamespacesnever mentions it.Effect
The namespace is emitted and documented, yet naming it in a trace configuration produces a
Config namespace errorfromcheckTraceConfiguration.Suggested fix
Documentation.hsandConsistency.hs, annotate the blockfetch decision tracer asTraceDecisionEvent remotePeer (Header blk), matching the record field.ClientMetricsentry togetAllNamespacesat prefix["BlockFetch","Client"], alongside the existingblockFetchClientNS.bench/trace-schemas/newNamespaces.txtand the trace schemas.Worth confirming whether the now-unused
MetaTrace/LogFormattinginstances forFetchDecision [Point header]and[TraceLabelPeer peer (FetchDecision [Point header])]still have a consumer; if not, they can go with (1).Root cause, and preventing recurrence
Each tracer's type is stated three times — once by the
Consensus.Tracersfield, once inDocumentation.hs, once inConsistency.hs— and only the first is checked by the compiler. The other two build their own tracer values purely to enumerate namespaces, so a wrong annotation there compiles cleanly and surfaces only as a wrong name in the generated docs or a rejected config entry.Anything that derives all three from one place would close this off. Failing that, a test asserting that the namespace set from
getAllNamespacesmatches the setdocTracersFirstPhaseproduces would have caught both of these, since they disagree in opposite directions.