git.iko.soy/typeable/control-logger
on 592cccb help sign in
.gitignore−2
since splitsnapshots
unifiedsplit
@@ -1,3 +1 @@
1.stack-work
1.stack-work
2−*~
3−*.swp
README.md+1−1
@@ -1,3 +1,3 @@
1# control-logger
1# control-logger
2
2
3−Utilities for logging
3+Utilities for logging with DTT projects
control-logger.cabal+43−51
@@ -1,55 +1,47 @@
1−cabal-version: 2.4
1+cabal-version: 2.4
2−name: control-logger
2+name: control-logger
3−version: 0.1.0.0
3+version: 0.1.0.0
4−synopsis: Logger used by all projects
4+synopsis: Logger used by all projects
5−license-file: LICENSE
5+license-file: LICENSE
6−build-type: Simple
6+build-type: Simple
7
7
8library
8library
9− hs-source-dirs: src
9+ hs-source-dirs: src
10− ghc-options: -Wall
10+ ghc-options: -Wall
11−
12 if !impl(ghcjs)
11 if !impl(ghcjs)
13− exposed-modules:
12+ exposed-modules: Control.Logger
14− Control.Logger
15− Control.Logger.Katip
13+ Control.Logger.Katip
16− Control.Logger.Katip.Utils
14+ Control.Logger.Katip.Utils
17− Control.Logger.Orphans
15+ Control.Logger.Orphans
18−
19− exposed-modules: Control.Logger.Internal
16+ exposed-modules: Control.Logger.Internal
20− build-depends:
17+ build-depends: base
21− , aeson
18+ , aeson
22− , base >=4.11
23− , bytestring
19+ , bytestring
24− , control-has
20+ , control-has
25− , control-has-katip
21+ , control-has-katip
26− , deepseq
22+ , deepseq
27− , exceptions
23+ , exceptions
28− , fast-logger >=2.4.11
24+ , fast-logger
29− , http-client
25+ , http-client
30− , lens
26+ , lens
31− , monad-logger
27+ , monad-logger
32− , mtl
28+ , mtl
33− , shakespeare
29+ , shakespeare
34− , text
30+ , text
35− , time
31+ , time
36− , unordered-containers
32+ , unordered-containers
37−
38 if !impl(ghcjs)
33 if !impl(ghcjs)
39− build-depends:
34+ build-depends: katip
40− , katip >=0.8.8.0
41− , optparse-applicative
35+ , optparse-applicative
42−
43− default-language: Haskell2010
36+ default-language: Haskell2010
44− default-extensions:
37+ default-extensions: RankNTypes
45− ConstraintKinds
46− DataKinds
38+ DataKinds
47− DeriveGeneric
48− FlexibleContexts
39+ FlexibleContexts
49− FlexibleInstances
40+ FlexibleInstances
50− LambdaCase
41+ LambdaCase
51− OverloadedStrings
42+ OverloadedStrings
52− RankNTypes
53− RecordWildCards
54− ScopedTypeVariables
43+ ScopedTypeVariables
44+ DeriveGeneric
45+ ConstraintKinds
46+ RecordWildCards
55− TypeSynonymInstances
47+ TypeSynonymInstances
default.nixdeleted−9
@@ -1,9 +0,0 @@
1−{ pkgs ? import <nixpkgs> {} }:
2−
3−pkgs.mkShell {
4− buildInputs = [
5− pkgs.ghc
6− pkgs.haskellPackages.cabal-install
7− pkgs.zlib
8− ];
9−}
src/Control/Logger.hs+11−65
@@ -1,10 +1,7 @@
1−{-# LANGUAGE CPP #-}
1+
2module Control.Logger
2module Control.Logger
3 ( Logger
3 ( Logger
4 , loggerContext
4 , loggerContext
5− , scrubber
6− , censor
7− , censorWith
8 , logMsg
5 , logMsg
9 , logMsgWith
6 , logMsgWith
10 , logInfo
7 , logInfo
@@ -35,27 +32,20 @@ module Control.Logger
35 , compactCallStack
32 , compactCallStack
36 , st
33 , st
37 , ToObject(..)
34 , ToObject(..)
38− , withScrubber
39− , censoringWith
40− , censoring
41 ) where
35 ) where
42
36
43import Control.Has
37import Control.Has
44−import Control.Lens hiding (censoring)
45import Control.Logger.Internal
38import Control.Logger.Internal
46−import Control.Logger.Orphans ()
39+import Control.Logger.Orphans ()
47−import Control.Monad
48import Control.Monad.Catch
40import Control.Monad.Catch
49−import Control.Monad.IO.Class
50−import qualified Data.List as List
41+import qualified Data.List as List
51−import Data.Monoid
52−import Data.Text (Text)
42+import Data.Text (Text)
53−import qualified Data.Text as Text
43+import qualified Data.Text as Text
54import Data.Time
44import Data.Time
55import GHC.Stack
45import GHC.Stack
56−import Katip (ToObject (..))
46+import Katip (ToObject(..))
57import System.Log.FastLogger
47import System.Log.FastLogger
58−import Text.Shakespeare.Text (st)
48+import Text.Shakespeare.Text (st)
59
49
60logError
50logError
61 :: (LoggingMonad r m)
51 :: (LoggingMonad r m)
@@ -109,50 +99,6 @@ logErrorWith
109 -> m ()
99 -> m ()
110logErrorWith logger msg = withFrozenCallStack (logMsgWith logger Error msg)
100logErrorWith logger msg = withFrozenCallStack (logMsgWith logger Error msg)
111
101
112−safeReplace :: Text -> Text -> Text -> Text
113−safeReplace what with where_
114− | Text.null what = where_
115− | otherwise = Text.replace what with where_
116−
117−-- | Add a some text to scrubber
118−censorWith :: Text -> Text -> Logger -> Logger
119−censorWith replacement needle l =
120− l & scrubber <>~ Endo (safeReplace needle replacement)
121−
122−-- | Censor with "***"
123−censor :: Text -> Logger -> Logger
124−censor = censorWith "***"
125−
126−-- | Run an action with adjusted scrubber
127−withScrubber
128− :: forall r m a. (Has Logger r, MonadReader r m)
129− => (Endo Text -> Endo Text)
130− -> m a
131− -> m a
132−withScrubber scrubF = local expandScrubber
133− where
134− expandScrubber :: r -> r
135− expandScrubber = over part (over scrubber scrubF)
136−
137−-- | Run an action while censoring additional text from logs
138−censoringWith
139− :: (Has Logger r, MonadReader r m)
140− => Text
141− -> Text
142− -> m a
143− -> m a
144−censoringWith replacement txt = withScrubber (<> censored)
145− where
146− censored = Endo (safeReplace txt replacement)
147−
148−-- | Run an action while censoring additional text from logs
149−censoring
150− :: (Has Logger r, MonadReader r m)
151− => Text
152− -> m a
153− -> m a
154−censoring = censoringWith "***"
155−
156-- | Log exceptions occured in computation and just ignore them.
102-- | Log exceptions occured in computation and just ignore them.
157tryLogError
103tryLogError
158 :: (MonadIO m, MonadCatch m, Has Logger r, MonadReader r m)
104 :: (MonadIO m, MonadCatch m, Has Logger r, MonadReader r m)
@@ -203,14 +149,14 @@ fileLogger :: MonadIO m => FilePath -> m Logger
203fileLogger fp = fastFunc <$> liftIO (newFileLoggerSet defaultBufSize fp)
149fileLogger fp = fastFunc <$> liftIO (newFileLoggerSet defaultBufSize fp)
204
150
205silentLogger :: Logger
151silentLogger :: Logger
206−silentLogger = Logger mempty mempty (\_ _ _ _ -> return ())
152+silentLogger = Logger mempty (\_ _ _ _ -> return ())
207
153
208-- | Logger which flushes buffer after each message. This is useful with
154-- | Logger which flushes buffer after each message. This is useful with
209-- stderrLogger.
155-- stderrLogger.
210flushingFastFunc
156flushingFastFunc
211 :: LogSeverity -> LoggerSet -> Logger
157 :: LogSeverity -> LoggerSet -> Logger
212flushingFastFunc minLogLevel loggerSet =
158flushingFastFunc minLogLevel loggerSet =
213− Logger mempty mempty $ \_ stack logLevel msg ->
159+ Logger mempty $ \_ stack logLevel msg ->
214 when (logLevel >= minLogLevel) $ do
160 when (logLevel >= minLogLevel) $ do
215 ts <- getCurrentTime
161 ts <- getCurrentTime
216 pushLogStr loggerSet
162 pushLogStr loggerSet
@@ -234,14 +180,14 @@ flushingStderrLogger =
234-- | Make our outdated 'Logger' of fast-logger's 'LoggerSet'
180-- | Make our outdated 'Logger' of fast-logger's 'LoggerSet'
235fastFunc :: LoggerSet -> Logger
181fastFunc :: LoggerSet -> Logger
236fastFunc loggerSet =
182fastFunc loggerSet =
237− Logger mempty mempty $ \_ _ _ msg -> pushLogStr loggerSet $ toLogStr msg
183+ Logger mempty $ \_ _ _ msg -> pushLogStr loggerSet $ toLogStr msg
238
184
239type LogSource = Text
185type LogSource = Text
240
186
241-- | Default logger tests and same things.
187-- | Default logger tests and same things.
242defaultFastFunc :: LogSource -> LogSeverity -> LoggerSet -> Logger
188defaultFastFunc :: LogSource -> LogSeverity -> LoggerSet -> Logger
243defaultFastFunc loc minLogLevel loggerSet =
189defaultFastFunc loc minLogLevel loggerSet =
244− Logger mempty mempty $ \_ stack s msg -> when (s >= minLogLevel) $ do
190+ Logger mempty $ \_ stack s msg -> when (s >= minLogLevel) $ do
245 ts <- getCurrentTime
191 ts <- getCurrentTime
246 pushLogStr loggerSet $ formatLogStr ts stack loc s (toLogStr msg)
192 pushLogStr loggerSet $ formatLogStr ts stack loc s (toLogStr msg)
247
193
src/Control/Logger/Internal.hs+8−29
@@ -1,12 +1,9 @@
1{-# LANGUAGE TemplateHaskell #-}
1{-# LANGUAGE TemplateHaskell #-}
2−{-# LANGUAGE NamedFieldPuns #-}
3−{-# LANGUAGE CPP #-}
4
2
5module Control.Logger.Internal
3module Control.Logger.Internal
6 ( Logger(..)
4 ( Logger(..)
7 , loggerContext
5 , loggerContext
8 , loggerAction
6 , loggerAction
9− , scrubber
10 , runLogger
7 , runLogger
11 , LogSeverity(..)
8 , LogSeverity(..)
12 , LoggingMonad
9 , LoggingMonad
@@ -16,11 +13,10 @@ module Control.Logger.Internal
16
13
17import Control.Has
14import Control.Has
18import Control.Lens
15import Control.Lens
19−import Control.Monad.IO.Class
20import Control.DeepSeq
16import Control.DeepSeq
21−import Data.Aeson (ToJSON, FromJSON, Object, Value(..))
17+import Data.Aeson (ToJSON, FromJSON, Object)
22import Data.Text (Text)
18import Data.Text (Text)
23−import Data.Monoid
19+import GHC.Generics (Generic)
24import GHC.Stack
20import GHC.Stack
25
21
26
22
@@ -34,26 +30,23 @@ data LogSeverity
34instance ToJSON LogSeverity
30instance ToJSON LogSeverity
35instance FromJSON LogSeverity
31instance FromJSON LogSeverity
36
32
37−data Logger = Logger
33+data Logger
34+ = Logger
38 { _loggerContext :: Object
35 { _loggerContext :: Object
39− , _scrubber :: Endo Text
40 , _loggerAction :: Object -> CallStack -> LogSeverity -> Text -> IO ()
36 , _loggerAction :: Object -> CallStack -> LogSeverity -> Text -> IO ()
41 } deriving Generic
37 } deriving Generic
42
38
43−instance NFData Logger where
39+instance NFData Logger
44− rnf Logger{_loggerContext, _scrubber, _loggerAction} =
45− rnf _loggerContext `deepseq` rwhnf (appEndo _scrubber) `deepseq` rwhnf _loggerAction
46
40
47makeLenses ''Logger
41makeLenses ''Logger
48
42
49instance Semigroup Logger where
43instance Semigroup Logger where
50− (Logger ctx1 s1 l1) <> (Logger ctx2 s2 l2)
44+ (Logger ctx1 l1) <> (Logger ctx2 l2) = Logger ctx'
51− = Logger ctx' (s1 <> s2)
52 $ \ctx stack s t -> l1 ctx stack s t >> l2 ctx stack s t
45 $ \ctx stack s t -> l1 ctx stack s t >> l2 ctx stack s t
53 where ctx' = ctx1 <> ctx2
46 where ctx' = ctx1 <> ctx2
54
47
55instance Monoid Logger where
48instance Monoid Logger where
56− mempty = Logger mempty mempty $ \_ _ _ _ -> pure ()
49+ mempty = Logger mempty $ \_ _ _ _ -> pure ()
57
50
58type LoggingMonad r m =
51type LoggingMonad r m =
59 (MonadReader r m, Has Logger r, MonadIO m, HasCallStack)
52 (MonadReader r m, Has Logger r, MonadIO m, HasCallStack)
@@ -77,18 +70,4 @@ logMsgWith logger s t =
77 liftIO $ runLogger logger callStack s t
70 liftIO $ runLogger logger callStack s t
78
71
79runLogger :: Logger -> CallStack -> LogSeverity -> Text -> IO ()
72runLogger :: Logger -> CallStack -> LogSeverity -> Text -> IO ()
80−runLogger (Logger ctx theScrubber logger) cs ls txt
73+runLogger (Logger ctx logger) = logger ctx
81− = logger (scrubContext theScrubber ctx) cs ls (appEndo theScrubber txt)
82−
83−
84−scrubContext :: Endo Text -> Object -> Object
85−scrubContext theScrubber = fmap doScrub
86− where
87− doScrub :: Value -> Value
88− doScrub = \case
89− Object object -> Object (fmap doScrub object)
90− Array array -> Array (fmap doScrub array)
91− String string -> String (appEndo theScrubber string)
92− n@Number{} -> n
93− b@Bool{} -> b
94− n@Null -> n
src/Control/Logger/Katip.hs+22−3
@@ -5,7 +5,7 @@ module Control.Logger.Katip
5 ( logSeverityToKSeverity
5 ( logSeverityToKSeverity
6 , KatipContextTState(..)
6 , KatipContextTState(..)
7 , getKatipLogger
7 , getKatipLogger
8− , ourItemJson
8+ , ourFormatter
9 , katipIndexNameString
9 , katipIndexNameString
10 ) where
10 ) where
11
11
@@ -14,11 +14,12 @@ import Control.Has.Katip ()
14import Control.Lens hiding ((.=))
14import Control.Lens hiding ((.=))
15import Control.Logger.Internal
15import Control.Logger.Internal
16import Data.Aeson hiding (Error)
16import Data.Aeson hiding (Error)
17+import qualified Data.HashMap.Strict as HM
17import Data.Text (Text)
18import Data.Text (Text)
18import qualified Data.Text as T
19import qualified Data.Text as T
19import qualified Data.Text.Lazy.Builder as T.Builder
20import qualified Data.Text.Lazy.Builder as T.Builder
20import Katip as K hiding (logMsg)
21import Katip as K hiding (logMsg)
21−import Katip.Core (LocJs(..), ProcessIDJs(..))
22+import Katip.Core (ItemFunc(..), LocJs(..), ProcessIDJs(..))
22import Katip.Monadic (KatipContextTState(..))
23import Katip.Monadic (KatipContextTState(..))
23
24
24
25
@@ -30,6 +31,24 @@ logSeverityToKSeverity = \case
30 Error -> ErrorS
31 Error -> ErrorS
31
32
32
33
34+-- | Adds the @rev-hash@ value to each record.
35+-- Early we copied `msg` to `msg-keyword` here but drop it
36+-- because purpose of this duplication is not clear.
37+ourFormatter
38+ :: Text
39+ -- ^ git revision string
40+ -> Verbosity
41+ -> ItemFunc Value
42+ourFormatter gitRev verb = ItemFunc $ \item -> go $ ourItemJson verb item
43+ where
44+ go :: Value -> Value
45+ go = \case
46+ Object h -> Object $ setRev h
47+ x -> x -- drop exception here?
48+ where
49+ setRev :: HM.HashMap Text Value -> HM.HashMap Text Value
50+ setRev = HM.insert "rev-hash" (toJSON gitRev)
51+
33katipIndexNameString :: Text
52katipIndexNameString :: Text
34katipIndexNameString = "antorica-b2b-logs"
53katipIndexNameString = "antorica-b2b-logs"
35
54
@@ -56,7 +75,7 @@ instance LogItem Object where
56 payloadKeys _ _ = AllKeys
75 payloadKeys _ _ = AllKeys
57
76
58getKatipLogger :: KatipContextTState -> Logger
77getKatipLogger :: KatipContextTState -> Logger
59−getKatipLogger katipCtx = Logger (toObject . ltsContext $ katipCtx) mempty
78+getKatipLogger katipCtx = Logger (toObject . ltsContext $ katipCtx)
60 $ \ ctx stack s msg ->
79 $ \ ctx stack s msg ->
61 let ?callStack = stack
80 let ?callStack = stack
62 in
81 in
src/Control/Logger/Katip/Utils.hs+15−36
@@ -1,4 +1,4 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE ImplicitParams #-}
2
2
3module Control.Logger.Katip.Utils
3module Control.Logger.Katip.Utils
4 ( katipIndexNameString
4 ( katipIndexNameString
@@ -6,6 +6,7 @@ module Control.Logger.Katip.Utils
6 , LogFormat(..)
6 , LogFormat(..)
7 , registerFileScribe
7 , registerFileScribe
8 , setLoggingCtx
8 , setLoggingCtx
9+ , ourFormatter
9 , getKatipLogger
10 , getKatipLogger
10 , logSeverityToKSeverity
11 , logSeverityToKSeverity
11 ) where
12 ) where
@@ -19,36 +20,18 @@ import Control.Logger.Internal as L
19import Control.Logger.Katip as L
20import Control.Logger.Katip as L
20import Data.Aeson hiding (Error)
21import Data.Aeson hiding (Error)
21import Data.Aeson.Text
22import Data.Aeson.Text
22−#if MIN_VERSION_aeson(2,0,0)
23−import qualified Data.Aeson.KeyMap as HM
23+import qualified Data.ByteString.Builder as B.Builder
24−import qualified Data.Aeson.Key as HM
25−#else
26import qualified Data.HashMap.Strict as HM
24import qualified Data.HashMap.Strict as HM
27−#endif
28import Data.Text (Text)
25import Data.Text (Text)
29−import qualified Data.Text.Lazy as T
30import qualified Data.Text.Lazy.Builder as T.Builder
26import qualified Data.Text.Lazy.Builder as T.Builder
27+import qualified Data.Text.Lazy.Encoding as T.Lazy
31import Katip as K hiding (logMsg)
28import Katip as K hiding (logMsg)
29+import Katip.Core (ItemFunc(..))
32import Katip.Monadic (KatipContextTState(..))
30import Katip.Monadic (KatipContextTState(..))
33import qualified Katip.Scribes.Handle as K
31import qualified Katip.Scribes.Handle as K
34import System.IO
32import System.IO
35
33
36
34
37−#if MIN_VERSION_aeson(2,0,0)
38−type KeyMap v = HM.KeyMap v
39−textToKey :: Text -> Key
40−textToKey = HM.fromText
41−keyToText :: Key -> Text
42−keyToText = HM.toText
43−#else
44−type KeyMap v = HM.HashMap Text v
45−type Key = Text
46−textToKey :: Text -> Key
47−textToKey = id
48−keyToText :: Key -> Text
49−keyToText = id
50−#endif
51−
52-- | How to format logs
35-- | How to format logs
53data LogFormat
36data LogFormat
54 = LogBracket -- ^ use `bracketFormat`
37 = LogBracket -- ^ use `bracketFormat`
@@ -72,42 +55,38 @@ registerFileScribe gitRev verbosity format filePath permitF additions logenv =
72 formatter = case format of
55 formatter = case format of
73 LogBracket -> customBracketFormat additions'
56 LogBracket -> customBracketFormat additions'
74 LogJson -> customJsonFormat gitRev additions'
57 LogJson -> customJsonFormat gitRev additions'
75− additions'
58+ additions' = HM.fromList . map (fmap String) $ additions
76− = HM.fromList
77− . map (\(k, v) -> (textToKey k, String v))
78− $ additions
79
59
80-- | JSON formatter that adds the specified fields to the output
60-- | JSON formatter that adds the specified fields to the output
81customJsonFormat
61customJsonFormat
82− :: forall a. LogItem a => Text -> KeyMap Value -> ItemFormatter a
62+ :: forall a. LogItem a => Text -> HM.HashMap Text Value -> ItemFormatter a
83customJsonFormat gitRev additions withColor verb i = (mappend "\n") $
63customJsonFormat gitRev additions withColor verb i = (mappend "\n") $
84 -- Here we reimplement the standard formater because we want the
64 -- Here we reimplement the standard formater because we want the
85 -- additional key/value pairs to be added at the top level.
65 -- additional key/value pairs to be added at the top level.
86 -- So we can't use the LogWithAdditions like we do for bracket format
66 -- So we can't use the LogWithAdditions like we do for bracket format
87− T.Builder.fromText $
67+ B.Builder.lazyByteString . T.Lazy.encodeUtf8 . T.Builder.toLazyText $
88 K.colorBySeverity withColor (_itemSeverity i) $
68 K.colorBySeverity withColor (_itemSeverity i) $
89− (T.toStrict . encodeToLazyText) (extend $ ourItemJson verb i)
69+ encodeToTextBuilder (extend $ applyItemFunc (ourFormatter gitRev verb) i)
90 where
70 where
91− extend (Object o) = Object $ HM.union additions' o
71+ extend (Object o) = Object $ HM.union additions o
92 extend v = v
72 extend v = v
93− additions' = HM.insert "rev-hash" (toJSON gitRev) additions
94
73
95-- | Bracket formatter that adds the specified fields to the output
74-- | Bracket formatter that adds the specified fields to the output
96customBracketFormat
75customBracketFormat
97− :: forall a. LogItem a => KeyMap Value -> ItemFormatter a
76+ :: forall a. LogItem a => HM.HashMap Text Value -> ItemFormatter a
98customBracketFormat additions withColor verb i =
77customBracketFormat additions withColor verb i =
99 bracketFormat withColor verb (LogWithAdditions additions <$> i)
78 bracketFormat withColor verb (LogWithAdditions additions <$> i)
100
79
101-- | Log item payload that adds the specified additional key/value pairs
80-- | Log item payload that adds the specified additional key/value pairs
102-- to the output on at verbosity levels
81-- to the output on at verbosity levels
103−data LogWithAdditions a = LogWithAdditions (KeyMap Value) a
82+data LogWithAdditions a = LogWithAdditions (HM.HashMap Text Value) a
104 deriving (Show)
83 deriving (Show)
105
84
106instance LogItem a => LogItem (LogWithAdditions a) where
85instance LogItem a => LogItem (LogWithAdditions a) where
107 payloadKeys v (LogWithAdditions additions a) =
86 payloadKeys v (LogWithAdditions additions a) =
108 case payloadKeys v a of
87 case payloadKeys v a of
109 AllKeys -> AllKeys
88 AllKeys -> AllKeys
110− SomeKeys keys -> SomeKeys (map keyToText (HM.keys additions) ++ keys)
89+ SomeKeys keys -> SomeKeys (HM.keys additions ++ keys)
111
90
112instance ToObject a => ToObject (LogWithAdditions a) where
91instance ToObject a => ToObject (LogWithAdditions a) where
113 toObject (LogWithAdditions additions a) =
92 toObject (LogWithAdditions additions a) =
@@ -120,5 +99,5 @@ setLoggingCtx
120 -> ReaderT r m a
99 -> ReaderT r m a
121setLoggingCtx ctx' = local (part %~ go)
100setLoggingCtx ctx' = local (part %~ go)
122 where
101 where
123− go (Logger ctx scrbber f) =
102+ go (Logger ctx f) =
124− Logger (ctx <> ctx') scrbber f
103+ Logger (ctx <> ctx') f
src/Control/Logger/Orphans.hs+2−2
@@ -10,7 +10,7 @@ import Control.EnvT
10import Control.Has
10import Control.Has
11import Control.Logger.Internal
11import Control.Logger.Internal
12import Control.Monad.Logger
12import Control.Monad.Logger
13−import qualified Data.Text.Encoding as T
13+import qualified Data.Text as T
14import GHC.Stack
14import GHC.Stack
15
15
16
16
@@ -21,7 +21,7 @@ instance (Has Logger r, MonadIO m)
21 in withFrozenCallStack
21 in withFrozenCallStack
22 $ logMsg
22 $ logMsg
23 (mlLevelToLogSeverity level)
23 (mlLevelToLogSeverity level)
24− (T.decodeUtf8Lenient . fromLogStr . toLogStr $ msg)
24+ (T.pack . show . toLogStr $ msg)
25
25
26locToCallStack :: Loc -> CallStack
26locToCallStack :: Loc -> CallStack
27locToCallStack Loc {..} = fromCallSiteList
27locToCallStack Loc {..} = fromCallSiteList