{-| Module : Game.GoreAndAsh.Logging.State Description : State of logging core module Copyright : (c) Anton Gushcha, 2015-2016 License : BSD3 Maintainer : ncrashed@gmail.com Stability : experimental Portability : POSIX Contains description of state for logging core module. -} module Game.GoreAndAsh.Logging.State( LoggingState(..) , LoggingLevel(..) , LoggingSink(..) , emptyLoggingState , filterLogMessage ) where import Control.DeepSeq import Data.Hashable import Data.Text import GHC.Generics (Generic) import qualified Data.HashMap.Strict as H import qualified Data.HashSet as HS import qualified Data.Sequence as S import System.IO -- | Distanation of logging data LoggingSink = -- | Putting to user terminal LoggingConsole -- | Putting into file | LoggingFile deriving (Eq, Ord, Bounded, Show, Read, Generic) instance NFData LoggingSink instance Hashable LoggingSink -- | Describes important of logging message data LoggingLevel = -- | Used for detailed logging LogDebug -- | Used for messages about normal operation of application | LogInfo -- | Used for recoverable errors or defaulting to fallback behavior | LogWarn -- | Used before throwing an exception or fatal fales | LogError -- | Special case of message, that never goes to console, but saved into file | LogMuted deriving (Eq, Ord, Bounded, Show, Read, Generic) instance NFData LoggingLevel instance Hashable LoggingLevel type LoggingFilter = H.HashMap LoggingLevel (HS.HashSet LoggingSink) -- | Inner state of logger. -- -- [@s@] next state, states of modules are chained via nesting data LoggingState s = LoggingState { loggingMsgs :: !(S.Seq (LoggingLevel, Text)) , loggingNextState :: !s , loggingFile :: !(Maybe Handle) , loggingFilter :: !(LoggingFilter) , loggignDebug :: !Bool } deriving (Generic) instance NFData s => NFData (LoggingState s) where rnf LoggingState{..} = loggingMsgs `deepseq` loggingNextState `deepseq` loggingFile `seq` loggingFilter `deepseq` loggignDebug `seq` () -- | Create empty module state emptyLoggingState :: s -> LoggingState s emptyLoggingState s = LoggingState { loggingMsgs = S.empty , loggingNextState = s , loggingFile = Nothing , loggingFilter = H.empty , loggignDebug = False } -- | Returns 'True' if given message level is allowed to go in the sink filterLogMessage :: LoggingState s -> LoggingLevel -> LoggingSink -> Bool filterLogMessage LoggingState{..} ll ls = case H.lookup ll loggingFilter of Nothing -> True Just ss -> HS.member ls ss