Skip to content

Commit

Permalink
New debug log-epoch-state command
Browse files Browse the repository at this point in the history
  • Loading branch information
newhoggy committed May 29, 2024
1 parent 315e192 commit 928aac5
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 0 deletions.
7 changes: 7 additions & 0 deletions cardano-cli/cardano-cli.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ library
Cardano.CLI.Byron.Vote
Cardano.CLI.Commands
Cardano.CLI.Commands.Ping
Cardano.CLI.Commands.Debug
Cardano.CLI.Commands.Debug.LogEpochState
Cardano.CLI.Environment
Cardano.CLI.EraBased.Commands
Cardano.CLI.EraBased.Commands.Address
Expand Down Expand Up @@ -140,13 +142,17 @@ library
Cardano.CLI.Legacy.Run.TextView
Cardano.CLI.Legacy.Run.Transaction
Cardano.CLI.Options
Cardano.CLI.Options.Debug
Cardano.CLI.Options.Ping
Cardano.CLI.Orphans
Cardano.CLI.OS.Posix
Cardano.CLI.Parser
Cardano.CLI.Pretty
Cardano.CLI.Read
Cardano.CLI.Render
Cardano.CLI.Run
Cardano.CLI.Run.Debug
Cardano.CLI.Run.Debug.LogEpochState
Cardano.CLI.Run.Ping
Cardano.CLI.TopHandler
Cardano.CLI.Types.Common
Expand Down Expand Up @@ -208,6 +214,7 @@ library
, cardano-git-rev ^>= 0.2.2
, cardano-ledger-api
, cardano-ledger-byron >= 1.0.1.0
, cardano-ledger-shelley
, cardano-ping ^>= 0.2.0.13
, cardano-prelude
, cardano-slotting ^>= 0.2.0.0
Expand Down
2 changes: 2 additions & 0 deletions cardano-cli/src/Cardano/CLI/Commands.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Cardano.CLI.Commands
) where

import Cardano.CLI.Byron.Commands (ByronCommand)
import Cardano.CLI.Commands.Debug
import Cardano.CLI.Commands.Ping (PingCmd (..))
import Cardano.CLI.EraBased.Commands
import Cardano.CLI.Legacy.Commands
Expand All @@ -22,6 +23,7 @@ data ClientCommand =
| LegacyCmds LegacyCmds

| CliPingCommand PingCmd
| CliDebugCmds DebugCmds

| forall a. Help ParserPrefs (ParserInfo a)
| DisplayVersion
8 changes: 8 additions & 0 deletions cardano-cli/src/Cardano/CLI/Commands/Debug.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Cardano.CLI.Commands.Debug
( DebugCmds (..)
) where

import Cardano.CLI.Commands.Debug.LogEpochState

newtype DebugCmds =
DebugLogEpochStateCmd LogEpochStateCmdArgs
22 changes: 22 additions & 0 deletions cardano-cli/src/Cardano/CLI/Commands/Debug/LogEpochState.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{-# LANGUAGE DataKinds #-}

module Cardano.CLI.Commands.Debug.LogEpochState
( LogEpochStateCmdArgs(..)
, Configuration
) where

import Cardano.Api

import Cardano.CLI.Orphans ()

-- | A phantom type to represent the configuration file.
data Configuration

-- | The arguments for the 'debug log-epoch-state' command.
--
-- This command will connect to a local node and log the epoch state.
data LogEpochStateCmdArgs = LogEpochStateCmdArgs
{ nodeSocketPath :: !SocketPath
, configurationFile :: !(NodeConfigFile 'In)
, outputFilePath :: !(File Configuration 'Out)
} deriving Show
5 changes: 5 additions & 0 deletions cardano-cli/src/Cardano/CLI/Options.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Cardano.CLI.Environment (EnvCli)
import Cardano.CLI.EraBased.Commands
import Cardano.CLI.EraBased.Options.Common
import Cardano.CLI.Legacy.Options (parseLegacyCmds)
import Cardano.CLI.Options.Debug
import Cardano.CLI.Options.Ping (parsePingCmd)
import Cardano.CLI.Render (customRenderHelp)
import Cardano.CLI.Run (ClientCommand (..))
Expand Down Expand Up @@ -55,6 +56,7 @@ parseClientCommand envCli =
, parseTopLevelLegacy envCli
, parseByron envCli
, parsePing
, parseDebug envCli
, backwardsCompatibilityCommands envCli
, parseDisplayVersion (opts envCli)
]
Expand All @@ -71,6 +73,9 @@ parseByron mNetworkId =
parsePing :: Parser ClientCommand
parsePing = CliPingCommand <$> parsePingCmd

parseDebug :: EnvCli -> Parser ClientCommand
parseDebug envCli = CliDebugCmds <$> parseDebugCmds envCli

parseAnyEra :: EnvCli -> Parser ClientCommand
parseAnyEra envCli = AnyEraCommand <$> pAnyEraCommand envCli

Expand Down
63 changes: 63 additions & 0 deletions cardano-cli/src/Cardano/CLI/Options/Debug.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}

{- HLINT ignore "Use <$>" -}
{- HLINT ignore "Move brackets to avoid $" -}

module Cardano.CLI.Options.Debug
( parseDebugCmds
) where

import Cardano.Api.Shelley hiding (QueryInShelleyBasedEra (..))

import Cardano.CLI.Commands.Debug
import Cardano.CLI.Commands.Debug.LogEpochState
import Cardano.CLI.Environment
import Cardano.CLI.EraBased.Options.Common

import Data.Foldable
import Options.Applicative hiding (help, str)
import qualified Options.Applicative as Opt

parseDebugCmds :: EnvCli -> Parser DebugCmds
parseDebugCmds envCli =
Opt.hsubparser $ mconcat
[ Opt.metavar "debug commands"
, Opt.commandGroup "debug commands"
, Opt.command "debug"
$ Opt.info (pDebugCmds envCli)
$ Opt.progDesc "Debug commands"
]

pDebugCmds :: EnvCli -> Parser DebugCmds
pDebugCmds envCli =
asum
[ subParser "log-epoch-state"
$ Opt.info pLogEpochStateCmdArgs
$ Opt.progDesc
$ mconcat
[ "Log epoch state of a running node."
, " This command will connect to a local node and log the epoch state to a file."
, " The log file format is line delimited JSON."
, " The command will not terminate."
]
]
where
pLogEpochStateCmdArgs :: Parser DebugCmds
pLogEpochStateCmdArgs =
fmap DebugLogEpochStateCmd $
LogEpochStateCmdArgs
<$> pSocketPath envCli
<*> pNodeConfigurationFileIn
<*> pFileOutDirection "out-file" "Output filepath of the log file. The log file format is line delimited JSON."

pNodeConfigurationFileIn :: Parser (NodeConfigFile In)
pNodeConfigurationFileIn =
fmap File $ Opt.strOption $ mconcat
[ Opt.long "node-configuration-file"
, Opt.metavar "FILE"
, Opt.help "Input filepath of the node configuration file."
, Opt.completer (Opt.bashCompleter "file")
]
2 changes: 2 additions & 0 deletions cardano-cli/src/Cardano/CLI/Options/Ping.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{-# LANGUAGE TypeApplications #-}

{- HLINT ignore "Move brackets to avoid $" -}

module Cardano.CLI.Options.Ping
( parsePingCmd
) where
Expand Down
24 changes: 24 additions & 0 deletions cardano-cli/src/Cardano/CLI/Orphans.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{-# OPTIONS_GHC -Wno-orphans #-}

module Cardano.CLI.Orphans
(
) where

import Cardano.Api

import qualified Cardano.Ledger.Api as L
import qualified Cardano.Ledger.Shelley.LedgerState as L

import Data.Aeson

-- TODO upstream this orphaned instance to the ledger
instance (L.EraTxOut ledgerera, L.EraGov ledgerera) => ToJSON (L.NewEpochState ledgerera) where
toJSON (L.NewEpochState nesEL nesBprev nesBCur nesEs nesRu nesPd _stashedAvvm)=
object
[ "currentEpoch" .= nesEL
, "priorBlocks" .= nesBprev
, "currentEpochBlocks" .= nesBCur
, "currentEpochState" .= nesEs
, "rewardUpdate" .= nesRu
, "currentStakeDistribution" .= nesPd
]
6 changes: 6 additions & 0 deletions cardano-cli/src/Cardano/CLI/Run.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Cardano.CLI.EraBased.Run
import Cardano.CLI.Legacy.Commands
import Cardano.CLI.Legacy.Run (runLegacyCmds)
import Cardano.CLI.Render (customRenderHelp)
import Cardano.CLI.Run.Debug
import Cardano.CLI.Run.Ping (PingClientCmdError (..), renderPingClientCmdError,
runPingCmd)
import Cardano.CLI.Types.Errors.CmdError
Expand Down Expand Up @@ -45,6 +46,7 @@ data ClientCommandErrors
= ByronClientError ByronClientCmdError
| CmdError Text CmdError
| PingClientError PingClientCmdError
| DebugCmdError DebugCmdError

runClientCommand :: ClientCommand -> ExceptT ClientCommandErrors IO ()
runClientCommand = \case
Expand All @@ -56,6 +58,8 @@ runClientCommand = \case
firstExceptT (CmdError (renderLegacyCommand cmds)) $ runLegacyCmds cmds
CliPingCommand cmds ->
firstExceptT PingClientError $ runPingCmd cmds
CliDebugCmds cmds ->
firstExceptT DebugCmdError $ runDebugCmds cmds
Help pprefs allParserInfo ->
runHelp pprefs allParserInfo
DisplayVersion ->
Expand All @@ -69,6 +73,8 @@ renderClientCommandError = \case
renderByronClientCmdError err
PingClientError err ->
renderPingClientCmdError err
DebugCmdError err ->
renderDebugCmdError err

runDisplayVersion :: ExceptT ClientCommandErrors IO ()
runDisplayVersion = do
Expand Down
24 changes: 24 additions & 0 deletions cardano-cli/src/Cardano/CLI/Run/Debug.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{-# LANGUAGE LambdaCase #-}

module Cardano.CLI.Run.Debug
( DebugCmdError(..)
, runLogEpochStateCmd
, runDebugCmds
, renderDebugCmdError
) where

import Cardano.CLI.Commands.Debug
import Cardano.CLI.Run.Debug.LogEpochState

import Control.Monad.IO.Class
import Control.Monad.Trans.Except
import Prettyprinter

data DebugCmdError = DebugCmdFailed

runDebugCmds :: DebugCmds -> ExceptT DebugCmdError IO ()
runDebugCmds = \case
DebugLogEpochStateCmd cmd -> liftIO $ runLogEpochStateCmd cmd

renderDebugCmdError :: DebugCmdError -> Doc ann
renderDebugCmdError DebugCmdFailed = "Debug command failed"
44 changes: 44 additions & 0 deletions cardano-cli/src/Cardano/CLI/Run/Debug/LogEpochState.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Cardano.CLI.Run.Debug.LogEpochState
( runLogEpochStateCmd
) where

import Cardano.Api
import qualified Cardano.Api as Api

import Cardano.CLI.Commands.Debug.LogEpochState
import Cardano.CLI.Orphans ()

import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Lazy as LBS
import qualified System.IO as IO

runLogEpochStateCmd
:: LogEpochStateCmdArgs
-> IO ()
runLogEpochStateCmd
LogEpochStateCmdArgs
{ nodeSocketPath
, configurationFile
, outputFilePath = File outputFilePath
} = do
LBS.appendFile outputFilePath ""

result <- runExceptT $ foldEpochState
configurationFile
nodeSocketPath
Api.QuickValidation
(EpochNo maxBound)
()
(\(AnyNewEpochState sbe nes) _ _ -> do
liftIO $ LBS.appendFile outputFilePath
$ shelleyBasedEraConstraints sbe (Aeson.encode nes) <> "\n"
pure ConditionNotMet
)

case result of
Right _ -> pure ()
Left e -> IO.hPutStrLn IO.stderr $ "Error: " <> show e
11 changes: 11 additions & 0 deletions cardano-cli/test/cardano-cli-golden/files/golden/help.cli
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Usage: cardano-cli
| Legacy commands
| byron
| ping
| debug commands
| version
)

Expand Down Expand Up @@ -12369,6 +12370,16 @@ Usage: cardano-cli ping [-c|--count COUNT]

Ping a cardano node either using node-to-node or node-to-client protocol. It negotiates a handshake and keeps sending keep alive messages.

Usage: cardano-cli debug log-epoch-state

Debug commands

Usage: cardano-cli debug log-epoch-state --socket-path SOCKET_PATH
--node-configuration-file FILE
--out-file FILE

Log epoch state.

Usage: cardano-cli genesis --genesis-output-dir FILEPATH
--start-time POSIXSECONDS
--protocol-parameters-file FILEPATH
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Usage: cardano-cli debug log-epoch-state --socket-path SOCKET_PATH
--node-configuration-file FILE
--out-file FILE

Log epoch state.

Available options:
--socket-path SOCKET_PATH
Path to the node socket. This overrides the
CARDANO_NODE_SOCKET_PATH environment variable. The
argument is optional if CARDANO_NODE_SOCKET_PATH is
defined and mandatory otherwise.
--node-configuration-file FILE
Input filepath of the node configuration file.
--out-file FILE Output filepath of the log file. The log file format
is line delimited JSON.
-h,--help Show this help text

0 comments on commit 928aac5

Please sign in to comment.