11{-# LANGUAGE DeriveAnyClass #-}
2+ {-# LANGUAGE DeriveDataTypeable #-}
23{-# LANGUAGE RankNTypes #-}
34{-# LANGUAGE TemplateHaskell #-}
45
@@ -9,6 +10,7 @@ module BotPlutusInterface.Types (
910 LogContext (.. ),
1011 LogLevel (.. ),
1112 LogType (.. ),
13+ LogLine (.. ),
1214 ContractEnvironment (.. ),
1315 Tip (Tip , epoch , hash , slot , block , era , syncProgress ),
1416 ContractState (.. ),
@@ -30,6 +32,7 @@ module BotPlutusInterface.Types (
3032 addBudget ,
3133 readCollateralUtxo ,
3234 collateralValue ,
35+ sufficientLogLevel ,
3336) where
3437
3538import Cardano.Api (NetworkId (Testnet ), NetworkMagic (.. ), ScriptExecutionError , ScriptWitnessIndex )
@@ -38,8 +41,10 @@ import Control.Concurrent.STM (TVar, readTVarIO)
3841import Data.Aeson (ToJSON )
3942import Data.Aeson qualified as JSON
4043import Data.Aeson.TH (Options (.. ), defaultOptions , deriveJSON )
44+ import Data.Data (Data (toConstr ), constrIndex , dataTypeOf , eqT , fromConstrB , indexConstr , type (:~: ) (Refl ))
4145import Data.Default (Default (def ))
4246import Data.Kind (Type )
47+ import Data.List (intersect )
4348import Data.Map (Map )
4449import Data.Map qualified as Map
4550import Data.Text (Text )
@@ -177,13 +182,29 @@ newtype ContractStats = ContractStats
177182instance Show (TVar ContractStats ) where
178183 show _ = " <ContractStats>"
179184
180- -- | List of string logs.
185+ {- | Single log message
186+ Defined for pretty instance.
187+ -}
188+ data LogLine = LogLine
189+ { logLineContext :: LogContext
190+ , logLineLevel :: LogLevel
191+ , logLineMsg :: PP. Doc ()
192+ }
193+ deriving stock (Show )
194+
195+ instance Pretty LogLine where
196+ pretty (LogLine msgCtx msgLogLvl msg) = pretty msgCtx <+> pretty msgLogLvl <+> PP. unAnnotate msg
197+
198+ -- | List of logs.
181199newtype LogsList = LogsList
182- { getLogsList :: [( LogContext , LogLevel , PP. Doc () ) ]
200+ { getLogsList :: [LogLine ]
183201 }
184202 deriving stock (Show )
185203 deriving newtype (Semigroup , Monoid )
186204
205+ instance Pretty LogsList where
206+ pretty = PP. vcat . map pretty . getLogsList
207+
187208instance Show (TVar LogsList ) where
188209 show _ = " <ContractLogs>"
189210
@@ -252,7 +273,7 @@ data LogType
252273 | CollateralLog
253274 | PABLog
254275 | AnyLog
255- deriving stock (Eq , Ord , Show )
276+ deriving stock (Eq , Ord , Show , Data )
256277
257278instance Pretty LogType where
258279 pretty CoinSelectionLog = " CoinSelection"
@@ -267,7 +288,16 @@ data LogLevel
267288 | Notice { ltLogTypes :: [LogType ]}
268289 | Info { ltLogTypes :: [LogType ]}
269290 | Debug { ltLogTypes :: [LogType ]}
270- deriving stock (Eq , Ord , Show )
291+ deriving stock (Eq , Show , Data )
292+
293+ instance Enum LogLevel where
294+ fromEnum = (\ a -> a - 1 ) . constrIndex . toConstr
295+ toEnum = fromConstrB field . indexConstr (dataTypeOf $ Notice [] ) . (+ 1 )
296+ where
297+ field :: forall a . Data a => a
298+ field = case eqT :: Maybe (a :~: [LogType ]) of
299+ Just Refl -> [AnyLog ]
300+ Nothing -> error " Expected a value of type LogType."
271301
272302instance Pretty LogLevel where
273303 pretty = \ case
@@ -277,6 +307,18 @@ instance Pretty LogLevel where
277307 Warn a -> " [WARNING " <> pretty a <> " ]"
278308 Error a -> " [ERROR " <> pretty a <> " ]"
279309
310+ {- | if sufficientLogLevel settingLogLevel msgLogLvl
311+ then message should be displayed with this log level setting.
312+ -}
313+ sufficientLogLevel :: LogLevel -> LogLevel -> Bool
314+ sufficientLogLevel logLevelSetting msgLogLvl =
315+ msgLogLvl `constrLEq` logLevelSetting -- the log is important enough
316+ && not (null intersectLogTypes) -- log is of type we're interested in
317+ where
318+ intersectLogTypes = ltLogTypes logLevelSetting `intersect` (ltLogTypes msgLogLvl <> [AnyLog ])
319+
320+ constrLEq a b = fromEnum a <= fromEnum b
321+
280322data LogContext = BpiLog | ContractLog
281323 deriving stock (Bounded , Enum , Eq , Ord , Show )
282324
0 commit comments