11{-# LANGUAGE RecordWildCards #-}
2+ {-# LANGUAGE TupleSections #-}
23
34module Cardano.Node.Tracing.Tracers.BlockReplayProgress
45 ( withReplayedBlock
@@ -14,42 +15,58 @@ import qualified Ouroboros.Consensus.Storage.LedgerDB as LedgerDB
1415import Ouroboros.Network.Block (pointSlot , unSlotNo )
1516import Ouroboros.Network.Point (withOrigin )
1617
17- import Control.Monad.IO.Class ( MonadIO )
18+ import Control.Concurrent.MVar
1819import Data.Aeson (Value (String ), (.=) )
1920import Data.Text (pack )
2021
22+ newtype ReplayBlockState = ReplayBlockState
23+ { -- | Last slot for which a `ReplayBlockStats` message has been issued.
24+ rpsLastSlot :: Maybe SlotNo
25+ }
26+
2127data ReplayBlockStats = ReplayBlockStats
22- { rpsDisplay :: Bool
23- , rpsCurSlot :: SlotNo
28+ { rpsCurSlot :: SlotNo
2429 , rpsGoalSlot :: SlotNo
25- , rpsProgress :: Double
26- , rpsLastProgress :: Double
2730 }
2831
29- emptyReplayBlockStats :: ReplayBlockStats
30- emptyReplayBlockStats = ReplayBlockStats False 0 0 0.0 0.0
32+ initialReplayBlockState :: ReplayBlockState
33+ initialReplayBlockState = ReplayBlockState {rpsLastSlot = Nothing }
34+
35+ progressForMachine :: ReplayBlockStats -> Double
36+ progressForMachine (ReplayBlockStats curSlot goalSlot) =
37+ (fromIntegral (unSlotNo curSlot) * 100.0 ) / fromIntegral (unSlotNo $ max curSlot goalSlot)
38+
39+ progressForHuman :: ReplayBlockStats -> Double
40+ progressForHuman = round2 . progressForMachine where
41+ round2 :: Double -> Double
42+ round2 num =
43+ let
44+ f :: Int
45+ f = round $ num * 100
46+ in fromIntegral f / 100
3147
3248--------------------------------------------------------------------------------
3349-- ReplayBlockStats Tracer
3450--------------------------------------------------------------------------------
3551
3652instance LogFormatting ReplayBlockStats where
37- forMachine _dtal ReplayBlockStats { .. } =
53+ forMachine _ stats =
3854 mconcat
3955 [ " kind" .= String " ReplayBlockStats"
40- , " progress" .= String (pack $ show rpsProgress )
56+ , " progress" .= String (pack $ show $ progressForMachine stats )
4157 ]
42- forHuman ReplayBlockStats {.. } = " Replayed block: slot " <> textShow (unSlotNo rpsCurSlot) <> " out of " <> textShow (unSlotNo rpsGoalSlot) <> " . Progress: " <> textShow (round2 rpsProgress) <> " %"
43- where
44- round2 :: Double -> Double
45- round2 num =
46- let
47- f :: Int
48- f = round $ num * 100
49- in fromIntegral f / 100
50-
51- asMetrics ReplayBlockStats {.. } =
52- [DoubleM " blockReplayProgress" rpsProgress]
58+
59+ forHuman stats@ ReplayBlockStats {.. } =
60+ " Replayed block: slot "
61+ <> textShow (unSlotNo rpsCurSlot)
62+ <> " out of "
63+ <> textShow (unSlotNo rpsGoalSlot)
64+ <> " . Progress: "
65+ <> textShow (progressForHuman stats)
66+ <> " %"
67+
68+ asMetrics stats =
69+ [DoubleM " blockReplayProgress" (progressForMachine stats)]
5370
5471instance MetaTrace ReplayBlockStats where
5572 namespaceFor ReplayBlockStats {} = Namespace [] [" LedgerReplay" ]
@@ -71,28 +88,31 @@ instance MetaTrace ReplayBlockStats where
7188
7289withReplayedBlock :: Trace IO ReplayBlockStats
7390 -> IO (Trace IO (ChainDB. TraceEvent blk ))
74- withReplayedBlock tr =
75- let tr' = filterTrace filterFunction tr
76- tr'' = contramap unfold tr'
77- in foldTraceM replayBlockStats emptyReplayBlockStats tr''
91+ withReplayedBlock tr = do
92+ var <- newMVar initialReplayBlockState
93+ contramapMCond tr (process var)
7894 where
79- filterFunction(_, ReplayBlockStats {.. }) = rpsDisplay
80-
81- replayBlockStats :: MonadIO m
82- => ReplayBlockStats
83- -> LoggingContext
84- -> ChainDB. TraceEvent blk
85- -> m ReplayBlockStats
86- replayBlockStats ReplayBlockStats {.. } _context
87- (ChainDB. TraceLedgerDBEvent
88- (LedgerDB. LedgerReplayEvent
89- (LedgerDB. TraceReplayProgressEvent
90- (LedgerDB. ReplayedBlock pt [] _ (LedgerDB. ReplayGoal replayTo))))) = do
91- let slotno = realPointSlot pt
92- endslot = withOrigin 0 id $ pointSlot replayTo
93- progress' = (fromIntegral (unSlotNo slotno) * 100.0 ) / fromIntegral (unSlotNo $ max slotno endslot)
94- pure $ if (progress' == 0.0 && not rpsDisplay)
95- || ((progress' - rpsLastProgress) > 0.1 )
96- then ReplayBlockStats True slotno endslot progress' progress'
97- else ReplayBlockStats False slotno endslot progress' rpsLastProgress
98- replayBlockStats st@ ReplayBlockStats {} _context _ = pure st
95+ process :: MVar ReplayBlockState
96+ -> (LoggingContext , Either TraceControl (ChainDB. TraceEvent blk ))
97+ -> IO (Maybe (LoggingContext , Either TraceControl ReplayBlockStats ))
98+ process var (ctx, Right msg) = modifyMVar var $ \ st -> do
99+ let (st', mbStats) = mbProduceBlockStats msg st
100+ pure (st', fmap ((ctx,) . Right ) mbStats)
101+ process _ (ctx, Left control) = pure (Just (ctx, Left control))
102+
103+ mbProduceBlockStats :: ChainDB. TraceEvent blk -> ReplayBlockState -> (ReplayBlockState , Maybe ReplayBlockStats )
104+ mbProduceBlockStats
105+ (ChainDB. TraceLedgerDBEvent
106+ (LedgerDB. LedgerReplayEvent
107+ (LedgerDB. TraceReplayProgressEvent
108+ (LedgerDB. ReplayedBlock curSlot [] _ (LedgerDB. ReplayGoal replayToSlot)))))
109+ st@ (ReplayBlockState mLastSlot) =
110+ let curSlotNo = realPointSlot curSlot
111+ goalSlotNo = withOrigin 0 id $ pointSlot replayToSlot
112+ stats = ReplayBlockStats curSlotNo goalSlotNo
113+ progressFor soFar goal = progressForHuman (ReplayBlockStats soFar goal)
114+ shouldEmit = maybe True (\ lastSlot -> progressFor curSlotNo goalSlotNo - progressFor lastSlot goalSlotNo >= 0.01 ) mLastSlot
115+ in if shouldEmit
116+ then (ReplayBlockState (Just curSlotNo), Just stats)
117+ else (st, Nothing )
118+ mbProduceBlockStats _ st = (st, Nothing )
0 commit comments