packages feed

log-warper 1.4.1 → 1.5.0

raw patch · 13 files changed

+281/−284 lines, 13 filesdep −safecopyPVP ok

version bump matches the API change (PVP)

Dependencies removed: safecopy

API changes (from Hackage documentation)

- System.Wlog.CanLog: LogEvent :: !LoggerName -> !Severity -> !Text -> LogEvent
- System.Wlog.CanLog: NamedPureLogger :: PureLogger (LoggerNameBox m) a -> NamedPureLogger m a
- System.Wlog.CanLog: PureLogger :: StateT (DList LogEvent) m a -> PureLogger m a
- System.Wlog.CanLog: [leLoggerName] :: LogEvent -> !LoggerName
- System.Wlog.CanLog: [leMessage] :: LogEvent -> !Text
- System.Wlog.CanLog: [leSeverity] :: LogEvent -> !Severity
- System.Wlog.CanLog: [runNamedPureLogger] :: NamedPureLogger m a -> PureLogger (LoggerNameBox m) a
- System.Wlog.CanLog: [runPureLogger] :: PureLogger m a -> StateT (DList LogEvent) m a
- System.Wlog.CanLog: data LogEvent
- System.Wlog.CanLog: dispatchEvents :: CanLog m => [LogEvent] -> m ()
- System.Wlog.CanLog: instance (System.Wlog.LoggerNameBox.HasLoggerName m, GHC.Base.Monad m) => System.Wlog.LoggerNameBox.HasLoggerName (System.Wlog.CanLog.PureLogger m)
- System.Wlog.CanLog: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (System.Wlog.CanLog.NamedPureLogger m)
- System.Wlog.CanLog: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (System.Wlog.CanLog.PureLogger m)
- System.Wlog.CanLog: instance Control.Monad.Morph.MFunctor System.Wlog.CanLog.NamedPureLogger
- System.Wlog.CanLog: instance Control.Monad.Morph.MFunctor System.Wlog.CanLog.PureLogger
- System.Wlog.CanLog: instance Control.Monad.Trans.Class.MonadTrans System.Wlog.CanLog.NamedPureLogger
- System.Wlog.CanLog: instance Control.Monad.Trans.Class.MonadTrans System.Wlog.CanLog.PureLogger
- System.Wlog.CanLog: instance Data.SafeCopy.SafeCopy.SafeCopy System.Wlog.CanLog.LogEvent
- System.Wlog.CanLog: instance GHC.Base.Functor m => GHC.Base.Functor (System.Wlog.CanLog.NamedPureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Functor m => GHC.Base.Functor (System.Wlog.CanLog.PureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.DList.DList System.Wlog.CanLog.LogEvent) (System.Wlog.CanLog.NamedPureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.DList.DList System.Wlog.CanLog.LogEvent) (System.Wlog.CanLog.PureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => GHC.Base.Applicative (System.Wlog.CanLog.NamedPureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => GHC.Base.Applicative (System.Wlog.CanLog.PureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => GHC.Base.Monad (System.Wlog.CanLog.NamedPureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => GHC.Base.Monad (System.Wlog.CanLog.PureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => System.Wlog.CanLog.CanLog (System.Wlog.CanLog.NamedPureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => System.Wlog.CanLog.CanLog (System.Wlog.CanLog.PureLogger m)
- System.Wlog.CanLog: instance GHC.Base.Monad m => System.Wlog.LoggerNameBox.HasLoggerName (System.Wlog.CanLog.NamedPureLogger m)
- System.Wlog.CanLog: instance GHC.Show.Show System.Wlog.CanLog.LogEvent
- System.Wlog.CanLog: launchNamedPureLog :: (WithLogger n, Monad m) => (forall f. Functor f => m (f a) -> n (f b)) -> NamedPureLogger m a -> n b
- System.Wlog.CanLog: launchPureLog :: (CanLog n, Monad m) => (forall f. Functor f => m (f a) -> n (f b)) -> PureLogger m a -> n b
- System.Wlog.CanLog: logEvents :: WithLogger m => [LogEvent] -> m ()
- System.Wlog.CanLog: newtype NamedPureLogger m a
- System.Wlog.CanLog: newtype PureLogger m a
- System.Wlog.CanLog: runNamedPureLog :: (Monad m, HasLoggerName m) => NamedPureLogger m a -> m (a, [LogEvent])
- System.Wlog.CanLog: runPureLog :: Monad m => PureLogger m a -> m (a, [LogEvent])
- System.Wlog.LoggerName: [loggerName] :: LoggerName -> String
- System.Wlog.LoggerName: instance Data.SafeCopy.SafeCopy.SafeCopy System.Wlog.LoggerName.LoggerName
- System.Wlog.LoggerNameBox: class HasLoggerName m
- System.Wlog.LoggerNameBox: getLoggerName :: HasLoggerName m => m LoggerName
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.Cont.ContT r m)
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.Except.ExceptT e m)
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.Reader.ReaderT a m)
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.State.Lazy.StateT a m)
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.State.Strict.StateT a m)
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m, GHC.Base.Monoid w) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m, GHC.Base.Monoid w) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.RWS.Strict.RWST r w s m)
- System.Wlog.LoggerNameBox: instance (GHC.Base.Monoid w, GHC.Base.Monad m, System.Wlog.LoggerNameBox.HasLoggerName m) => System.Wlog.LoggerNameBox.HasLoggerName (Control.Monad.Trans.Writer.Lazy.WriterT w m)
- System.Wlog.LoggerNameBox: instance GHC.Base.Monad m => System.Wlog.LoggerNameBox.HasLoggerName (System.Wlog.LoggerNameBox.LoggerNameBox m)
- System.Wlog.LoggerNameBox: instance System.Wlog.LoggerNameBox.HasLoggerName Data.Functor.Identity.Identity
- System.Wlog.LoggerNameBox: modifyLoggerName :: HasLoggerName m => (LoggerName -> LoggerName) -> m a -> m a
- System.Wlog.LoggerNameBox: setLoggerName :: HasLoggerName m => LoggerName -> m a -> m a
- System.Wlog.Severity: instance Data.SafeCopy.SafeCopy.SafeCopy System.Wlog.Severity.Severity
+ System.Wlog.HasLoggerName: askLoggerName :: (HasLoggerName m, MonadTrans t, t n ~ m, Monad n, HasLoggerName n) => m LoggerName
+ System.Wlog.HasLoggerName: class HasLoggerName m where askLoggerName = lift askLoggerName modifyLoggerName f = hoist (modifyLoggerName f)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.Cont.ContT r m)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.Except.ExceptT e m)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.Reader.ReaderT a m)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.State.Lazy.StateT a m)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.State.Strict.StateT a m)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m, GHC.Base.Monoid w) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m, GHC.Base.Monoid w) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.RWS.Strict.RWST r w s m)
+ System.Wlog.HasLoggerName: instance (GHC.Base.Monoid w, GHC.Base.Monad m, System.Wlog.HasLoggerName.HasLoggerName m) => System.Wlog.HasLoggerName.HasLoggerName (Control.Monad.Trans.Writer.Lazy.WriterT w m)
+ System.Wlog.HasLoggerName: instance System.Wlog.HasLoggerName.HasLoggerName Data.Functor.Identity.Identity
+ System.Wlog.HasLoggerName: modifyLoggerName :: (HasLoggerName m, MFunctor t, t n ~ m, Monad n, HasLoggerName n) => (LoggerName -> LoggerName) -> m a -> m a
+ System.Wlog.HasLoggerName: setLoggerName :: HasLoggerName m => LoggerName -> m a -> m a
+ System.Wlog.LoggerName: [getLoggerName] :: LoggerName -> Text
+ System.Wlog.LoggerName: instance GHC.Classes.Ord System.Wlog.LoggerName.LoggerName
+ System.Wlog.LoggerNameBox: instance GHC.Base.Monad m => System.Wlog.HasLoggerName.HasLoggerName (System.Wlog.LoggerNameBox.LoggerNameBox m)
+ System.Wlog.PureLogging: LogEvent :: !LoggerName -> !Severity -> !Text -> LogEvent
+ System.Wlog.PureLogging: NamedPureLogger :: PureLogger (LoggerNameBox m) a -> NamedPureLogger m a
+ System.Wlog.PureLogging: PureLogger :: StateT (DList LogEvent) m a -> PureLogger m a
+ System.Wlog.PureLogging: [leLoggerName] :: LogEvent -> !LoggerName
+ System.Wlog.PureLogging: [leMessage] :: LogEvent -> !Text
+ System.Wlog.PureLogging: [leSeverity] :: LogEvent -> !Severity
+ System.Wlog.PureLogging: [runNamedPureLogger] :: NamedPureLogger m a -> PureLogger (LoggerNameBox m) a
+ System.Wlog.PureLogging: [runPureLogger] :: PureLogger m a -> StateT (DList LogEvent) m a
+ System.Wlog.PureLogging: data LogEvent
+ System.Wlog.PureLogging: dispatchEvents :: CanLog m => [LogEvent] -> m ()
+ System.Wlog.PureLogging: instance (System.Wlog.HasLoggerName.HasLoggerName m, GHC.Base.Monad m) => System.Wlog.HasLoggerName.HasLoggerName (System.Wlog.PureLogging.PureLogger m)
+ System.Wlog.PureLogging: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (System.Wlog.PureLogging.NamedPureLogger m)
+ System.Wlog.PureLogging: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (System.Wlog.PureLogging.PureLogger m)
+ System.Wlog.PureLogging: instance Control.Monad.Morph.MFunctor System.Wlog.PureLogging.NamedPureLogger
+ System.Wlog.PureLogging: instance Control.Monad.Morph.MFunctor System.Wlog.PureLogging.PureLogger
+ System.Wlog.PureLogging: instance Control.Monad.Trans.Class.MonadTrans System.Wlog.PureLogging.NamedPureLogger
+ System.Wlog.PureLogging: instance Control.Monad.Trans.Class.MonadTrans System.Wlog.PureLogging.PureLogger
+ System.Wlog.PureLogging: instance GHC.Base.Functor m => GHC.Base.Functor (System.Wlog.PureLogging.NamedPureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Functor m => GHC.Base.Functor (System.Wlog.PureLogging.PureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.DList.DList System.Wlog.PureLogging.LogEvent) (System.Wlog.PureLogging.NamedPureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Data.DList.DList System.Wlog.PureLogging.LogEvent) (System.Wlog.PureLogging.PureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => GHC.Base.Applicative (System.Wlog.PureLogging.NamedPureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => GHC.Base.Applicative (System.Wlog.PureLogging.PureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => GHC.Base.Monad (System.Wlog.PureLogging.NamedPureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => GHC.Base.Monad (System.Wlog.PureLogging.PureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => System.Wlog.CanLog.CanLog (System.Wlog.PureLogging.NamedPureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => System.Wlog.CanLog.CanLog (System.Wlog.PureLogging.PureLogger m)
+ System.Wlog.PureLogging: instance GHC.Base.Monad m => System.Wlog.HasLoggerName.HasLoggerName (System.Wlog.PureLogging.NamedPureLogger m)
+ System.Wlog.PureLogging: instance GHC.Show.Show System.Wlog.PureLogging.LogEvent
+ System.Wlog.PureLogging: launchNamedPureLog :: (WithLogger n, Monad m) => (forall f. Functor f => m (f a) -> n (f b)) -> NamedPureLogger m a -> n b
+ System.Wlog.PureLogging: launchPureLog :: (CanLog n, Monad m) => (forall f. Functor f => m (f a) -> n (f b)) -> PureLogger m a -> n b
+ System.Wlog.PureLogging: logEvents :: WithLogger m => [LogEvent] -> m ()
+ System.Wlog.PureLogging: newtype NamedPureLogger m a
+ System.Wlog.PureLogging: newtype PureLogger m a
+ System.Wlog.PureLogging: runNamedPureLog :: (Monad m, HasLoggerName m) => NamedPureLogger m a -> m (a, [LogEvent])
+ System.Wlog.PureLogging: runPureLog :: Monad m => PureLogger m a -> m (a, [LogEvent])
- System.Wlog.Handler: class LogHandler a where getFormatter _h = nullFormatter handle h lr@(LR pri _) logname = when (pri >= (getLevel h)) $ do { formattedMsg <- (getFormatter h) h lr (toText logname); emit h formattedMsg logname }
+ System.Wlog.Handler: class LogHandler a where getFormatter _h = nullFormatter handle h lr@(LR pri _) logname = when (pri >= (getLevel h)) $ do { let lName = getLoggerName logname; formattedMsg <- (getFormatter h) h lr lName; emit h formattedMsg lName }
- System.Wlog.Handler: emit :: LogHandler a => a -> Builder -> String -> IO ()
+ System.Wlog.Handler: emit :: LogHandler a => a -> Builder -> Text -> IO ()
- System.Wlog.Handler: handle :: LogHandler a => a -> LogRecord -> String -> IO ()
+ System.Wlog.Handler: handle :: LogHandler a => a -> LogRecord -> LoggerName -> IO ()
- System.Wlog.Logger: debugM :: String -> Text -> IO ()
+ System.Wlog.Logger: debugM :: LoggerName -> Text -> IO ()
- System.Wlog.Logger: errorM :: String -> Text -> IO ()
+ System.Wlog.Logger: errorM :: LoggerName -> Text -> IO ()
- System.Wlog.Logger: getLogger :: String -> IO Logger
+ System.Wlog.Logger: getLogger :: LoggerName -> IO Logger
- System.Wlog.Logger: infoM :: String -> Text -> IO ()
+ System.Wlog.Logger: infoM :: LoggerName -> Text -> IO ()
- System.Wlog.Logger: logM :: String -> Severity -> Text -> IO ()
+ System.Wlog.Logger: logM :: LoggerName -> Severity -> Text -> IO ()
- System.Wlog.Logger: logMCond :: String -> Severity -> Text -> (LogHandlerTag -> Bool) -> IO ()
+ System.Wlog.Logger: logMCond :: LoggerName -> Severity -> Text -> (LogHandlerTag -> Bool) -> IO ()
- System.Wlog.Logger: noticeM :: String -> Text -> IO ()
+ System.Wlog.Logger: noticeM :: LoggerName -> Text -> IO ()
- System.Wlog.Logger: rootLoggerName :: String
+ System.Wlog.Logger: rootLoggerName :: LoggerName
- System.Wlog.Logger: traplogging :: String -> Severity -> Text -> IO a -> IO a
+ System.Wlog.Logger: traplogging :: LoggerName -> Severity -> Text -> IO a -> IO a
- System.Wlog.Logger: updateGlobalLogger :: String -> (Logger -> Logger) -> IO ()
+ System.Wlog.Logger: updateGlobalLogger :: LoggerName -> (Logger -> Logger) -> IO ()
- System.Wlog.Logger: warningM :: String -> Text -> IO ()
+ System.Wlog.Logger: warningM :: LoggerName -> Text -> IO ()
- System.Wlog.LoggerName: LoggerName :: String -> LoggerName
+ System.Wlog.LoggerName: LoggerName :: Text -> LoggerName

Files

CHANGES.md view
@@ -1,3 +1,14 @@+1.5.0+=====++* Replace `String` to `Text` in `LoggerName`.+* Rename `LoggerName` field name to `getLoggerName`.+* Rename `getLoggerName` of `HasLoggerName` class to `askLoggerName`.+* Use `LoggerName` instead of `Text` where possible.+* Make separate `HasLoggerName` module.+* Make separate `PureLogging` module.+* Remove `safecopy` dependency and refactor code.+ 1.4.1 ===== 
log-warper.cabal view
@@ -1,5 +1,5 @@ name:                log-warper-version:             1.4.1+version:             1.5.0 synopsis:            Flexible, configurable, monadic and pretty logging homepage:            https://github.com/serokell/log-warper license:             MIT@@ -24,11 +24,13 @@                        System.Wlog.Handler.Roller                        System.Wlog.Handler.Simple                        System.Wlog.Handler.Syslog+                       System.Wlog.HasLoggerName                        System.Wlog.Launcher                        System.Wlog.Logger                        System.Wlog.LoggerConfig                        System.Wlog.LoggerName                        System.Wlog.LoggerNameBox+                       System.Wlog.PureLogging                        System.Wlog.Severity                        System.Wlog.Wrapper @@ -55,7 +57,6 @@                      , mmorph               >= 1.0.9                      , mtl                  >= 2.2.1                      , network              >= 2.6.3.1-                     , safecopy             >= 0.9.1                      , text                 >= 1.2.2.0                      , text-format          >= 0.3.1.1                      , time                 >= 1.6.0.1
src/System/Wlog.hs view
@@ -17,11 +17,13 @@        , module System.Wlog.Handler.Roller        , module System.Wlog.Handler.Simple        , module System.Wlog.Handler.Syslog+       , module System.Wlog.HasLoggerName        , module System.Wlog.Launcher        , module System.Wlog.Logger        , module System.Wlog.LoggerConfig        , module System.Wlog.LoggerName        , module System.Wlog.LoggerNameBox+       , module System.Wlog.PureLogging        , module System.Wlog.Severity        , module System.Wlog.Wrapper        ) where@@ -31,10 +33,12 @@ import           System.Wlog.Handler.Roller import           System.Wlog.Handler.Simple import           System.Wlog.Handler.Syslog+import           System.Wlog.HasLoggerName import           System.Wlog.Launcher import           System.Wlog.Logger import           System.Wlog.LoggerConfig import           System.Wlog.LoggerName import           System.Wlog.LoggerNameBox+import           System.Wlog.PureLogging import           System.Wlog.Severity import           System.Wlog.Wrapper
src/System/Wlog/CanLog.hs view
@@ -5,10 +5,7 @@ {-# LANGUAGE NoImplicitPrelude     #-} {-# LANGUAGE OverloadedLists       #-} {-# LANGUAGE Rank2Types            #-}-{-# LANGUAGE StandaloneDeriving    #-}-{-# LANGUAGE TemplateHaskell       #-} {-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE ViewPatterns          #-}  -- | Type class that add ability to log messages. -- Supports pure and IO logging.@@ -16,19 +13,7 @@        ( CanLog (..)        , WithLogger -         -- * Pure logging manipulation-       , PureLogger (..)-       , LogEvent   (..)-       , dispatchEvents-       , logEvents-       , runPureLog-       , launchPureLog--       , NamedPureLogger (..)-       , runNamedPureLog-       , launchNamedPureLog--         -- * Logging functions+       -- * Logging functions        , logDebug        , logError        , logInfo@@ -39,21 +24,17 @@  import           Universum -import           Control.Monad.Except       (ExceptT)-import           Control.Monad.Morph        (MFunctor (..))-import qualified Control.Monad.RWS          as RWSLazy-import qualified Control.Monad.RWS.Strict   as RWSStrict-import qualified Control.Monad.State.Lazy   as StateLazy-import           Control.Monad.State.Strict (modify')-import           Control.Monad.Trans        (MonadTrans (lift))-import qualified Data.DList                 as DL (DList, snoc)-import           Data.SafeCopy              (base, deriveSafeCopySimple)+import           Control.Monad.Except      (ExceptT)+import qualified Control.Monad.RWS         as RWSLazy+import qualified Control.Monad.RWS.Strict  as RWSStrict+import qualified Control.Monad.State.Lazy  as StateLazy+import           Control.Monad.Trans       (MonadTrans (lift)) -import           System.Wlog.Logger         (logM)-import           System.Wlog.LoggerName     (LoggerName (..))-import           System.Wlog.LoggerNameBox  (HasLoggerName (..), LoggerNameBox (..),-                                             usingLoggerName)-import           System.Wlog.Severity       (Severity (..))+import           System.Wlog.HasLoggerName (HasLoggerName (..))+import           System.Wlog.Logger        (logM)+import           System.Wlog.LoggerName    (LoggerName (..))+import           System.Wlog.LoggerNameBox (LoggerNameBox (..))+import           System.Wlog.Severity      (Severity (..))   -- | Type alias for constraints 'CanLog' and 'HasLoggerName'.@@ -75,7 +56,7 @@     dispatchMessage name sev t = lift $ dispatchMessage name sev t  instance CanLog IO where-    dispatchMessage (loggerName -> name) prior msg = logM name prior msg+    dispatchMessage name prior msg = logM name prior msg  instance CanLog m => CanLog (LoggerNameBox m) instance CanLog m => CanLog (ReaderT r m)@@ -85,97 +66,6 @@ instance (CanLog m, Monoid w) => CanLog (RWSLazy.RWST r w s m) instance (CanLog m, Monoid w) => CanLog (RWSStrict.RWST r w s m) --- | Holds all required information for 'dispatchLoggerName' function.-data LogEvent = LogEvent-    { leLoggerName :: !LoggerName-    , leSeverity   :: !Severity-    , leMessage    :: !Text-    } deriving (Show)--deriveSafeCopySimple 0 'base ''LogEvent---- | Pure implementation of 'CanLog' type class. Instead of writing log messages--- into console it appends log messages into 'StateT' log. It uses 'DList' for--- better performance, because messages can be added only at the end of log.--- But it uses 'unsafePerformIO' so use with caution within IO.------ TODO: Should we use some @Data.Tree@-like structure to observe message only--- by chosen logger names?-newtype PureLogger m a = PureLogger-    { runPureLogger :: StateT (DL.DList LogEvent) m a-    } deriving (Functor, Applicative, Monad, MonadTrans, MonadState (DL.DList LogEvent),-                MonadThrow, HasLoggerName)--instance Monad m => CanLog (PureLogger m) where-    dispatchMessage leLoggerName leSeverity leMessage = modify' (flip DL.snoc LogEvent{..})--instance MFunctor PureLogger where-    hoist f = PureLogger . hoist f . runPureLogger---- | Return log of pure logging action as list of 'LogEvent'.-runPureLog :: Monad m => PureLogger m a -> m (a, [LogEvent])-runPureLog = fmap (second toList) . flip runStateT mempty . runPureLogger---- | Logs all 'LogEvent'`s from given list. This function supposed to--- be used after 'runPureLog'.-dispatchEvents :: CanLog m => [LogEvent] -> m ()-dispatchEvents = mapM_ dispatchLogEvent-  where-    dispatchLogEvent (LogEvent name sev t) = dispatchMessage name sev t---- | Logs all 'LogEvent'`s from given list. Just like--- 'dispatchEvents' but uses proper logger Name.-logEvents :: WithLogger m => [LogEvent] -> m ()-logEvents events = do-    logName <- getLoggerName-    mapM_ (dispatchLogEvent logName) events-  where-    dispatchLogEvent logName (LogEvent _ sev t) = dispatchMessage logName sev t---- | Performs actual logging once given action completes.-launchPureLog-    :: (CanLog n, Monad m)-    => (forall f. Functor f => m (f a) -> n (f b))-    -> PureLogger m a-    -> n b-launchPureLog hoist' action = do-    (logs, res) <- hoist' $ swap <$> runPureLog action-    res <$ dispatchEvents logs--newtype NamedPureLogger m a = NamedPureLogger-    { runNamedPureLogger :: PureLogger (LoggerNameBox m) a-    } deriving (Functor, Applicative, Monad, MonadState (DL.DList LogEvent),-                MonadThrow, HasLoggerName)--instance MonadTrans NamedPureLogger where-    lift = NamedPureLogger . lift . lift--instance Monad m => CanLog (NamedPureLogger m) where-    dispatchMessage name sev msg =-        NamedPureLogger $ dispatchMessage name sev msg--instance MFunctor NamedPureLogger where-    hoist f = NamedPureLogger . hoist (hoist f) . runNamedPureLogger---- | Return log of pure logging action as list of 'LogEvent',--- using logger name provided by context.-runNamedPureLog-    :: (Monad m, HasLoggerName m)-    => NamedPureLogger m a -> m (a, [LogEvent])-runNamedPureLog (NamedPureLogger action) =-    getLoggerName >>= (`usingLoggerName` runPureLog action)---- | Similar as `launchPureLog`, but provides logger name from current context.-launchNamedPureLog-    :: (WithLogger n, Monad m)-    => (forall f. Functor f => m (f a) -> n (f b))-    -> NamedPureLogger m a-    -> n b-launchNamedPureLog hoist' (NamedPureLogger action) = do-    name <- getLoggerName-    (logs, res) <- hoist' $ swap <$> usingLoggerName name (runPureLog action)-    res <$ dispatchEvents logs- -- | Shortcut for 'logMessage' to use according severity. logDebug, logInfo, logNotice, logWarning, logError     :: WithLogger m@@ -193,5 +83,5 @@     -> Text     -> m () logMessage severity t = do-    name <- getLoggerName+    name <- askLoggerName     dispatchMessage name severity t
src/System/Wlog/Handler.hs view
@@ -26,10 +26,13 @@        , LogHandler(..)        ) where +import           Universum+ import           Data.Text.Lazy.Builder as B+ import           System.Wlog.Formatter  (LogFormatter, nullFormatter)+import           System.Wlog.LoggerName (LoggerName (..)) import           System.Wlog.Severity   (LogRecord (..), Severity)-import           Universum  -- | Tag identifying handlers. data LogHandlerTag@@ -58,15 +61,16 @@      -- | Logs an event if it meets the requirements     -- given by the most recent call to 'setLevel'.-    handle :: a -> LogRecord -> String -> IO ()+    handle :: a -> LogRecord -> LoggerName -> IO ()     handle h lr@(LR pri _) logname =         when (pri >= (getLevel h)) $ do-            formattedMsg <- (getFormatter h) h lr (toText logname)-            emit h formattedMsg logname+            let lName = getLoggerName logname+            formattedMsg <- (getFormatter h) h lr lName+            emit h formattedMsg lName      -- | Forces an event to be logged regardless of     -- the configured level.-    emit :: a -> B.Builder -> String -> IO ()+    emit :: a -> B.Builder -> Text -> IO ()      -- | Read back from logger (e.g. file), newest first. You specify     -- the number of (newest) logging entries. Logger can return @pure
+ src/System/Wlog/HasLoggerName.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE DefaultSignatures     #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE UndecidableInstances  #-}++-- | This module contains type class for 'HasLoggerName'.++module System.Wlog.HasLoggerName+       ( -- * Remove boilerplater+         HasLoggerName (..)+       , setLoggerName+       ) where++import           Universum++import           Control.Monad.Except       (ExceptT (..))+import           Control.Monad.Morph        (MFunctor (..))+import qualified Control.Monad.RWS          as RWSLazy+import qualified Control.Monad.RWS.Strict   as RWSStrict+import qualified Control.Monad.State        as StateLazy (StateT)+import           Control.Monad.State.Strict (StateT)+import           Control.Monad.Trans        (MonadTrans, lift)+import           Control.Monad.Trans.Cont   (ContT, mapContT)+import           Control.Monad.Writer       (WriterT (..))++import           System.Wlog.LoggerName     (LoggerName)++-- | This type class exists to remove boilerplate logging+-- by adding the logger's name to the context in each module.+--+-- TODO: replace current methods with Lens?+class HasLoggerName m where+    -- | Extract logger name from context+    askLoggerName :: m LoggerName++    -- | Change logger name in context+    modifyLoggerName :: (LoggerName -> LoggerName) -> m a -> m a++    default askLoggerName :: (MonadTrans t, t n ~ m, Monad n, HasLoggerName n) => m LoggerName+    askLoggerName = lift askLoggerName++    default modifyLoggerName :: (MFunctor t, t n ~ m, Monad n, HasLoggerName n)+                             => (LoggerName -> LoggerName)+                             -> m a+                             -> m a+    modifyLoggerName f = hoist (modifyLoggerName f)++instance (Monad m, HasLoggerName m) => HasLoggerName (ReaderT a m) where+instance (Monad m, HasLoggerName m) => HasLoggerName (StateT a m) where+instance (Monad m, HasLoggerName m) => HasLoggerName (StateLazy.StateT a m) where+instance (Monoid w, Monad m, HasLoggerName m) => HasLoggerName (WriterT w m) where+instance (Monad m, HasLoggerName m) => HasLoggerName (ExceptT e m) where+instance (Monad m, HasLoggerName m) => HasLoggerName (ContT r m) where+    askLoggerName    = lift askLoggerName+    modifyLoggerName = mapContT . modifyLoggerName++instance (Monad m, HasLoggerName m, Monoid w) => HasLoggerName (RWSLazy.RWST r w s m) where+instance (Monad m, HasLoggerName m, Monoid w) => HasLoggerName (RWSStrict.RWST r w s m) where++instance HasLoggerName Identity where+    askLoggerName    = Identity "Identity"+    modifyLoggerName = flip const++-- | Set logger name in context.+setLoggerName :: HasLoggerName m => LoggerName -> m a -> m a+setLoggerName = modifyLoggerName . const
src/System/Wlog/Launcher.hs view
@@ -37,7 +37,6 @@ import           Control.Error.Util         ((?:)) import           Control.Exception          (throwIO) import qualified Data.HashMap.Strict        as HM hiding (HashMap)-import qualified Data.Text                  as T import           Data.Time                  (UTCTime) import           Data.Yaml                  (decodeFileEither) import           System.Directory           (createDirectoryIfMissing)@@ -103,10 +102,10 @@                     let roundFmt r = (`setFormatter` stdoutFormatterTimeRounded timeF r)                     let fmt = maybe defFmt roundFmt _hwRounding                     thisLoggerHandler <- fmt <$> handlerCreator-                    updateGlobalLogger (loggerName parent) $ addHandler thisLoggerHandler+                    updateGlobalLogger parent $ addHandler thisLoggerHandler          for_ (HM.toList _ltSubloggers) $ \(name, loggerConfig) -> do-            let thisLoggerName = LoggerName $ T.unpack name+            let thisLoggerName = LoggerName name             let thisLogger     = parent <> logMapper thisLoggerName             processLoggers thisLogger loggerConfig 
src/System/Wlog/Logger.hs view
@@ -54,21 +54,22 @@        , retrieveLogContent        ) where +import           Universum+ import           Control.Concurrent.MVar (modifyMVar, modifyMVar_, withMVar) import           Control.Lens            (makeLenses)-import           Data.List               (isPrefixOf) import qualified Data.Map                as M import           Data.Maybe              (fromJust) import qualified Data.Text               as T import qualified Data.Text.IO            as TIO import           System.FilePath         ((</>)) import           System.IO.Unsafe        (unsafePerformIO)-import           Universum  import           System.Wlog.Handler     (LogHandler (getTag),                                           LogHandlerTag (HandlerFilelike), close,                                           readBack) import qualified System.Wlog.Handler     (handle)+import           System.Wlog.LoggerName  (LoggerName (..)) import           System.Wlog.Severity    (LogRecord (..), Severity (..))  @@ -81,15 +82,15 @@ data Logger = Logger     { _lLevel    :: Maybe Severity     , _lHandlers :: [HandlerT]-    , _lName     :: String+    , _lName     :: LoggerName     } deriving (Generic)  makeLenses ''Logger -type LogTree = Map String Logger+type LogTree = Map LoggerName Logger  data LogInternalState = LogInternalState-    { liTree   :: Map String Logger+    { liTree   :: LogTree     , liPrefix :: Maybe FilePath     } deriving (Generic) @@ -99,8 +100,8 @@  -- | The name of the root logger, which is always defined and present -- on the system.-rootLoggerName :: String-rootLoggerName = ""+rootLoggerName :: LoggerName+rootLoggerName = mempty  --------------------------------------------------------------------------- -- Logger Tree Storage@@ -124,14 +125,14 @@ >["", "MissingH", "System.Cmd.Utils", "System.Cmd.Utils.pOpen"]  -}-componentsOfName :: String -> [String]-componentsOfName name =-    rootLoggerName : joinComp (split "." name) []+componentsOfName :: LoggerName -> [LoggerName]+componentsOfName (LoggerName name) =+    rootLoggerName : (LoggerName <$> (joinComp (T.splitOn "." name) ""))   where     joinComp [] _ = []-    joinComp (x:xs) [] = x : joinComp xs x+    joinComp (x:xs) "" = x : joinComp xs x     joinComp (x:xs) accum =-        let newlevel = accum ++ "." ++ x+        let newlevel = accum <> "." <> x         in newlevel : joinComp xs newlevel  ---------------------------------------------------------------------------@@ -139,7 +140,7 @@ ---------------------------------------------------------------------------  -- | Log a message using the given logger at a given priority.-logM :: String     -- ^ Name of the logger to use+logM :: LoggerName -- ^ Name of the logger to use      -> Severity   -- ^ Severity of this message      -> Text       -- ^ The log text itself      -> IO ()@@ -147,7 +148,7 @@     l <- getLogger logname     logL l pri msg -logMCond :: String -> Severity -> Text -> (LogHandlerTag -> Bool) -> IO ()+logMCond :: LoggerName -> Severity -> Text -> (LogHandlerTag -> Bool) -> IO () logMCond logname sev msg cond = do     l <- getLogger logname     logLCond l sev msg cond@@ -157,31 +158,31 @@ ---------------------------------------------------------------------------  {- | Log a message at 'Debug' priority -}-debugM :: String                       -- ^ Logger name+debugM :: LoggerName                   -- ^ Logger name        -> Text                         -- ^ Log message        -> IO () debugM s = logM s Debug  {- | Log a message at 'Info' priority -}-infoM :: String                        -- ^ Logger name+infoM :: LoggerName                    -- ^ Logger name       -> Text                          -- ^ Log message       -> IO () infoM s = logM s Info  {- | Log a message at 'Notice' priority -}-noticeM :: String                      -- ^ Logger name+noticeM :: LoggerName                  -- ^ Logger name         -> Text                        -- ^ Log message         -> IO () noticeM s = logM s Notice  {- | Log a message at 'Warning' priority -}-warningM :: String                     -- ^ Logger name+warningM :: LoggerName                 -- ^ Logger name          -> Text                       -- ^ Log message          -> IO () warningM s = logM s Warning  {- | Log a message at 'Error' priority -}-errorM :: String                       -- ^ Logger name+errorM :: LoggerName                   -- ^ Logger name        -> Text                         -- ^ Log message        -> IO () errorM s = logM s Error@@ -193,7 +194,7 @@ -- | Returns the logger for the given name.  If no logger with that name -- exists, creates new loggers and any necessary parent loggers, with -- no connected handlers.-getLogger :: String -> IO Logger+getLogger :: LoggerName -> IO Logger getLogger lname = modifyMVar logInternalState $ \lt@LogInternalState{..} ->     case M.lookup lname liTree of       Just x ->  return (lt, x) -- A logger exists; return it and leave tree@@ -203,7 +204,7 @@           let result = fromJust $ M.lookup lname newlt           return (LogInternalState newlt liPrefix, result)   where-    createLoggers :: [String] -> LogTree -> LogTree+    createLoggers :: [LoggerName] -> LogTree -> LogTree     createLoggers [] lt = lt -- No names to add; return tree unmodified     createLoggers (x:xs) lt = -- Add logger to tree         createLoggers xs $@@ -228,24 +229,23 @@ handle :: Logger -> LogRecord -> (LogHandlerTag -> Bool) -> IO () handle l lrecord@(LR sev _) handlerFilter = do     lp <- getLoggerSeverity nm-    if sev >= lp then do+    when (sev >= lp) $ do         ph <- concatMap (view lHandlers) <$> parentLoggers nm         forM_ ph $ callHandler lrecord nm-    else return ()   where     nm = view lName l-    parentLoggers :: String -> IO [Logger]+    parentLoggers :: LoggerName -> IO [Logger]     parentLoggers = mapM getLogger . componentsOfName     -- Get the severity we should use. Find the first logger in the     -- tree, starting here, with a set severity. If even root doesn't     -- have one, assume "Debug".-    getLoggerSeverity :: String -> IO Severity+    getLoggerSeverity :: LoggerName -> IO Severity     getLoggerSeverity name = do         pl <- parentLoggers name         case catMaybes . map (view lLevel) $ (l : pl) of             []    -> pure Debug             (x:_) -> pure x-    callHandler :: LogRecord -> String -> HandlerT -> IO ()+    callHandler :: LogRecord -> LoggerName -> HandlerT -> IO ()     callHandler lr loggername (HandlerT x) =         when (handlerFilter $ getTag x) $             System.Wlog.Handler.handle x lr loggername@@ -308,7 +308,7 @@ -- > updateGlobalLogger "MyApp.BuggyComponent" -- >                    (setLevel DEBUG . setHandlers [s]) updateGlobalLogger-    :: String -- ^ Logger name+    :: LoggerName         -- ^ Logger name     -> (Logger -> Logger) -- ^ Function to call     -> IO () updateGlobalLogger ln func =@@ -328,7 +328,7 @@ -- -- Takes a logger name, priority, leading description text (you can set it to -- @\"\"@ if you don't want any), and action to run.-traplogging :: String     -- ^ Logger name+traplogging :: LoggerName -- ^ Logger name             -> Severity   -- ^ Logging priority             -> Text       -- ^ Descriptive text to prepend to logged messages             -> IO a       -- ^ Action to run@@ -371,31 +371,3 @@             []  -> takeMaybe . reverse . T.lines <$> TIO.readFile filePathFull             xs  -> error $ "Found more than one (" <> show (length xs) <>                            "handle with the same filePath tag, impossible."--------------------------------------------------------------------------------- List util functions--------------------------------------------------------------------------------- | This function pulled in from MissingH to avoid a dep on it-split :: Eq a => [a] -> [a] -> [[a]]-split _ [] = []-split delim str =-    let (firstline, remainder) = breakList (isPrefixOf delim) str-    in firstline :-       case remainder of-           [] -> []-           x | x == delim -> [] : []-             | otherwise -> split delim (drop (length delim) x)---- This function also pulled from MissingH-breakList :: ([a] -> Bool) -> [a] -> ([a], [a])-breakList func = spanList (not . func)---- This function also pulled from MissingH-spanList :: ([a] -> Bool) -> [a] -> ([a], [a])-spanList _ [] = ([],[])-spanList func l@(x:xs) =-    let (ys, zs) = spanList func xs-    in if func l-       then (x : ys, zs)-       else ([], l)
src/System/Wlog/LoggerName.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TemplateHaskell #-}- -- | Contains @newtype@ wrapper around logger name to support hierarchy.  module System.Wlog.LoggerName@@ -7,25 +5,20 @@        , loggerNameF        ) where +import           Universum+ import           Data.Hashable       (Hashable)-import           Data.SafeCopy       (base, deriveSafeCopySimple) import           Data.Semigroup      (Semigroup) import qualified Data.Semigroup      as Semigroup import           Data.String         (IsString) import           Data.Text.Buildable (Buildable) import qualified Data.Text.Buildable as Buildable-import           Formatting          (Format, bprint, build, string)-import           Universum+import           Formatting          (Format, bprint, build, stext)  -- | Logger name to keep in context.---- TODO: replace 'String' with 'Text'--- TODO: change field name into @getLoggerName@ to follow naming convention newtype LoggerName = LoggerName-    { loggerName :: String-    } deriving (Show, IsString, Eq, Hashable)--deriveSafeCopySimple 0 'base ''LoggerName+    { getLoggerName :: Text+    } deriving (Show, IsString, Eq, Ord, Hashable)  -- | Defined such that @n1@ is parent for @(n1 <> n2)@ -- (see <http://hackage.haskell.org/package/hslogger-1.2.10/docs/System-Log-Logger.html hslogger description>).@@ -33,14 +26,14 @@     LoggerName parent <> LoggerName suffix         | null parent = LoggerName suffix         | null suffix = LoggerName parent-        | otherwise   = LoggerName $ parent ++ "." ++ suffix+        | otherwise   = LoggerName $ parent <> "." <> suffix  instance Monoid LoggerName where     mempty = ""     mappend = (Semigroup.<>)  instance Buildable LoggerName where-    build = bprint string . loggerName+    build = bprint stext . getLoggerName  -- | 'LoggerName' formatter which restricts type. loggerNameF :: Format r (LoggerName -> r)
src/System/Wlog/LoggerNameBox.hs view
@@ -7,90 +7,25 @@  module System.Wlog.LoggerNameBox        ( -- * Remove boilerplater-         HasLoggerName (..)-       , LoggerNameBox (..)-       , setLoggerName+         LoggerNameBox (..)        , usingLoggerName        ) where +import           Universum+ import           Control.Monad.Base          (MonadBase) import           Control.Monad.Catch         (MonadCatch, MonadMask, MonadThrow)-import           Control.Monad.Except        (ExceptT (..), mapExceptT) import           Control.Monad.Except        (MonadError) import           Control.Monad.Fix           (MonadFix) import           Control.Monad.Morph         (MFunctor (..))-import           Control.Monad.Reader        (MonadReader (..), ReaderT, mapReaderT,-                                              runReaderT)-import qualified Control.Monad.RWS           as RWSLazy-import qualified Control.Monad.RWS.Strict    as RWSStrict-import qualified Control.Monad.State         as StateLazy (StateT, mapStateT)-import           Control.Monad.State.Strict  (MonadState, StateT, mapStateT)+import           Control.Monad.Reader        (MonadReader (..), ReaderT, runReaderT)+import           Control.Monad.State.Strict  (MonadState) import           Control.Monad.Trans         (MonadIO, MonadTrans, lift)-import           Control.Monad.Trans.Cont    (ContT, mapContT) import           Control.Monad.Trans.Control (MonadBaseControl (..))-import           Control.Monad.Writer        (WriterT (..), mapWriterT)-import           Universum +import           System.Wlog.HasLoggerName   (HasLoggerName (..)) import           System.Wlog.LoggerName      (LoggerName) --- | This type class exists to remove boilerplate logging--- by adding the logger's name to the context in each module.------ TODO: replace current methods with Lens?-class HasLoggerName m where-    -- | Extract logger name from context-    getLoggerName :: m LoggerName--    -- | Change logger name in context-    modifyLoggerName :: (LoggerName -> LoggerName) -> m a -> m a--instance (Monad m, HasLoggerName m) => HasLoggerName (ReaderT a m) where-    getLoggerName = lift getLoggerName--    modifyLoggerName = mapReaderT . modifyLoggerName--instance (Monad m, HasLoggerName m) => HasLoggerName (StateT a m) where-    getLoggerName = lift getLoggerName--    modifyLoggerName = mapStateT . modifyLoggerName--instance (Monad m, HasLoggerName m) => HasLoggerName (StateLazy.StateT a m) where-    getLoggerName = lift getLoggerName-    modifyLoggerName = StateLazy.mapStateT . modifyLoggerName--instance (Monoid w, Monad m, HasLoggerName m) => HasLoggerName (WriterT w m) where-    getLoggerName = lift getLoggerName--    modifyLoggerName = mapWriterT . modifyLoggerName--instance (Monad m, HasLoggerName m) => HasLoggerName (ExceptT e m) where-    getLoggerName = lift getLoggerName--    modifyLoggerName = mapExceptT . modifyLoggerName--instance (Monad m, HasLoggerName m) => HasLoggerName (ContT r m) where-    getLoggerName = lift getLoggerName--    modifyLoggerName = mapContT . modifyLoggerName--instance (Monad m, HasLoggerName m, Monoid w) => HasLoggerName (RWSLazy.RWST r w s m) where-    getLoggerName = lift getLoggerName--    modifyLoggerName = RWSLazy.mapRWST . modifyLoggerName--instance (Monad m, HasLoggerName m, Monoid w) => HasLoggerName (RWSStrict.RWST r w s m) where-    getLoggerName = lift getLoggerName--    modifyLoggerName = RWSStrict.mapRWST . modifyLoggerName--instance HasLoggerName Identity where-    getLoggerName    = Identity "Identity"-    modifyLoggerName = flip const---- | Set logger name in context.-setLoggerName :: HasLoggerName m => LoggerName -> m a -> m a-setLoggerName = modifyLoggerName . const- -- | Default implementation of `WithNamedLogger`. newtype LoggerNameBox m a = LoggerNameBox     { loggerNameBoxEntry :: ReaderT LoggerName m a@@ -101,7 +36,7 @@ instance MonadReader r m => MonadReader r (LoggerNameBox m) where     ask = lift ask     reader = lift . reader-    local f (LoggerNameBox m) = getLoggerName >>= lift . local f . runReaderT m+    local f (LoggerNameBox m) = askLoggerName >>= lift . local f . runReaderT m  instance MonadBaseControl b m => MonadBaseControl b (LoggerNameBox m) where     type StM (LoggerNameBox m) a = StM (ReaderT LoggerName m) a@@ -117,6 +52,6 @@ usingLoggerName name = flip runReaderT name . loggerNameBoxEntry  instance Monad m => HasLoggerName (LoggerNameBox m) where-    getLoggerName = LoggerNameBox ask+    askLoggerName = LoggerNameBox ask      modifyLoggerName how = LoggerNameBox . local how . loggerNameBoxEntry
+ src/System/Wlog/PureLogging.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude     #-}+{-# LANGUAGE OverloadedLists       #-}+{-# LANGUAGE Rank2Types            #-}+{-# LANGUAGE TypeFamilies          #-}++-- | This module supports pure logging.+module System.Wlog.PureLogging+       (+       -- * Pure logging manipulation+         PureLogger (..)+       , LogEvent   (..)+       , dispatchEvents+       , logEvents+       , runPureLog+       , launchPureLog++       , NamedPureLogger (..)+       , runNamedPureLog+       , launchNamedPureLog+       ) where++import           Universum++import           Control.Monad.Morph        (MFunctor (..))+import           Control.Monad.State.Strict (modify')+import           Control.Monad.Trans        (MonadTrans (lift))+import qualified Data.DList                 as DL (DList, snoc)++import           System.Wlog.CanLog         (CanLog (..), WithLogger)+import           System.Wlog.HasLoggerName  (HasLoggerName (..))+import           System.Wlog.LoggerName     (LoggerName (..))+import           System.Wlog.LoggerNameBox  (LoggerNameBox (..), usingLoggerName)+import           System.Wlog.Severity       (Severity (..))++-- | Holds all required information for 'dispatchLoggerName' function.+data LogEvent = LogEvent+    { leLoggerName :: !LoggerName+    , leSeverity   :: !Severity+    , leMessage    :: !Text+    } deriving (Show)++-- | Pure implementation of 'CanLog' type class. Instead of writing log messages+-- into console it appends log messages into 'StateT' log. It uses 'DList' for+-- better performance, because messages can be added only at the end of log.+-- But it uses 'unsafePerformIO' so use with caution within IO.+--+-- TODO: Should we use some @Data.Tree@-like structure to observe message only+-- by chosen logger names?+newtype PureLogger m a = PureLogger+    { runPureLogger :: StateT (DL.DList LogEvent) m a+    } deriving (Functor, Applicative, Monad, MonadTrans, MonadState (DL.DList LogEvent),+                MonadThrow, HasLoggerName)++instance Monad m => CanLog (PureLogger m) where+    dispatchMessage leLoggerName leSeverity leMessage = modify' (flip DL.snoc LogEvent{..})++instance MFunctor PureLogger where+    hoist f = PureLogger . hoist f . runPureLogger++-- | Return log of pure logging action as list of 'LogEvent'.+runPureLog :: Monad m => PureLogger m a -> m (a, [LogEvent])+runPureLog = fmap (second toList) . flip runStateT mempty . runPureLogger++-- | Logs all 'LogEvent'`s from given list. This function supposed to+-- be used after 'runPureLog'.+dispatchEvents :: CanLog m => [LogEvent] -> m ()+dispatchEvents = mapM_ dispatchLogEvent+  where+    dispatchLogEvent (LogEvent name sev t) = dispatchMessage name sev t++-- | Logs all 'LogEvent'`s from given list. Just like+-- 'dispatchEvents' but uses proper logger Name.+logEvents :: WithLogger m => [LogEvent] -> m ()+logEvents events = do+    logName <- askLoggerName+    mapM_ (dispatchLogEvent logName) events+  where+    dispatchLogEvent logName (LogEvent _ sev t) = dispatchMessage logName sev t++-- | Performs actual logging once given action completes.+launchPureLog+    :: (CanLog n, Monad m)+    => (forall f. Functor f => m (f a) -> n (f b))+    -> PureLogger m a+    -> n b+launchPureLog hoist' action = do+    (logs, res) <- hoist' $ swap <$> runPureLog action+    res <$ dispatchEvents logs++newtype NamedPureLogger m a = NamedPureLogger+    { runNamedPureLogger :: PureLogger (LoggerNameBox m) a+    } deriving (Functor, Applicative, Monad, MonadState (DL.DList LogEvent),+                MonadThrow, HasLoggerName)++instance MonadTrans NamedPureLogger where+    lift = NamedPureLogger . lift . lift++instance Monad m => CanLog (NamedPureLogger m) where+    dispatchMessage name sev msg =+        NamedPureLogger $ dispatchMessage name sev msg++instance MFunctor NamedPureLogger where+    hoist f = NamedPureLogger . hoist (hoist f) . runNamedPureLogger++-- | Return log of pure logging action as list of 'LogEvent',+-- using logger name provided by context.+runNamedPureLog+    :: (Monad m, HasLoggerName m)+    => NamedPureLogger m a -> m (a, [LogEvent])+runNamedPureLog (NamedPureLogger action) =+    askLoggerName >>= (`usingLoggerName` runPureLog action)++-- | Similar as `launchPureLog`, but provides logger name from current context.+launchNamedPureLog+    :: (WithLogger n, Monad m)+    => (forall f. Functor f => m (f a) -> n (f b))+    -> NamedPureLogger m a+    -> n b+launchNamedPureLog hoist' (NamedPureLogger action) = do+    name <- askLoggerName+    (logs, res) <- hoist' $ swap <$> usingLoggerName name (runPureLog action)+    res <$ dispatchEvents logs
src/System/Wlog/Severity.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TemplateHaskell #-}- -- | Custom wrapper around @hslogger.Priority@.  module System.Wlog.Severity@@ -7,11 +5,11 @@        , LogRecord(..)        ) where -import           Data.SafeCopy (base, deriveSafeCopySimple)+import           Universum+ import           Data.Typeable (Typeable) import           Data.Yaml     (FromJSON, ToJSON) import           GHC.Generics  (Generic)-import           Universum  -- | Severity is level of log message importance. It uniquely -- determines which messages to print.@@ -25,8 +23,6 @@  instance FromJSON Severity instance ToJSON   Severity--deriveSafeCopySimple 0 'base ''Severity  -- | Internal type of log records. data LogRecord = LR !Severity !Text deriving Show
src/System/Wlog/Wrapper.hs view
@@ -90,14 +90,14 @@  -- | Set severity for given logger. By default parent's severity is used. setSeverity :: MonadIO m => LoggerName -> Severity -> m ()-setSeverity (LoggerName name) =+setSeverity name =     liftIO . updateGlobalLogger name . setLevel  -- | Set or clear severity. setSeverityMaybe     :: MonadIO m     => LoggerName -> Maybe Severity -> m ()-setSeverityMaybe (LoggerName name) Nothing =+setSeverityMaybe name Nothing =     liftIO $ updateGlobalLogger name clearLevel setSeverityMaybe n (Just x) = setSeverity n x