1
1
{-# LANGUAGE OverloadedRecordDot #-}
2
- {-# OPTIONS_GHC -Wno-deprecations #-}
3
2
4
3
module Main where
5
4
@@ -12,27 +11,68 @@ import Control.Lens ((^?))
12
11
import Control.Monad (foldM )
13
12
import Data.Aeson (eitherDecode' )
14
13
import Data.Aeson.Lens (key , _String )
15
- import Data.ByteString.Lazy.Char8 qualified as C8
16
14
import Data.Text.Encoding (encodeUtf8 )
17
15
import Hydra.Chain (ChainEvent (.. ))
18
16
import Hydra.HeadLogic (Effect (.. ), Input (.. ), Outcome (.. ), StateChanged (.. ))
19
17
import Hydra.Logging (Envelope (.. ))
20
18
import Hydra.Logging.Messages (HydraLog (.. ))
21
19
import Hydra.Node (HydraNodeLog (.. ))
22
20
23
- data InfoLine = InfoLine { header :: Text , line :: Text , color :: Text } deriving (Eq , Show )
21
+ data InfoLine = InfoLine { toplabel :: LogType , details :: Text } deriving (Eq , Show )
24
22
25
23
data Decoded tx
26
24
= DecodedHydraLog { t :: UTCTime , n :: Text , info :: InfoLine }
27
25
| DropLog
28
26
deriving (Eq , Show )
29
27
28
+ -- | This instance is needed to sort results by timestamp
30
29
instance Ord (Decoded tx ) where
31
30
compare DropLog DropLog = EQ
32
31
compare DropLog DecodedHydraLog {} = LT
33
32
compare DecodedHydraLog {} DropLog = GT
34
33
compare (DecodedHydraLog t1 _ _) (DecodedHydraLog t2 _ _) = compare t1 t2
35
34
35
+ -- | Log type labels for visualization
36
+ data LogType
37
+ = NodeOptionsLabel
38
+ | ClientSentLabel
39
+ | ObservationLabel
40
+ | NetworkLabel
41
+ | ChainEffectLabel
42
+ | ErrorLabel
43
+ | LogicLabel Text
44
+ | LogicError Text
45
+ | Other Text
46
+ deriving (Eq , Show )
47
+
48
+ labelLog :: LogType -> Text
49
+ labelLog NodeOptionsLabel = " NODE OPTIONS"
50
+ labelLog ClientSentLabel = " CLIENT SENT"
51
+ labelLog ObservationLabel = " OBSERVATION"
52
+ labelLog NetworkLabel = " NETWORK EFFECT"
53
+ labelLog ChainEffectLabel = " POSTING TX"
54
+ labelLog ErrorLabel = " ERROR"
55
+ labelLog (LogicLabel t) = unlines [" LOGIC" , t]
56
+ labelLog (LogicError t) = unlines [" LOGIC ERROR" , t]
57
+ labelLog (Other t) = unlines [" OTHER" , t]
58
+
59
+ colorLog :: LogType -> Text
60
+ colorLog = \ case
61
+ NodeOptionsLabel -> green
62
+ ClientSentLabel -> green
63
+ ObservationLabel -> blue
64
+ NetworkLabel -> magenta
65
+ ChainEffectLabel -> blue
66
+ ErrorLabel -> red
67
+ LogicLabel t -> case t of
68
+ " DepositExpired" -> red
69
+ " DecommitInvalid" -> red
70
+ " IgnoredHeadInitializing" -> red
71
+ " TxInvalid" -> red
72
+ _ -> cyan
73
+ LogicError _ -> red
74
+ Other _ -> green
75
+
36
76
main :: IO ()
37
77
main = visualize [" ../devnet/alice-logs.txt" , " ../devnet/bob-logs.txt" ]
38
78
@@ -42,95 +82,117 @@ visualize paths = do
42
82
runConduitRes $
43
83
mapM_ sourceFileBS paths
44
84
.| linesUnboundedAsciiC
45
- .| mapMC
46
- ( \ l ->
47
- case l ^? key " message" . _String of
48
- Nothing -> P. error " Failed to find key 'message' which was expected"
49
- Just line ->
50
- let envelope = fromStrict $ encodeUtf8 line
51
- in case decodeAs envelope (undefined :: Envelope (HydraLog Tx )) of
52
- Left e -> P. error $ show e <> line
53
- Right decoded ->
54
- case decoded. message of
55
- NodeOptions opt -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " NODE OPTIONS" (show opt) green)
56
- Node msg ->
57
- case msg of
58
- BeginInput {input} ->
59
- case input of
60
- ClientInput {clientInput} ->
61
- pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " CLIENT SENT" (show clientInput) green)
62
- NetworkInput {} -> pure DropLog
63
- ChainInput {chainEvent} ->
64
- case chainEvent of
65
- Observation {observedTx} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " OBESERVATION" (show observedTx) blue)
66
- Rollback {} -> pure DropLog
67
- Tick {} -> pure DropLog
68
- PostTxError {postTxError} ->
69
- pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " ERROR" (show postTxError) red)
70
- EndInput {} -> pure DropLog
71
- BeginEffect {effect} ->
72
- case effect of
73
- ClientEffect {} -> pure DropLog
74
- NetworkEffect {message} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " NETWORK EFFECT" (show message) magenta)
75
- OnChainEffect {postChainTx} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " POSTING" (show postChainTx) blue)
76
- EndEffect {} -> pure DropLog
77
- LogicOutcome {outcome} ->
78
- case outcome of
79
- Continue {stateChanges} ->
80
- foldM
81
- ( \ b a -> case a of
82
- HeadInitialized {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " HeadInitialized" " " cyan)
83
- HeadOpened {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " HeadOpened" " " cyan)
84
- CommittedUTxO {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " CommittedUTxO" " " cyan)
85
- HeadAborted {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " HeadAborted" " " red)
86
- SnapshotRequestDecided {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " SnapshotRequestDecided" " " cyan)
87
- SnapshotRequested {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " SnapshotRequested" " " cyan)
88
- PartySignedSnapshot {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " PartySignedSnapshot" " " cyan)
89
- SnapshotConfirmed {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " SnapshotConfirmed" " " cyan)
90
- DepositRecorded {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DepositRecorded" " " cyan)
91
- DepositActivated {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DepositActivated" " " cyan)
92
- DepositExpired {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DepositExpired" " " red)
93
- DepositRecovered {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DepositRecovered" " " cyan)
94
- CommitApproved {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " CommitApproved" " " cyan)
95
- CommitFinalized {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " CommitFinalized" " " cyan)
96
- DecommitRecorded {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DecommitRecorded" " " cyan)
97
- DecommitApproved {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DecommitApproved" " " cyan)
98
- DecommitInvalid {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DecommitInvalid" " " red)
99
- DecommitFinalized {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " DecommitFinalized" " " cyan)
100
- HeadClosed {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " HeadClosed" " " green)
101
- HeadContested {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " HeadContested" " " cyan)
102
- HeadIsReadyToFanout {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " HeadIsReadyToFanout" " " cyan)
103
- HeadFannedOut {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " HeadFannedOut" " " cyan)
104
- IgnoredHeadInitializing {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " IgnoredHeadInitializing" " " red)
105
- TxInvalid {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " TxInvalid" " " red)
106
- _ -> pure b
107
- )
108
- DropLog
109
- stateChanges
110
- Wait {} -> pure DropLog
111
- Error {error = err} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " LOGIC ERROR" (show err) red)
112
- DroppedFromQueue {} -> pure DropLog
113
- LoadingState -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " Loading state..." " " green)
114
- LoadedState {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " Loaded." " " green)
115
- ReplayingState -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " Replaying state..." " " green)
116
- Misconfiguration {} -> pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine " MISCONFIG!" " " red)
117
- _ -> pure DropLog
118
- )
85
+ .| mapMC decodeAndProcess
119
86
.| filterC (/= DropLog )
120
87
.| sinkList
121
- forM_ (sort decodedLines) $ \ l ->
122
- render l
123
88
124
- decodeAs :: forall a . FromJSON a => C8. ByteString -> a -> Either String a
125
- decodeAs l _ =
126
- case eitherDecode' l :: Either String a of
127
- Left e -> Left e
128
- Right decoded -> pure decoded
89
+ forM_ (sort decodedLines) render
90
+
91
+ decodeAndProcess :: ByteString -> ResourceT IO (Decoded Tx )
92
+ decodeAndProcess l =
93
+ case l ^? key " message" . _String of
94
+ Nothing -> P. error " Failed to find key 'message' which was expected"
95
+ Just line ->
96
+ let envelope = fromStrict $ encodeUtf8 line
97
+ in case eitherDecode' envelope :: Either String (Envelope (HydraLog Tx )) of
98
+ Left e -> P. error $ " Decoding failed" <> show e <> " for line: " <> line
99
+ Right decoded -> lift $ processLogs decoded
100
+
101
+ -- | Ideally we would have Data instances for all types so we could get data type String representation
102
+ -- instead of providing strings but that would add some compilation time overhead so not worth it.
103
+ processLogs :: Envelope (HydraLog Tx ) -> IO (Decoded Tx )
104
+ processLogs decoded =
105
+ case decoded. message of
106
+ NodeOptions opt -> logIt NodeOptionsLabel (show opt)
107
+ Node msg ->
108
+ case msg of
109
+ BeginInput {input} ->
110
+ case input of
111
+ ClientInput {clientInput} -> logIt ClientSentLabel (show clientInput)
112
+ NetworkInput {} -> pure DropLog
113
+ ChainInput {chainEvent} ->
114
+ case chainEvent of
115
+ Observation {observedTx} -> logIt ObservationLabel (show observedTx)
116
+ Rollback {} -> pure DropLog
117
+ Tick {} -> pure DropLog
118
+ PostTxError {postTxError} -> logIt ErrorLabel (show postTxError)
119
+ EndInput {} -> pure DropLog
120
+ BeginEffect {effect} ->
121
+ case effect of
122
+ ClientEffect {} -> pure DropLog
123
+ NetworkEffect {message} -> logIt NetworkLabel (show message)
124
+ OnChainEffect {postChainTx} -> logIt ChainEffectLabel (show postChainTx)
125
+ EndEffect {} -> pure DropLog
126
+ LogicOutcome {outcome} ->
127
+ case outcome of
128
+ Continue {stateChanges} ->
129
+ foldM
130
+ ( \ _ a -> case a of
131
+ HeadInitialized {} -> logIt (LogicLabel " HeadInitialized" ) " "
132
+ HeadOpened {} -> logIt (LogicLabel " HeadOpened" ) " "
133
+ CommittedUTxO {} -> logIt (LogicLabel " CommittedUTxO" ) " "
134
+ HeadAborted {} -> logIt (LogicLabel " HeadAborted" ) " "
135
+ SnapshotRequestDecided {} -> logIt (LogicLabel " SnapshotRequestDecided" ) " "
136
+ SnapshotRequested {} -> logIt (LogicLabel " SnapshotRequested" ) " "
137
+ PartySignedSnapshot {} -> logIt (LogicLabel " PartySignedSnapshot" ) " "
138
+ SnapshotConfirmed {} -> logIt (LogicLabel " SnapshotConfirmed" ) " "
139
+ DepositRecorded {} -> logIt (LogicLabel " DepositRecorded" ) " "
140
+ DepositActivated {} -> logIt (LogicLabel " DepositActivated" ) " "
141
+ DepositExpired {} -> logIt (LogicLabel " DepositExpired" ) " "
142
+ DepositRecovered {} -> logIt (LogicLabel " DepositRecovered" ) " "
143
+ CommitApproved {} -> logIt (LogicLabel " CommitApproved" ) " "
144
+ CommitFinalized {} -> logIt (LogicLabel " CommitFinalized" ) " "
145
+ DecommitRecorded {} -> logIt (LogicLabel " DecommitRecorded" ) " "
146
+ DecommitApproved {} -> logIt (LogicLabel " DecommitApproved" ) " "
147
+ DecommitInvalid {} -> logIt (LogicLabel " DecommitInvalid" ) " "
148
+ DecommitFinalized {} -> logIt (LogicLabel " DecommitFinalized" ) " "
149
+ HeadClosed {} -> logIt (LogicLabel " HeadClosed" ) " "
150
+ HeadContested {} -> logIt (LogicLabel " HeadContested" ) " "
151
+ HeadIsReadyToFanout {} -> logIt (LogicLabel " HeadIsReadyToFanout" ) " "
152
+ HeadFannedOut {} -> logIt (LogicLabel " HeadFannedOut" ) " "
153
+ IgnoredHeadInitializing {} -> logIt (LogicLabel " IgnoredHeadInitializing" ) " "
154
+ TxInvalid {} -> logIt (LogicLabel " TxInvalid" ) " "
155
+ NetworkConnected {} -> pure DropLog
156
+ NetworkDisconnected {} -> pure DropLog
157
+ PeerConnected {} -> pure DropLog
158
+ PeerDisconnected {} -> pure DropLog
159
+ NetworkVersionMismatch {} -> pure DropLog
160
+ NetworkClusterIDMismatch {} -> pure DropLog
161
+ TransactionReceived {} -> pure DropLog
162
+ TransactionAppliedToLocalUTxO {} -> pure DropLog
163
+ ChainRolledBack {} -> pure DropLog
164
+ TickObserved {} -> pure DropLog
165
+ LocalStateCleared {} -> pure DropLog
166
+ Checkpoint {} -> pure DropLog
167
+ )
168
+ DropLog
169
+ stateChanges
170
+ Wait {} -> pure DropLog
171
+ Error {error = err} -> logIt (LogicError " LOGIC ERROR" ) (show err)
172
+ DroppedFromQueue {} -> pure DropLog
173
+ LoadingState -> logIt (Other " Loading state..." ) " "
174
+ LoadedState {} -> logIt (Other " Loaded." ) " "
175
+ ReplayingState -> logIt (Other " Replaying state..." ) " "
176
+ Misconfiguration {} -> logIt (Other " MISCONFIG!" ) " "
177
+ _ -> pure DropLog
178
+ where
179
+ logIt :: LogType -> Text -> IO (Decoded Tx )
180
+ logIt l s =
181
+ pure $ DecodedHydraLog decoded. timestamp decoded. namespace (InfoLine l s)
129
182
130
183
render :: Decoded tx -> IO ()
131
184
render = \ case
132
- DecodedHydraLog {t, n, info = InfoLine {header, line, color}} -> do
133
- putTextLn $ color <> unlines [" [" <> show t <> " ]" , " NAMESPACE:" <> show n, header, line] <> reset
185
+ DecodedHydraLog {t, n, info = InfoLine {toplabel, details}} -> do
186
+ putTextLn $
187
+ unlines
188
+ [ " -----------------------------------"
189
+ , " [" <> show t <> " ]"
190
+ , " NAMESPACE:" <> show n
191
+ , colorLog toplabel
192
+ , labelLog toplabel
193
+ , details
194
+ , reset
195
+ ]
134
196
DropLog -> putTextLn " "
135
197
136
198
-- ANSI escape codes for colors
0 commit comments