5
5
6
6
module Booster.Log (module Booster.Log ) where
7
7
8
- import Booster.Definition.Attributes.Base
9
- import Booster.Definition.Base (RewriteRule (.. ), SourceRef (.. ), sourceRef )
10
- import Booster.Pattern.Base (
11
- Pattern (.. ),
12
- Predicate (.. ),
13
- Term (.. ),
14
- TermAttributes (hash ),
15
- pattern AndTerm ,
16
- )
17
- import Booster.Prettyprinter (renderOneLineText )
18
- import Booster.Syntax.Json (KorePattern , prettyPattern )
8
+ import Control.Monad (when )
19
9
import Control.Monad.IO.Class
20
- import Control.Monad.Logger (
21
- LogLevel (.. ),
22
- MonadLogger ,
23
- MonadLoggerIO (askLoggerIO ),
24
- NoLoggingT ,
25
- ToLogStr (toLogStr ),
26
- defaultLoc ,
27
- )
10
+ import Control.Monad.Logger qualified
28
11
import Control.Monad.Trans.Class qualified as Trans
29
12
import Control.Monad.Trans.Except (ExceptT (.. ))
30
13
import Control.Monad.Trans.Maybe (MaybeT (.. ))
31
14
import Control.Monad.Trans.Reader (ReaderT (.. ), ask , withReaderT )
32
15
import Control.Monad.Trans.State (StateT (.. ))
33
16
import Control.Monad.Trans.State.Strict qualified as Strict
17
+ import Data.Aeson (ToJSON (.. ), Value (.. ), (.=) )
18
+ import Data.Aeson.Encode.Pretty (Config (confIndent ), Indent (Spaces ), encodePretty' )
19
+ import Data.Aeson.Key qualified as Key
20
+ import Data.Aeson.Types (object )
34
21
import Data.Coerce (coerce )
35
22
import Data.Data (Proxy (.. ))
36
23
import Data.Hashable qualified
@@ -42,15 +29,28 @@ import Data.Text (Text, pack)
42
29
import Data.Text.Lazy qualified as LazyText
43
30
import GHC.Exts (IsString (.. ))
44
31
import GHC.TypeLits (KnownSymbol , symbolVal )
45
- import Kore.Util (showHashHex )
46
32
import Prettyprinter (Pretty , pretty )
47
33
34
+ import Booster.Definition.Attributes.Base
35
+ import Booster.Definition.Base (RewriteRule (.. ), SourceRef (.. ), sourceRef )
36
+ import Booster.Pattern.Base (
37
+ Pattern (.. ),
38
+ Predicate (.. ),
39
+ Term (.. ),
40
+ TermAttributes (hash ),
41
+ pattern AndTerm ,
42
+ )
43
+ import Booster.Prettyprinter (renderOneLineText )
44
+ import Booster.Syntax.Json (KorePattern , addHeader , prettyPattern )
45
+ import Booster.Syntax.Json.Externalise (externaliseTerm )
46
+ import Kore.JsonRpc.Types (rpcJsonConfig )
47
+ import Kore.Util (showHashHex )
48
+
48
49
newtype Logger a = Logger (a -> IO () )
49
50
50
51
class ToLogFormat a where
51
52
toTextualLog :: a -> Text
52
-
53
- -- toJSONLog :: a -> Value
53
+ toJSONLog :: a -> Value
54
54
55
55
data LogContext = forall a . ToLogFormat a => LogContext a
56
56
@@ -60,7 +60,7 @@ instance IsString LogContext where
60
60
data LogMessage where
61
61
LogMessage :: ToLogFormat a => [LogContext ] -> a -> LogMessage
62
62
63
- class MonadLoggerIO m => LoggerMIO m where
63
+ class MonadIO m => LoggerMIO m where
64
64
getLogger :: m (Logger LogMessage )
65
65
default getLogger :: (Trans. MonadTrans t , LoggerMIO n , m ~ t n ) => m (Logger LogMessage )
66
66
getLogger = Trans. lift getLogger
@@ -78,7 +78,7 @@ instance LoggerMIO m => LoggerMIO (StateT s m) where
78
78
instance LoggerMIO m => LoggerMIO (Strict. StateT s m ) where
79
79
withLogger modL (Strict. StateT m) = Strict. StateT $ \ s -> withLogger modL $ m s
80
80
81
- instance MonadIO m => LoggerMIO (NoLoggingT m ) where
81
+ instance MonadIO m => LoggerMIO (Control.Monad.Logger. NoLoggingT m ) where
82
82
getLogger = pure $ Logger $ \ _ -> pure ()
83
83
withLogger _ = id
84
84
@@ -97,22 +97,25 @@ newtype TermCtxt = TermCtxt Int
97
97
98
98
instance ToLogFormat TermCtxt where
99
99
toTextualLog (TermCtxt hsh) = " term " <> (showHashHex hsh)
100
+ toJSONLog (TermCtxt hsh) = object [" term" .= showHashHex hsh]
101
+
102
+ newtype HookCtxt = HookCtxt Text
100
103
101
- -- toJSONLog (TermCtxt hsh) = object [ "term" .= hsh ]
104
+ instance ToLogFormat HookCtxt where
105
+ toTextualLog (HookCtxt h) = " hook " <> h
106
+ toJSONLog (HookCtxt h) = object [" hook" .= h]
102
107
103
108
instance ToLogFormat Term where
104
109
toTextualLog t = renderOneLineText $ pretty t
105
-
106
- -- toJSONLog t = toJSON $ externaliseTerm t
110
+ toJSONLog t = toJSON $ addHeader $ externaliseTerm t
107
111
108
112
instance ToLogFormat Text where
109
113
toTextualLog t = t
110
-
111
- -- toJSONLog t = String t
114
+ toJSONLog t = String t
112
115
113
116
withTermContext :: LoggerMIO m => Term -> m a -> m a
114
117
withTermContext t@ (Term attrs _) m = withContext (LogContext $ TermCtxt attrs. hash) $ do
115
- withContext " detail " $ logMessage t
118
+ withContext " kore-term " $ logMessage t
116
119
m
117
120
118
121
withPatternContext :: LoggerMIO m => Pattern -> m a -> m a
@@ -122,22 +125,29 @@ withPatternContext Pattern{term, constraints} m =
122
125
123
126
instance ToLogFormat KorePattern where
124
127
toTextualLog = prettyPattern
128
+ toJSONLog p = toJSON p
125
129
126
130
newtype KorePatternCtxt = KorePatternCtxt KorePattern
127
131
128
132
instance ToLogFormat KorePatternCtxt where
129
133
toTextualLog (KorePatternCtxt t) = " term " <> (showHashHex $ Data.Hashable. hash $ prettyPattern t)
134
+ toJSONLog (KorePatternCtxt t) = object [" term" .= (showHashHex $ Data.Hashable. hash $ prettyPattern t)]
130
135
131
136
instance KnownSymbol k => ToLogFormat (RewriteRule k ) where
132
137
toTextualLog RewriteRule {attributes} =
133
138
LazyText. toStrict $
134
139
(LazyText. toLower $ LazyText. pack $ symbolVal (Proxy :: Proxy k ))
135
140
<> " "
136
141
<> maybe " UNKNOWN" (LazyText. take 7 . LazyText. fromStrict . coerce) attributes. uniqueId
142
+ toJSONLog RewriteRule {attributes} =
143
+ object
144
+ [ (Key. fromText $ LazyText. toStrict $ LazyText. toLower $ LazyText. pack $ symbolVal (Proxy :: Proxy k ))
145
+ .= ((maybe " UNKNOWN" coerce attributes. uniqueId) :: Text )
146
+ ]
137
147
138
148
withKorePatternContext :: LoggerMIO m => KorePattern -> m a -> m a
139
149
withKorePatternContext t m = withContext (LogContext $ KorePatternCtxt t) $ do
140
- withContext " detail " $ logMessage t
150
+ withContext " kore-term " $ logMessage t
141
151
m
142
152
143
153
withRuleContext :: KnownSymbol tag => LoggerMIO m => RewriteRule tag -> m a -> m a
@@ -149,16 +159,47 @@ withRuleContext rule m = withContext (LogContext rule) $ do
149
159
loc -> loc
150
160
m
151
161
152
- newtype LoggerT m a = LoggerT { unLoggerT :: ReaderT (Logger LogMessage ) m a }
153
- deriving newtype (Applicative , Functor , Monad , MonadIO , MonadLogger , MonadLoggerIO )
162
+ data WithJsonMessage where
163
+ WithJsonMessage :: ToLogFormat a => Value -> a -> WithJsonMessage
164
+
165
+ instance ToLogFormat WithJsonMessage where
166
+ toTextualLog (WithJsonMessage _ a) = toTextualLog a
167
+ toJSONLog (WithJsonMessage v _) = v
154
168
155
- instance MonadLoggerIO m => LoggerMIO (LoggerT m ) where
169
+ newtype LoggerT m a = LoggerT { unLoggerT :: ReaderT (Logger LogMessage ) m a }
170
+ deriving newtype
171
+ ( Applicative
172
+ , Functor
173
+ , Monad
174
+ , MonadIO
175
+ , Control.Monad.Logger. MonadLogger
176
+ , Control.Monad.Logger. MonadLoggerIO
177
+ )
178
+
179
+ instance MonadIO m => LoggerMIO (LoggerT m ) where
156
180
getLogger = LoggerT ask
157
181
withLogger modL (LoggerT m) = LoggerT $ withReaderT modL m
158
182
159
- runLogger :: MonadLoggerIO m => LoggerT m a -> m a
160
- runLogger (LoggerT m) = do
161
- l <- askLoggerIO
162
- runReaderT m $ Logger $ \ (LogMessage ctxts msg) ->
163
- let logLevel = mconcat $ intersperse " ][" $ map (\ (LogContext lc) -> toTextualLog lc) ctxts
164
- in l defaultLoc " " (LevelOther logLevel) $ toLogStr $ toTextualLog msg
183
+ textLogger :: (Control.Monad.Logger. LogStr -> IO () ) -> Logger LogMessage
184
+ textLogger l = Logger $ \ (LogMessage ctxts msg) ->
185
+ let logLevel = mconcat $ intersperse " ][" $ map (\ (LogContext lc) -> toTextualLog lc) ctxts
186
+ in l $
187
+ " ["
188
+ <> (Control.Monad.Logger. toLogStr logLevel)
189
+ <> " ] "
190
+ <> (Control.Monad.Logger. toLogStr $ toTextualLog msg)
191
+ <> " \n "
192
+
193
+ jsonLogger :: (Control.Monad.Logger. LogStr -> IO () ) -> Logger LogMessage
194
+ jsonLogger l = Logger $ \ (LogMessage ctxts msg) ->
195
+ let ctxt = toJSON $ map (\ (LogContext lc) -> toJSONLog lc) ctxts
196
+ in liftIO $
197
+ l $
198
+ ( Control.Monad.Logger. toLogStr $
199
+ encodePretty' rpcJsonConfig{confIndent = Spaces 0 } $
200
+ object [" context" .= ctxt, " message" .= toJSONLog msg]
201
+ )
202
+ <> " \n "
203
+
204
+ filterLogger :: (LogMessage -> Bool ) -> Logger LogMessage -> Logger LogMessage
205
+ filterLogger p (Logger l) = Logger $ \ m -> when (p m) $ l m
0 commit comments