packages feed

log-effect 0.4.0.1 → 1.0.0

raw patch · 6 files changed

+138/−205 lines, 6 filesdep +monad-controldep +textdep +transformers-basedep −fast-loggerdep −timedep ~basedep ~bytestringdep ~extensible-effectsnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: monad-control, text, transformers-base

Dependencies removed: fast-logger, time

Dependency ranges changed: base, bytestring, extensible-effects

API changes (from Hackage documentation)

- Control.Eff.Log: Log :: a -> v -> Log a v
- Control.Eff.Log: instance Functor (Log a)
- Control.Eff.Log: instance Typeable2 Log
- Control.Eff.Log: runLogFile :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r) => FilePath -> proxy l -> Eff (Log l :> r) a -> Eff r a
- Control.Eff.Log: runLogStderr :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r) => proxy l -> Eff (Log l :> r) a -> Eff r a
- Control.Eff.Log: runLogStdout :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r) => proxy l -> Eff (Log l :> r) a -> Eff r a
- Control.Eff.Log: runLogWithLoggerSet :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r) => LoggerSet -> proxy l -> Eff (Log l :> r) a -> Eff r a
- Control.Eff.Log.Simple: ALERT :: Severity
- Control.Eff.Log.Simple: CRITICAL :: Severity
- Control.Eff.Log.Simple: DEBUG :: Severity
- Control.Eff.Log.Simple: ERROR :: Severity
- Control.Eff.Log.Simple: INFO :: Severity
- Control.Eff.Log.Simple: NOTICE :: Severity
- Control.Eff.Log.Simple: PANIC :: Severity
- Control.Eff.Log.Simple: WARNING :: Severity
- Control.Eff.Log.Simple: alert :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
- Control.Eff.Log.Simple: critical :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
- Control.Eff.Log.Simple: data Severity
- Control.Eff.Log.Simple: debug :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
- Control.Eff.Log.Simple: error :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
- Control.Eff.Log.Simple: info :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
- Control.Eff.Log.Simple: instance Bounded Severity
- Control.Eff.Log.Simple: instance Enum Severity
- Control.Eff.Log.Simple: instance Eq Severity
- Control.Eff.Log.Simple: instance Ord Severity
- Control.Eff.Log.Simple: instance Read Severity
- Control.Eff.Log.Simple: instance Show Severity
- Control.Eff.Log.Simple: instance ToLogStr Severity
- Control.Eff.Log.Simple: instance ToLogStr a => ToLogStr (Severity, a)
- Control.Eff.Log.Simple: instance Typeable Severity
- Control.Eff.Log.Simple: logTo :: (Typeable l, Member (Log (Severity, l)) r) => Severity -> l -> Eff r ()
- Control.Eff.Log.Simple: notice :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
- Control.Eff.Log.Simple: panic :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
- Control.Eff.Log.Simple: type SimpleLog a = Log (Severity, a)
- Control.Eff.Log.Simple: warning :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()
+ Control.Eff.Log: class LogMessage l
+ Control.Eff.Log: data LogM m l v
+ Control.Eff.Log: instance (Control.Monad.Base.MonadBase m m, Control.Eff.Lift.Lifted m r, Control.Monad.Trans.Control.MonadBaseControl m (Control.Eff.Internal.Eff r)) => Control.Monad.Trans.Control.MonadBaseControl m (Control.Eff.Internal.Eff (Control.Eff.Log.Log l : r))
+ Control.Eff.Log: instance (Control.Monad.Base.MonadBase m m, Control.Eff.Lift.Lifted m r, Control.Monad.Trans.Control.MonadBaseControl m (Control.Eff.Internal.Eff r)) => Control.Monad.Trans.Control.MonadBaseControl m (Control.Eff.Internal.Eff (Control.Eff.Log.LogM m l : r))
+ Control.Eff.Log: instance Control.Eff.Log.LogMessage Data.ByteString.Internal.ByteString
+ Control.Eff.Log: instance Control.Eff.Log.LogMessage Data.Text.Internal.Text
+ Control.Eff.Log: instance Control.Eff.Log.LogMessage [GHC.Types.Char]
+ Control.Eff.Log: logM :: (Member (LogM m l) r, Lifted m r) => l -> Eff r ()
+ Control.Eff.Log: runLogM :: Lifted m r => Logger m l -> Eff (LogM m l : r) a -> Eff r a
+ Control.Eff.Log: stderrLogger :: (LogMessage l, MonadBase IO m) => Logger m l
+ Control.Eff.Log: stdoutLogger :: (LogMessage l, MonadBase IO m) => Logger m l
+ Control.Eff.Log: toMsg :: LogMessage l => l -> ByteString
- Control.Eff.Log: data Log a v
+ Control.Eff.Log: data Log l v
- Control.Eff.Log: filterLog :: (Typeable l, Member (Log l) r) => (l -> Bool) -> Eff r a -> Eff r a
+ Control.Eff.Log: filterLog :: forall l r a. Member (Log l) r => (l -> Bool) -> Eff r a -> Eff r a
- Control.Eff.Log: filterLog' :: (Typeable l, Member (Log l) r) => (l -> Bool) -> proxy l -> Eff r a -> Eff r a
+ Control.Eff.Log: filterLog' :: Member (Log l) r => (l -> Bool) -> proxy l -> Eff r a -> Eff r a
- Control.Eff.Log: logE :: (Typeable l, Member (Log l) r) => l -> Eff r ()
+ Control.Eff.Log: logE :: Member (Log l) r => l -> Eff r ()
- Control.Eff.Log: runLog :: (Typeable l, Typeable1 m, SetMember Lift (Lift m) r) => Logger m l -> Eff (Log l :> r) a -> Eff r a
+ Control.Eff.Log: runLog :: Lifted m r => Logger m l -> Eff (Log l : r) a -> Eff r a
- Control.Eff.Log: runLogPure :: Typeable l => Eff (Log l :> r) a -> Eff r (a, [l])
+ Control.Eff.Log: runLogPure :: Eff (Log l : r) a -> Eff r (a, [l])
- Control.Eff.Log: type Logger m l = forall v. Log l v -> m ()
+ Control.Eff.Log: type Logger m l = l -> m ()

Files

Changelog.md view
@@ -1,5 +1,17 @@ # Changelog +## Version 1.0++	* Complete revamp of the logging effects.++	* Add LogM effect.++	* Add MonadBaseControl instances.++	* Remove fast-logger dependency in favor of a custom typeclass.+++ ## Version 0.4   * add a proxy to most `runLog` functions to not have to supply the full
LICENSE view
@@ -1,6 +1,7 @@ The MIT License (MIT)  Copyright (c) 2013, 2014 Tobias Florek (me@ibotty.net)+Copyright (c) 2018 Lana Black (lanablack@amok.cc)  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
− examples/IOLogger.hs
@@ -1,17 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module Main (main) where--import Control.Eff-import Control.Eff.Lift-import Control.Eff.Log-import System.Log.FastLogger--data Proxy a = Proxy--main :: IO ()-main = do-    loggerSet <- newStderrLoggerSet defaultBufSize-    pushLogStr loggerSet "logging from outer space^WIO\n"-    runLift $ runLogWithLoggerSet loggerSet (Proxy :: Proxy String) $-        logE ("logging from inner Eff" :: String)-    flushLogStr loggerSet
log-effect.cabal view
@@ -2,35 +2,35 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                log-effect-version:             0.4.0.1+version:             1.0.0 synopsis:            An extensible log effect using extensible-effects-description:         Any help (especially documentation) is very welcome,-homepage:            https://github.com/ibotty/log-effect+description:         Introduce two logging effects to your extensible effects arsenal+homepage:            https://github.com/greydot/log-effect license:             MIT license-file:        LICENSE-author:              Tobias Florek-maintainer:          tob@butter.sh+author:              Tobias Florek, Lana Black+maintainer:          Lana Black <lanablack@amok.cc> -- copyright:            category:            Control, Effect, Logging build-type:          Simple extra-source-files:    Changelog.md-                     , examples/IOLogger.hs cabal-version:       >=1.10+Tested-With:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1  library   exposed-modules:     Control.Eff.Log-                     , Control.Eff.Log.Simple   -- other-modules:          -- other-extensions:    -  build-depends:       base >=4.6 && <4.8-                     , bytestring >=0.10.2 && <0.11-                     , extensible-effects ==1.4.* || ==1.7.*-                     , fast-logger >=2.1.4 && <2.2-                     , time >=1.4 && <1.5+  build-depends:       base >=4.6 && <5.0+                     , bytestring >= 0.10+                     , extensible-effects >= 2.5.1.0+                     , monad-control >= 1.0+                     , text >= 1.2+                     , transformers-base >= 0.4   hs-source-dirs:      src   default-language:    Haskell2010  source-repository head   type: git-  location: https://github.com/ibotty/log-effect+  location: https://github.com/greydot/log-effect 
src/Control/Eff/Log.hs view
@@ -1,128 +1,139 @@-{-# LANGUAGE DeriveDataTypeable    #-}-{-# LANGUAGE DeriveFunctor         #-}-{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE RankNTypes            #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE TypeOperators         #-}-module Control.Eff.Log-  ( Log(Log, logLine)-  , Logger-  , logE-  , filterLog-  , filterLog'-  , runLogPure-  , runLogStdout-  , runLogStderr-  , runLogFile-  , runLogWithLoggerSet-  , runLog-  ) where+module Control.Eff.Log ( Log+                       , LogM+                       , Logger+                       , stdoutLogger+                       , stderrLogger+                       , LogMessage(..)+                       , logE+                       , logM+                       , filterLog+                       , filterLog'+                       , runLogPure+                       , runLog+                       , runLogM+                       ) where -import Control.Applicative   ((<$>), (<*))-import Control.Eff           ((:>), Eff, Member, SetMember, VE (..), admin,-                              handleRelay, inj, interpose, send)-import Control.Eff.Lift      (Lift, lift)-import Data.Monoid           ((<>))-import Data.Typeable         (Typeable, Typeable1)-import System.Log.FastLogger (LogStr, LoggerSet, ToLogStr, defaultBufSize,-                              flushLogStr, fromLogStr, newFileLoggerSet,-                              newStderrLoggerSet, newStdoutLoggerSet,-                              pushLogStr, toLogStr)+import Control.Applicative   ((<$>), (<*), (<$))+import Control.Eff+import Control.Eff.Lift      (Lifted, lift)+import Control.Monad         (when)+import Control.Monad.Base    (MonadBase(..))+import Control.Monad.Trans.Control (MonadBaseControl(..))+import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as Char8+import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8)+import Data.Typeable         (Typeable)+import System.IO (stderr, stdout) -import qualified Data.ByteString.Char8 as B8+-- | Simple log effect, useful in pure code+data Log l v where+  Log :: l -> Log l () -data Log a v = Log-  { logLine :: a-  , logNext :: v-  } deriving (Typeable, Functor)+instance ( MonadBase m m+         , Lifted m r+         , MonadBaseControl m (Eff r)+         ) => MonadBaseControl m (Eff (Log l ': r)) where+    type StM (Eff (Log l ': r)) a = StM (Eff r) (a, [l])+    liftBaseWith f = raise $ liftBaseWith $ \runInBase ->+                       f (runInBase . runLogPure)+    restoreM x = do (a, ls :: [l]) <- raise (restoreM x)+                    mapM_ logE ls+                    return a --- | a monadic action that does the real logging-type Logger m l = forall v. Log l v -> m ()+logLine :: Log a v -> a+logLine (Log l) = l +-- | Monadic action that does the real logging+type Logger m l = l -> m ()++-- | Logger that outputs messages to stdout+stdoutLogger :: (LogMessage l, MonadBase IO m) => Logger m l+stdoutLogger = liftBase . Char8.hPutStrLn stdout . toMsg++-- | Logger that outputs messages to stderr+stderrLogger :: (LogMessage l, MonadBase IO m) => Logger m l+stderrLogger = liftBase . Char8.hPutStrLn stderr . toMsg+ -- | Log something.-logE :: (Typeable l, Member (Log l) r)-  => l -> Eff r ()-logE line = send $ \next -> inj (Log line (next ()))+logE :: Member (Log l) r => l -> Eff r ()+logE = send . Log  -- | Collect log messages in a list.-runLogPure :: (Typeable l)-  => Eff (Log l :> r) a-  -> Eff r (a, [l])-runLogPure = go . admin-  where go (Val v) = return (v, [])-        go (E req) = handleRelay req go performLog-        performLog l = fmap (prefixLogWith l) (go (logNext l))-        prefixLogWith log' (v, l) = (v, logLine log' : l)+runLogPure :: Eff (Log l ': r) a -> Eff r (a, [l])+runLogPure = handle_relay (\x -> return (x, []))+                          (\(Log l) k -> k () >>= \(x, ls) -> return (x, l:ls))  -- | Run the 'Logger' action in the base monad for every log line.-runLog :: (Typeable l, Typeable1 m, SetMember Lift (Lift m) r)-  => Logger m l -> Eff (Log l :> r) a -> Eff r a-runLog logger = go . admin-  where go (Val v) = return v-        go (E req) = handleRelay req go performLog-        performLog l = lift (logger l) >> go (logNext l)+runLog :: Lifted m r => Logger m l -> Eff (Log l ': r) a -> Eff r a+runLog logger = handle_relay return+                             (\(Log l) k -> lift (logger l) >> k ())  -- | Filter Log entries with a predicate. -- -- Note that, most of the time an explicit type signature for the predicate -- will be required.-filterLog :: (Typeable l, Member (Log l) r)-  => (l -> Bool) -> Eff r a -> Eff r a-filterLog f = go . admin-  where go (Val v) = return v-        go (E req) = interpose req go filter'-          where filter' (Log l v) = if f l then send (<$> req) >>= go-                                           else go v+filterLog :: forall l r a. Member (Log l) r+          => (l -> Bool) -> Eff r a -> Eff r a+filterLog f = interpose return h+  where+    h :: Log l v -> (v -> Eff r b) -> Eff r b+    h (Log l) k = when (f l) (logE l) >> k () + -- | Filter Log entries with a predicate and a proxy. -- -- This is the same as 'filterLog' but with a proxy l for type inference.-filterLog' :: (Typeable l, Member (Log l) r)-  => (l -> Bool) -> proxy l -> Eff r a -> Eff r a+filterLog' :: Member (Log l) r+           => (l -> Bool) -> proxy l -> Eff r a -> Eff r a filterLog' predicate _ = filterLog predicate --- | Log to stdout.-runLogStdout :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r)-  => proxy l -> Eff (Log l :> r) a -> Eff r a-runLogStdout proxy eff = do-    s <- lift $ newStdoutLoggerSet defaultBufSize-    runLogWithLoggerSet s proxy eff <* lift (flushLogStr s)+-- | A more advanced version of 'Log'. Adds an ability to log from multiple threads.+data LogM m l v where+  AskLogger :: LogM m l (Logger m l) --- | Log to stderr.-runLogStderr :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r)-  => proxy l -> Eff (Log l :> r) a -> Eff r a-runLogStderr proxy eff = do-    s <- lift $ newStderrLoggerSet defaultBufSize-    runLogWithLoggerSet s proxy eff <* lift (flushLogStr s)+askLogger :: Member (LogM m l) r => Eff r (Logger m l)+askLogger = send AskLogger --- | Log to file.-runLogFile :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r)-  => FilePath -> proxy l -> Eff (Log l :> r) a -> Eff r a-runLogFile f proxy eff = do-    s <- lift $ newFileLoggerSet defaultBufSize f-    runLogWithLoggerSet s proxy eff <* lift (flushLogStr s)+-- | Log something using `LogM` effect+logM :: (Member (LogM m l) r, Lifted m r) => l -> Eff r ()+logM l = do logger <- askLogger+            lift (logger l) --- | Log to a file using a 'LoggerSet'.------ Note, that you will still have to call 'flushLogStr' on the 'LoggerSet'--- at one point.------ With that function you can combine a logger in a surrounding IO action--- with a logger in the 'Eff' effect.------ >data Proxy a = Proxy--- >--- > main :: IO ()--- > main = do--- >     loggerSet <- newStderrLoggerSet defaultBufSize--- >     pushLogStr loggerSet "logging from outer space^WIO\n"--- >     runLift $ runLogWithLoggerSet loggerSet (Proxy :: Proxy String) $--- >         logE ("logging from within Eff" :: String)--- >     flushLogStr loggerSet-runLogWithLoggerSet :: (Typeable l, ToLogStr l, SetMember Lift (Lift IO) r)-  => LoggerSet -> proxy l -> Eff (Log l :> r) a -> Eff r a-runLogWithLoggerSet s _ = runLog (loggerSetLogger s)+-- | Run the 'Logger' action in the base monad for every log line.+runLogM :: Lifted m r => Logger m l -> Eff (LogM m l ': r) a -> Eff r a+runLogM logger = handle_relay return+                              (\AskLogger -> ($ logger)) -loggerSetLogger :: ToLogStr l => LoggerSet -> Logger IO l-loggerSetLogger loggerSet = pushLogStr loggerSet . (<> "\n") . toLogStr . logLine+instance ( MonadBase m m+         , Lifted m r+         , MonadBaseControl m (Eff r)+         ) => MonadBaseControl m (Eff (LogM m l ': r)) where+    type StM (Eff (LogM m l ': r)) a = StM (Eff r) a+    liftBaseWith f = do l <- askLogger+                        raise $ liftBaseWith $ \runInBase ->+                          f (runInBase . runLogM l)+    restoreM = raise . restoreM++-- | Handy typeclass to convert log messages for output+class LogMessage l where+  toMsg :: l -> ByteString+  {-# MINIMAL toMsg #-}++instance LogMessage ByteString where+  toMsg = id++instance LogMessage [Char] where+  toMsg = Char8.pack++instance LogMessage Text where+  toMsg = encodeUtf8
− src/Control/Eff/Log/Simple.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE DeriveDataTypeable    #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE RankNTypes            #-}-{-# LANGUAGE TypeOperators         #-}-module Control.Eff.Log.Simple-  ( SimpleLog-  , Severity(..)-  , logTo-  , debug-  , info-  , notice-  , warning-  , error-  , critical-  , alert-  , panic-  ) where--import Control.Eff           (Eff, Member)-import Control.Eff.Log-import Data.Monoid           ((<>))-import Data.Typeable         (Typeable)-import Prelude               hiding (error)-import System.Log.FastLogger (ToLogStr, toLogStr)--data Severity =-    DEBUG | INFO | NOTICE | WARNING | ERROR | CRITICAL | ALERT | PANIC-  deriving (Bounded, Enum, Eq, Ord, Read, Show, Typeable)--type SimpleLog a = Log (Severity, a)--instance ToLogStr Severity where-    toLogStr DEBUG    = "DEBUG"-    toLogStr INFO     = "INFO"-    toLogStr NOTICE   = "NOTICE"-    toLogStr WARNING  = "WARNING"-    toLogStr ERROR    = "ERROR"-    toLogStr CRITICAL = "CRITICAL"-    toLogStr ALERT    = "ALERT"-    toLogStr PANIC    = "PANIC"--instance ToLogStr a => ToLogStr (Severity, a) where-    toLogStr (sev, line) = "[" <> toLogStr sev <> "] " <> toLogStr line <> "\n"--logTo :: (Typeable l, Member (Log (Severity, l)) r)-  => Severity -> l -> Eff r ()-logTo sev line = logE (sev, line)--debug :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-debug = logTo DEBUG--info :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-info = logTo INFO--notice :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-notice = logTo NOTICE--warning :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-warning = logTo WARNING--error :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-error = logTo ERROR--critical :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-critical = logTo CRITICAL--alert :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-alert = logTo ALERT--panic :: (Typeable l, Member (Log (Severity, l)) r) => l -> Eff r ()-panic = logTo PANIC