module System.Log.Heavy.Types
(
LogSource, LogMessage (..), LogFilter,
IsLogBackend (..), LogBackend (..), Logger,
LoggingT (LoggingT), runLoggingT,
defaultLogFilter,
splitString, splitDots,
logMessage
) where
import Control.Monad.Reader
import Control.Monad.Logger (MonadLogger (..), LogLevel (..))
import Control.Monad.Base
import Control.Monad.Trans.Control
import Data.String
import Language.Haskell.TH
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Text.Lazy as TL
import System.Log.FastLogger
import qualified Data.Text.Format.Heavy as F
type LogSource = [String]
data LogMessage = forall vars. F.VarContainer vars => LogMessage {
lmLevel :: LogLevel
, lmSource :: LogSource
, lmLocation :: Loc
, lmFormatString :: TL.Text
, lmFormatVars :: vars
}
type LogFilter = [(LogSource, LogLevel)]
defaultLogFilter :: LogFilter
defaultLogFilter = [([], LevelInfo)]
class IsLogBackend b where
withLoggingB :: (MonadIO m)
=> b
-> (m a -> IO a)
-> LoggingT m a
-> m a
data LogBackend = forall b. IsLogBackend b => LogBackend b
newtype LoggingT m a = LoggingT {
runLoggingT_ :: ReaderT Logger m a
}
deriving (Functor, Applicative, Monad, MonadReader Logger, MonadTrans)
deriving instance MonadIO m => MonadIO (LoggingT m)
instance MonadIO m => MonadBase IO (LoggingT m) where
liftBase = liftIO
instance MonadTransControl LoggingT where
type StT LoggingT a = StT (ReaderT Logger) a
liftWith = defaultLiftWith LoggingT runLoggingT_
restoreT = defaultRestoreT LoggingT
instance (MonadBaseControl IO m, MonadIO m) => MonadBaseControl IO (LoggingT m) where
type StM (LoggingT m) a = ComposeSt LoggingT m a
liftBaseWith = defaultLiftBaseWith
restoreM = defaultRestoreM
runLoggingT :: LoggingT m a -> Logger -> m a
runLoggingT actions logger = runReaderT (runLoggingT_ actions) logger
type Logger = LogMessage -> IO ()
textFromLogStr :: ToLogStr str => str -> TL.Text
textFromLogStr str = TL.fromStrict $ TE.decodeUtf8 $ fromLogStr $ toLogStr str
instance MonadIO m => MonadLogger (LoggingT m) where
monadLoggerLog loc src level msg =
logMessage $ LogMessage level src' loc (textFromLogStr msg) ()
where
src' = splitDots $ T.unpack src
instance F.Formatable LogStr where
formatVar fmt str = F.formatVar fmt $ fromLogStr str
splitString :: Char -> String -> [String]
splitString _ "" = []
splitString c s = let (l, s') = break (== c) s
in l : case s' of
[] -> []
(_:s'') -> splitString c s''
splitDots :: String -> [String]
splitDots = splitString '.'
logMessage :: (MonadIO m) => LogMessage -> LoggingT m ()
logMessage m = do
logger <- ask
liftIO $ logger m