Skip to content

cardano-node: remove iohk-monitoring tracing backend#6580

Draft
jutaro wants to merge 5 commits into
masterfrom
remove-iohk-monitoring
Draft

cardano-node: remove iohk-monitoring tracing backend#6580
jutaro wants to merge 5 commits into
masterfrom
remove-iohk-monitoring

Conversation

@jutaro
Copy link
Copy Markdown
Contributor

@jutaro jutaro commented May 26, 2026

Summary

Removes the legacy iohk-monitoring-based tracing infrastructure from
cardano-node, leaving trace-dispatcher as the sole tracing backend.

trace-dispatcher has been the production default since node 8.x. The old
iohk-monitoring path was retained during a transition period but is no longer
used or tested in production deployments. Removing it eliminates ~11 000 lines
of dead code and 9 transitive build dependencies.

What changed

Deleted (~8 100 lines, 15 modules):

  • All of Cardano.Tracing.*Config, HasIssuer, Metrics, Render,
    Shutdown, Startup, Tracers, and all OrphanInstances.* modules
    (Byron, Common, Consensus, HardFork, Network, Shelley)
  • Cardano.Node.Configuration.Logging — the iohk-monitoring init layer
  • Cardano.Node.Tracing.Compat — compatibility shim

Modified:

  • Cardano.Node.Run — simplified to use only initTraceDispatcher; all
    legacy createLoggingLayer / setupTrace / Cardano.BM.* imports gone
  • Cardano.Node.TraceConstraints — removes HasIssuer, ToObject, and
    related iohk-monitoring constraints
  • cardano-node.cabal — drops iohk-monitoring, lobemo-backend-*,
    lobemo-scribe-systemd, ekg-wai, tracer-transformers, scientific
  • Nix service config — removes legacy logging-layer options
  • Benchmark profiles — "tracing_backend" updated to "trace-dispatcher"

Breaking change

Any node config still using "TracingBackend": "iohk-monitoring" or legacy
Logging config keys will need to be migrated to trace-dispatcher
configuration before upgrading. Refer to the trace-dispatcher migration guide.

Config options removed with iohk-monitoring

The following node configuration keys have no effect after the removal of the
iohk-monitoring tracing backend. All tracing is now handled exclusively by
trace-dispatcher.

Parsed by the node but silently ignored

These three keys are still accepted by the JSON parser to avoid hard failures
on existing configs, but have no effect:

Key Previous effect
TurnOnLogging Master on/off switch for the iohk-monitoring logging layer
TurnOnLogMetrics Enabled/disabled node metrics collection via iohk-monitoring
UseTraceDispatcher Chose between legacy (false) and trace-dispatcher (true) backend

Parsed by Cardano.Tracing.Config (module deleted)

Key Previous effect
TracingVerbosity Rendering verbosity: MinimalVerbosity / NormalVerbosity / MaximalVerbosity
TraceAcceptPolicy Per-tracer on/off toggle (bool)
TraceBackingStore "
TraceBlockFetchClient "
TraceBlockFetchDecisions "
TraceBlockFetchProtocol "
TraceBlockFetchProtocolSerialised "
TraceBlockFetchServer "
TraceBlockchainTime "
TraceChainDB / TraceChainDb "
TraceChainSyncClient "
TraceChainSyncBlockServer "
TraceChainSyncHeaderServer "
TraceChainSyncProtocol "
TraceChurnMode "
TraceConnectionManager "
TraceConnectionManagerCounters "
TraceConnectionManagerTransitions "
TraceCsj "
TraceDevotedBlockFetch "
TraceDiffusionInitialization "
TraceDNS / TraceDnsResolver / TraceDnsSubscription "
TraceErrorPolicy / TraceLocalErrorPolicy "
TraceForge / TraceForgeStateInfo "
TraceGDD "
TraceGsm "
TraceHandshake / TraceLocalHandshake "
TraceInboundGovernor "
TraceInboundGovernorCounters "
TraceInboundGovernorTransitions "
TraceIpSubscription "
TraceKeepAliveClient / TraceKeepAliveProtocol "
TraceKesAgent "
TraceLedgerPeers "
TraceLocalChainSyncProtocol "
TraceLocalConnectionManager "
TraceLocalMux / TraceLocalMuxBearer / TraceLocalMuxChannel "
TraceLocalRootPeers "
TraceLocalServer "
TraceLocalStateQueryProtocol "
TraceLocalTxMonitorProtocol "
TraceLocalTxSubmissionProtocol / TraceLocalTxSubmissionServer "
TraceMempool "
TraceMux / TraceMuxBearer / TraceMuxChannel "
TracePeerSelection / TracePeerSelectionActions / TracePeerSelectionCounters "
TracePeerSharingProtocol "
TracePublicRootPeers "
TraceSanityCheckIssue "
TraceServer "
TraceTxCounters "
TraceTxInbound / TraceTxOutbound "
TraceTxLogic "
TraceTxSubmissionProtocol / TraceTxSubmission2Protocol "

Read directly by the iohk-monitoring library

These keys were consumed by Cardano.BM.Configuration — the node never parsed
them itself. They are now entirely ignored:

Key Previous effect
minSeverity Global severity filter (Debug / Info / Notice / Warning / Error / Critical)
rotation Log file rotation (rpLogLimitBytes, rpKeepFilesNum, rpMaxAgeHours)
setupBackends Which backends to initialise (KatipBK, EKGViewBK, etc.)
defaultBackends Default backend routing for namespaces
setupScribes Log output targets (file, stdout, journald, trace-forwarder)
defaultScribes Default scribe routing
hasEKG Port for EKG web metrics interface
hasPrometheus Host/port for Prometheus metrics endpoint
options.mapBackends Per-namespace backend routing overrides
options.mapSubtrace Per-namespace subtrace behaviour overrides
options.mapSeverity Per-namespace severity filter overrides

Replacements in trace-dispatcher

The trace-dispatcher backend has its own equivalents for severity filtering
and output routing, configured under TraceOptions in the trace-dispatcher
config file. Refer to the trace-dispatcher documentation for the current config
format.

@jutaro
Copy link
Copy Markdown
Contributor Author

jutaro commented May 26, 2026

The change in [Byron.hs:122] is:

Before:
( "txid" .= txId tx )
which relied on instance ToJSON (TxId (GenTx ByronBlock)) from the now-deleted Cardano.Tracing.OrphanInstances.Byron, which was:

instance ToJSON (TxId (GenTx ByronBlock)) where
toJSON = String . Text.take 8 . renderTxId
After:

( "txid" .= (Text.take 8 . renderTxId $ txId tx) )
The output is identical — both produce an 8-character hex string. The change just inlines the behavior that used to live in the deleted orphan instance, because that instance no longer exists.

configureTracers configReflection trConfig [shutdownTr]
shutdownTrDoc <- documentTracer (shutdownTr :: Logging.Trace IO ShutdownTrace)

chainDBTr <- mkCardanoTracer'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed?

consensusStartupErrorTrDoc <- documentTracer (consensusStartupErrorTr ::
Logging.Trace IO ConsensusStartupException)

consensusGddTr <- mkCardanoTracer
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed?


instance ToJSON NodeToClientVersionData where
toJSON = String . Text.pack . show

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there a ToJSON for both of the above in cardano-diffusion/orphan-instances/Cardano/Network/OrphanInstances.hs?
Using Show here seems to lose structure.

["Consensus", "Startup"]
configureTracers configReflection trConfig [consensusStartupErrorTr]

!consensusGddTr <- mkCardanoTracer
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every TraceGDDEvent is silently discarded. This makes Genesis Density Disconnection events completely invisible

else return $ Last $ Just PartialTracingOff
_turnOnLogging :: Maybe Bool <- v .:? "TurnOnLogging"
_turnOnLogMetrics :: Maybe Bool <- v .:? "TurnOnLogMetrics"
_useTraceDispatcher :: Maybe Bool <- v .:? "UseTraceDispatcher"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can go, right?

, "decisions" .= if dtal >= DMaximum
then toJSON (Verbose <$> xs)
else toJSON xs
, "decisions" .= List.foldl' (\acc x -> forMachine DDetailed x : acc) [] xs
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this produces the same output?
There's already a mismatch in detail levels.

(case pt of
GenesisPoint -> "Genesis"
BlockPoint _ h -> renderHeaderHash (Proxy @header) h)
BlockPoint slot _ -> "slot-" <> showT slot)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is completely wrong.
The output must look like

...
"ns":"BlockFetch.Client.CompletedBlockFetch","data":{"block":"00c854f75889b72e14e59e7ed891a467f1b21e28378b092efc786c63b769f67f", ...}

[ "kind" .= String "SendFetchRequest"
, "head" .= String (renderChainHash
(renderHeaderHash (Proxy @header))
(AF.headHash af))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The head key is missing after the change.

, "length" .= toJSON (fragmentLength' af)]
++
[ "deltaq" .= toJSON gsv | dtal >= DDetailed ]
[ "deltaq" .= String (Text.pack $ show gsv) | dtal >= DDetailed ]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field has a ToJSON in network, IIRC. It's an Object, not a String.

mconcat
[ "kind" .= String "TraceMempoolManuallyRemovedTxs"
, "txsRemoved" .= txs0
, "txsRemoved" .= map (String . Text.pack . show) (toList txs0)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is suspicious. It might result in the same output, it may not.
This needs scrutiny.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants