{-# LANGUAGE TemplateHaskell #-}
module Effects.Logger
(
MonadLogger (..),
LogLevel (..),
levelTrace,
levelFatal,
logTrace,
MLogger.logDebug,
MLogger.logInfo,
MLogger.logWarn,
MLogger.logError,
MLogger.logOther,
logFatal,
guardLevel,
shouldLog,
LogFormatter (..),
Utils.defaultLogFormatter,
LocStrategy (..),
formatLog,
_LevelTrace,
_LevelInfo,
_LevelDebug,
_LevelWarn,
_LevelError,
_LevelOther,
_LevelFatal,
LogStr,
Loc,
)
where
import Control.Monad (when)
import Control.Monad.Logger
( LogLevel (LevelDebug, LevelError, LevelInfo, LevelOther, LevelWarn),
LogStr,
MonadLogger (monadLoggerLog),
ToLogStr,
liftLoc,
)
import Control.Monad.Logger qualified as MLogger
import Data.Text (Text)
import Data.Text qualified as T
import Data.Word (Word8)
import Effects.Concurrent.Thread (MonadThread)
import Effects.Logger.Utils
( LocStrategy (LocNone, LocPartial, LocStable),
LogFormatter (MkLogFormatter, locStrategy, newline, threadLabel, timezone),
)
import Effects.Logger.Utils qualified as Utils
import Effects.Time (MonadTime)
import GHC.Stack (HasCallStack)
import Language.Haskell.TH (Loc)
import Language.Haskell.TH.Syntax (Exp, Lift (lift), Q, Quasi (qLocation))
import Optics.Core
( Prism',
preview,
prism,
)
formatLog ::
( HasCallStack,
MonadThread m,
MonadTime m,
ToLogStr msg
) =>
LogFormatter ->
LogLevel ->
msg ->
m LogStr
formatLog :: forall (m :: * -> *) msg.
(HasCallStack, MonadThread m, MonadTime m, ToLogStr msg) =>
LogFormatter -> LogLevel -> msg -> m LogStr
formatLog = Maybe Namespace -> LogFormatter -> LogLevel -> msg -> m LogStr
forall (m :: * -> *) msg.
(HasCallStack, MonadThread m, MonadTime m, ToLogStr msg) =>
Maybe Namespace -> LogFormatter -> LogLevel -> msg -> m LogStr
Utils.formatLog Maybe Namespace
forall a. Maybe a
Nothing
{-# INLINEABLE formatLog #-}
logTH :: LogLevel -> Q Exp
logTH :: LogLevel -> Q Exp
logTH LogLevel
level =
[|
monadLoggerLog $(Q Loc
forall (m :: * -> *). Quasi m => m Loc
qLocation Q Loc -> (Loc -> Q Exp) -> Q Exp
forall a b. Q a -> (a -> Q b) -> Q b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Loc -> Q Exp
liftLoc) (T.pack "") $(LogLevel -> Q Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => LogLevel -> m Exp
lift LogLevel
level)
. (id :: Text -> Text)
|]
levelTrace :: LogLevel
levelTrace :: LogLevel
levelTrace = Text -> LogLevel
LevelOther Text
"Trace"
levelFatal :: LogLevel
levelFatal :: LogLevel
levelFatal = Text -> LogLevel
LevelOther Text
"Fatal"
logTrace :: Q Exp
logTrace :: Q Exp
logTrace = LogLevel -> Q Exp
logTH LogLevel
levelTrace
logFatal :: Q Exp
logFatal :: Q Exp
logFatal = LogLevel -> Q Exp
logTH LogLevel
levelFatal
guardLevel ::
(Applicative f) =>
LogLevel ->
LogLevel ->
f () ->
f ()
guardLevel :: forall (f :: * -> *).
Applicative f =>
LogLevel -> LogLevel -> f () -> f ()
guardLevel LogLevel
configLvl LogLevel
lvl = Bool -> f () -> f ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (LogLevel -> LogLevel -> Bool
shouldLog LogLevel
configLvl LogLevel
lvl)
{-# INLINEABLE guardLevel #-}
shouldLog ::
LogLevel ->
LogLevel ->
Bool
shouldLog :: LogLevel -> LogLevel -> Bool
shouldLog LogLevel
configLvl LogLevel
lvl =
case (Optic' A_Prism NoIx LogLevel Text -> LogLevel -> Maybe Text
forall k (is :: IxList) s a.
Is k An_AffineFold =>
Optic' k is s a -> s -> Maybe a
preview Optic' A_Prism NoIx LogLevel Text
_LevelOther LogLevel
configLvl, Optic' A_Prism NoIx LogLevel Text -> LogLevel -> Maybe Text
forall k (is :: IxList) s a.
Is k An_AffineFold =>
Optic' k is s a -> s -> Maybe a
preview Optic' A_Prism NoIx LogLevel Text
_LevelOther LogLevel
lvl) of
(Just Text
configTxt, Just Text
lvlTxt)
| Text -> Bool
forall {a}. (Eq a, IsString a) => a -> Bool
isCustom Text
configTxt Bool -> Bool -> Bool
&& Text -> Bool
forall {a}. (Eq a, IsString a) => a -> Bool
isCustom Text
lvlTxt -> Text
configTxt Text -> Text -> Bool
forall a. Ord a => a -> a -> Bool
<= Text
lvlTxt
(Maybe Text, Maybe Text)
_ -> LogLevel -> Word8
logLevelToWord LogLevel
configLvl Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= LogLevel -> Word8
logLevelToWord LogLevel
lvl
where
isCustom :: a -> Bool
isCustom a
t =
a
t a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
"Trace" Bool -> Bool -> Bool
&& a
t a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
"Fatal"
_LevelTrace :: Prism' LogLevel ()
_LevelTrace :: Prism' LogLevel ()
_LevelTrace =
(() -> LogLevel)
-> (LogLevel -> Either LogLevel ()) -> Prism' LogLevel ()
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
(LogLevel -> () -> LogLevel
forall a b. a -> b -> a
const LogLevel
levelTrace)
( \case
LevelOther Text
"Trace" -> () -> Either LogLevel ()
forall a b. b -> Either a b
Right ()
LogLevel
other -> LogLevel -> Either LogLevel ()
forall a b. a -> Either a b
Left LogLevel
other
)
{-# INLINE _LevelTrace #-}
_LevelDebug :: Prism' LogLevel ()
_LevelDebug :: Prism' LogLevel ()
_LevelDebug =
(() -> LogLevel)
-> (LogLevel -> Either LogLevel ()) -> Prism' LogLevel ()
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
(LogLevel -> () -> LogLevel
forall a b. a -> b -> a
const LogLevel
LevelDebug)
( \case
LogLevel
LevelDebug -> () -> Either LogLevel ()
forall a b. b -> Either a b
Right ()
LogLevel
other -> LogLevel -> Either LogLevel ()
forall a b. a -> Either a b
Left LogLevel
other
)
{-# INLINE _LevelDebug #-}
_LevelInfo :: Prism' LogLevel ()
_LevelInfo :: Prism' LogLevel ()
_LevelInfo =
(() -> LogLevel)
-> (LogLevel -> Either LogLevel ()) -> Prism' LogLevel ()
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
(LogLevel -> () -> LogLevel
forall a b. a -> b -> a
const LogLevel
LevelInfo)
( \case
LogLevel
LevelInfo -> () -> Either LogLevel ()
forall a b. b -> Either a b
Right ()
LogLevel
other -> LogLevel -> Either LogLevel ()
forall a b. a -> Either a b
Left LogLevel
other
)
{-# INLINE _LevelInfo #-}
_LevelWarn :: Prism' LogLevel ()
_LevelWarn :: Prism' LogLevel ()
_LevelWarn =
(() -> LogLevel)
-> (LogLevel -> Either LogLevel ()) -> Prism' LogLevel ()
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
(LogLevel -> () -> LogLevel
forall a b. a -> b -> a
const LogLevel
LevelWarn)
( \case
LogLevel
LevelWarn -> () -> Either LogLevel ()
forall a b. b -> Either a b
Right ()
LogLevel
other -> LogLevel -> Either LogLevel ()
forall a b. a -> Either a b
Left LogLevel
other
)
{-# INLINE _LevelWarn #-}
_LevelError :: Prism' LogLevel ()
_LevelError :: Prism' LogLevel ()
_LevelError =
(() -> LogLevel)
-> (LogLevel -> Either LogLevel ()) -> Prism' LogLevel ()
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
(LogLevel -> () -> LogLevel
forall a b. a -> b -> a
const LogLevel
LevelError)
( \case
LogLevel
LevelError -> () -> Either LogLevel ()
forall a b. b -> Either a b
Right ()
LogLevel
other -> LogLevel -> Either LogLevel ()
forall a b. a -> Either a b
Left LogLevel
other
)
{-# INLINE _LevelError #-}
_LevelOther :: Prism' LogLevel Text
_LevelOther :: Optic' A_Prism NoIx LogLevel Text
_LevelOther =
(Text -> LogLevel)
-> (LogLevel -> Either LogLevel Text)
-> Optic' A_Prism NoIx LogLevel Text
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
Text -> LogLevel
LevelOther
( \case
LevelOther Text
l -> Text -> Either LogLevel Text
forall a b. b -> Either a b
Right Text
l
LogLevel
other -> LogLevel -> Either LogLevel Text
forall a b. a -> Either a b
Left LogLevel
other
)
{-# INLINE _LevelOther #-}
_LevelFatal :: Prism' LogLevel ()
_LevelFatal :: Prism' LogLevel ()
_LevelFatal =
(() -> LogLevel)
-> (LogLevel -> Either LogLevel ()) -> Prism' LogLevel ()
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
(LogLevel -> () -> LogLevel
forall a b. a -> b -> a
const LogLevel
levelFatal)
( \case
LevelOther Text
"Fatal" -> () -> Either LogLevel ()
forall a b. b -> Either a b
Right ()
LogLevel
other -> LogLevel -> Either LogLevel ()
forall a b. a -> Either a b
Left LogLevel
other
)
{-# INLINE _LevelFatal #-}
logLevelToWord :: LogLevel -> Word8
logLevelToWord :: LogLevel -> Word8
logLevelToWord (LevelOther Text
"Trace") = Word8
0
logLevelToWord LogLevel
LevelDebug = Word8
1
logLevelToWord LogLevel
LevelInfo = Word8
2
logLevelToWord LogLevel
LevelWarn = Word8
3
logLevelToWord LogLevel
LevelError = Word8
4
logLevelToWord (LevelOther Text
"Fatal") = Word8
5
logLevelToWord (LevelOther Text
_) = Word8
6