{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances, ExistentialQuantification, TypeFamilies, GeneralizedNewtypeDeriving, StandaloneDeriving, MultiParamTypeClasses, UndecidableInstances, AllowAmbiguousTypes, ScopedTypeVariables, FunctionalDependencies, FlexibleContexts, ConstraintKinds #-}
module System.Log.Heavy.LoggingT
(
LoggingT (LoggingT), LoggingTState (..),
runLoggingT
) where
import Control.Monad.Reader
import Control.Monad.Base
import Control.Monad.Trans.Control
import System.Log.Heavy.Types
data LoggingTState = LoggingTState {
ltsLogger :: SpecializedLogger
, ltsBackend :: AnyLogBackend
, ltsContext :: LogContext
}
newtype LoggingT m a = LoggingT {
runLoggingT_ :: ReaderT LoggingTState m a
}
deriving (Functor, Applicative, Monad, MonadReader LoggingTState, 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 LoggingTState) 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
instance Monad m => HasLogger (LoggingT m) where
getLogger = asks ltsLogger
localLogger l actions = LoggingT $ ReaderT $ \lts -> runReaderT (runLoggingT_ actions) $ lts {ltsLogger = l}
instance (Monad m) => HasLogContext (LoggingT m) where
getLogContext = asks ltsContext
withLogContext frame actions =
LoggingT $ ReaderT $ \lts -> runReaderT (runLoggingT_ actions) $ lts {ltsContext = frame: ltsContext lts}
runLoggingT :: LoggingT m a -> LoggingTState -> m a
runLoggingT actions context = runReaderT (runLoggingT_ actions) context
instance Monad m => HasLogBackend AnyLogBackend (LoggingT m) where
getLogBackend = asks ltsBackend