packages feed

monad-log 0.1.0.0 → 0.1.1.0

raw patch · 8 files changed

+257/−32 lines, 8 filesdep ~aesondep ~basedep ~exceptions

Dependency ranges changed: aeson, base, exceptions, transformers

Files

+ CHANGELOG.md view
@@ -0,0 +1,4 @@+0.1.1.0+-------++Update haddock, fix build on GHC-7.6/7.8.
Control/Monad/Log.hs view
@@ -5,7 +5,19 @@ {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE CPP #-} +-- | This module provides a mtl style 'MonadLog' class and a concrete monad transformer 'LogT'.+--+-- If you are an application author, you can use 'LogT' transformer,+-- a specialized reader monad to inject 'Logger'.+--+-- If you are a library author, you should:+--+--     * make your monad stack an instance of 'MonadLog', usually you can do this by embedding a 'Logger' into your monad's reader part.+--+--     * provide a default formatter, and API to run with customized formatter.+-- module Control.Monad.Log (     -- * parametrized 'Logger' type       Level(..)@@ -21,24 +33,17 @@     , makeDefaultJSONLogger     , defaultFormatter     , defaultJSONFormatter-    -- * re-export from fast-logger-    , module X-    , LogStr-    , toLogStr-    , LogType(..)     -- * 'MonadLog' class     , MonadLog(..)-    , localEnv     , withFilterLevel     , withEnv+    , localEnv     -- * LogT, a concrete monad transformaer     , LogT(..)     , runLogTSafe     , runLogTSafeBase     , runLogT'-    -- * re-export from text-show-    , module TextShow-    -- logging functions+    -- * logging functions     , debug     , info     , warning@@ -49,8 +54,25 @@     , warning'     , error'     , critical'+    -- * re-export from text-show and fast-logger+    , LogStr+    , toLogStr+    , LogType(..)+    , FileLogSpec(..)+    , TimeFormat+    , FormattedTime+    , simpleTimeFormat+    , simpleTimeFormat'+    , module X     ) where +#if !(MIN_VERSION_base(4,8,0))+import Control.Applicative+import Data.Monoid (Monoid)+#endif+#if MIN_VERSION_base(4,9,0)+import qualified Control.Monad.Fail as Fail+#endif import Control.Monad (when, liftM, ap) import Control.Monad.Catch (MonadMask, finally) import Control.Monad.Trans.Control (MonadBaseControl)@@ -73,15 +95,13 @@ import Control.Monad.Trans.Writer.Strict as Strict  import System.Log.FastLogger-import System.Log.FastLogger.Date as X-import System.Log.FastLogger.File as X import Prelude hiding (log, error)  import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.ByteString.Builder as BB-import TextShow (TextShow, showt, showb)+import TextShow as X  import qualified Data.Aeson as JSON import Data.Aeson (ToJSON, fromEncoding, (.=))@@ -144,11 +164,11 @@  -- | make a 'Logger' based on 'FastLogger'. makeLogger :: (MonadIO m)-    => (Level -> FormattedTime -> env -> Text -> LogStr)-    -> TimeFormat+    => (Level -> FormattedTime -> env -> Text -> LogStr)  -- ^ formatter function+    -> TimeFormat                                         -- ^ check "System.Log.FastLogger.Date"     -> LogType-    -> Level-    -> env+    -> Level                                              -- ^ filter level+    -> env                                                -- ^ init environment     -> m (Logger env) makeLogger fmt tfmt typ fltr env = liftIO $ do     tc <- newTimeCache tfmt@@ -182,7 +202,7 @@  -- | a default JSON formatter with following format: ----- @{"level": LEVEL, "time": TIME, "env": ENV, msg: LOG MESSAGE }\\n@+-- @{"level": "LEVEL", "time": "TIME", "env": "ENV", "msg": "LOG MESSAGE" }\\n@ defaultJSONFormatter :: (ToJSON env) => Level -> FormattedTime -> env -> Text -> LogStr defaultJSONFormatter lvl time env msg = toLogStr . BB.toLazyByteString $     ( fromEncoding . JSON.pairs $@@ -196,8 +216,7 @@  -- | This is the main class for using logging function in this package. ----- provide an instance for 'MonadLog' to log within your monad stack--- a concrete transformmer 'LogT' is also provided.+-- provide an instance for 'MonadLog' to log within your monad stack. class (MonadIO m) => MonadLog env m | m -> env where     askLogger :: m (Logger env)     localLogger :: (Logger env -> Logger env) -> m a -> m a@@ -266,7 +285,7 @@  -- | A simple 'MonadLog' instance. ----- a reader monad which embed a 'Logger'.+-- a special reader monad which embed a 'Logger'. newtype LogT env m a = LogT { runLogT :: Logger env -> m a }  instance Monad m => Functor (LogT env m) where@@ -287,6 +306,14 @@         let LogT f' = f a         f' lgr     {-# INLINE (>>=) #-}+    fail msg = lift (fail msg)+    {-# INLINE fail #-}++#if MIN_VERSION_base(4,9,0)+instance Fail.MonadFail m => Fail.MonadFail (LogT env m) where+    fail msg = lift (Fail.fail msg)+    {-# INLINE fail #-}+#endif  instance (MonadFix m) => MonadFix (LogT r m) where     mfix f = LogT $ \ r -> mfix $ \ a -> runLogT (f a) r
Control/Monad/Log/Label.hs view
@@ -1,12 +1,15 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}  module Control.Monad.Log.Label where  import Control.Monad.Log+#if !(MIN_VERSION_base(4,8,0))+import Control.Applicative+#endif import Data.Aeson import Data.Text (Text)-import Data.Text.Internal.Builder (fromText)  -- | Simple 'Label' environment for labelled logging. --@@ -21,7 +24,9 @@  instance ToJSON Label where     toJSON (Label t) = toJSON t+#if MIN_VERSION_aeson(0,10,0)     toEncoding (Label t) = toEncoding t+#endif  instance FromJSON Label where     parseJSON t = Label <$> parseJSON t
Control/Monad/Log/LogLoc.hs view
@@ -2,13 +2,16 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}  module Control.Monad.Log.LogLoc where  import Control.Monad.Log+#if !(MIN_VERSION_base(4,8,0))+import Control.Applicative+#endif import Data.Text (Text) import qualified Data.Text as T-import Data.Text.Internal.Builder (fromText) import Data.Aeson import Data.Monoid ((<>)) @@ -35,8 +38,10 @@ instance ToJSON LogLoc where     toJSON (LogLoc p m f l) =         object ["filename" .= f, "module" .= m, "package" .= p, "line" .= l]+#if MIN_VERSION_aeson(0,10,0)     toEncoding (LogLoc p m f l) =         pairs ("filename" .= f <> "module" .= m <> "package" .= p <> "line" .= l)+#endif  instance FromJSON LogLoc where     parseJSON (Object v) = LogLoc <$>@@ -56,6 +61,11 @@     |]  -- | Get current 'LogLoc'.+--+--  depending on how accurately you want to record source location,+--  you may want to use 'Logger' 's environment, or provide your own on every log.+--+--  example usage: @info' $myLogLoc "log message"@ myLogLoc :: Q Exp myLogLoc = [| $(TH.location >>= liftLogLoc) |] 
Control/Monad/Log/LogThreadId.hs view
@@ -1,15 +1,18 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}  module Control.Monad.Log.LogThreadId where  import Control.Monad.Log+#if !(MIN_VERSION_base(4,8,0))+import Control.Applicative+#endif import Control.Monad.IO.Class import Control.Concurrent import Data.Aeson import Data.Text (Text) import qualified Data.Text as T-import Data.Text.Internal.Builder (fromText)  -- | a formatted 'LogThreadId'. --@@ -24,7 +27,9 @@  instance ToJSON LogThreadId where     toJSON (LogThreadId t) = toJSON t+#if MIN_VERSION_aeson(0,10,0)     toEncoding (LogThreadId t) = toEncoding t+#endif  instance FromJSON LogThreadId where     parseJSON t = LogThreadId <$> parseJSON t
Control/Monad/Log/NameSpace.hs view
@@ -1,9 +1,13 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}  module Control.Monad.Log.NameSpace where  import Control.Monad.Log+#if !(MIN_VERSION_base(4,8,0))+import Control.Applicative+#endif import Data.Aeson import Data.Text (Text) import qualified Data.Text as T@@ -27,7 +31,9 @@  instance ToJSON NameSpace where     toJSON (NameSpace t) = toJSON t+#if MIN_VERSION_aeson(0,10,0)     toEncoding (NameSpace t) = toEncoding t+#endif  instance FromJSON NameSpace where     parseJSON t = NameSpace <$> parseJSON t
+ README.md view
@@ -0,0 +1,151 @@+A fast & simple logging monad+=============================++[![Hackage](https://img.shields.io/hackage/v/monad-log.svg?style=flat-square)](http://hackage.haskell.org/package/monad-log)+[![Travis-CI](https://travis-ci.org/winterland1989/monad-log.svg?style=flat-square)](https://travis-ci.org/winterland1989/monad-log)++This package provide a mtl style `MonadLog` class and a concrete monad transformer `LogT`, the main difference between this package and monad-logger are:+++ Base monad has to be an instance of `MonadIO`.+++ Parametrized logging environment for extensibility.+++ Basic logging environment type(`Label`,`Loc`,`NameSpace`,`ThreadId`) are included, and you can easily make your own.+++ JSON logging built-in.+++ default to fast-logger backend, with good stdout and file support.++If you are an application author, you can use `LogT` transformer, a specialized reader monad to inject `Logger env`.++If you are a library author, you should:+++ make your monad stack an instance of 'MonadLog', usually you can do this by embedding `Logger env` into your monad's reader part.+++ provide a default formatter, and API to run with customized formatter.++Example+-------+++ A simple labelled logger:++```haskell+{-# LANGUAGE OverloadedStrings #-}++module Main where++import Control.Monad.Log+import Control.Monad.Log.Label++-- Following log will be output to stdout:+-- [INFO] [25-Apr-2016 12:51:56] [main] This is simple log 1+-- [INFO] [25-Apr-2016 12:51:56] [foo] This is simple log 2++main :: IO ()+main = do+    logger <- makeDefaultLogger+        simpleTimeFormat'+        (LogStdout 4096)+        levelDebug+        (Label "main")++    runLogTSafe logger $ do+        info "This is simple log 1"++        withLabel (Label "foo") $ do+            info "This is simple log 2"++```+++ Logging with ThreadId:++```haskell+{-# LANGUAGE OverloadedStrings #-}++module Main where++import Control.Monad.Log+import Control.Monad.IO.Class+import Control.Monad+import Control.Concurrent+import Control.Monad.Log.LogThreadId++-- Following log will be output to stdout:+-- [INFO] [25-Apr-2016 15:06:10] [ThreadId 671] This is simple log 1+-- [INFO] [25-Apr-2016 15:06:10] [ThreadId 674] This is simple log 2+-- [INFO] [25-Apr-2016 15:06:10] [ThreadId 675] This is simple log 2+-- [INFO] [25-Apr-2016 15:06:10] [ThreadId 676] This is simple log 2+-- [INFO] [25-Apr-2016 15:06:10] [ThreadId 677] This is simple log 2+-- [INFO] [25-Apr-2016 15:06:10] [ThreadId 678] This is simple log 2+-- [INFO] [25-Apr-2016 15:06:10] [ThreadId 679] This is simple log 2+...++main :: IO ()+main = do+    tid <- myLogThreadId+    logger <- makeDefaultLogger+        simpleTimeFormat'+        (LogStdout 4096)+        levelDebug+        tid++    runLogTSafe logger $ do+        info "This is simple log 1"++    replicateM_ 100 $+        forkIO . runLogT' logger . withMyLogThreadId $ do+            info "This is simple log 2"+```+++ Customized logging environment:++```haskell+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}++module Main where++import Control.Monad.Log+import Control.Monad.Log.LogLoc+import Control.Monad.Log.NameSpace+import Data.Aeson.TH+import Data.Text (Text)++-- Following JSON log will be output to stdout:+-- {"level":"INFO","time":"25-Apr-2016 13:54:32"+-- ,"env":{"loc":{"filename":"Test.hs","module":"Test","package":"monad_GM54RwU2jZ84vGJIhnMYMH","line":33},"ns":["root"]}+-- ,"msg":"This is simple log 1"}+-- {"level":"INFO","time":"25-Apr-2016 13:54:32"+-- ,"env":{"loc":{"filename":"Test.hs","module":"Test","package":"monad_GM54RwU2jZ84vGJIhnMYMH","line":33},"ns":["foo","root"]}+-- ,"msg":"This is simple log 2"}++-- | Define your logging environment type.+-- To use 'defaultFomatter', provide a 'TextShow' instance+-- To use 'defaultJSONFomatter', provide a 'ToJSON' instance++data MyEnv = MyEnv {+        loc :: LogLoc  -- This is shared by every log within one 'MonadLog'.+    ,   ns  :: NameSpace+    } deriving (Show, Eq)++$(deriveJSON defaultOptions ''MyEnv)++subMyNS :: (MonadLog MyEnv m) => Text -> m a -> m a+subMyNS sub = localEnv $ \env -> env { ns = pushNameSpace sub (ns env) }++main :: IO ()+main = do+    logger <- makeDefaultJSONLogger+        simpleTimeFormat'+        (LogStdout 4096)+        levelDebug+        (MyEnv $myLogLoc (NameSpace ["root"]))++    runLogTSafe logger $ do+        info "This is simple log 1"++        subMyNS "foo" $ do+            info "This is simple log 2"++```
monad-log.cabal view
@@ -1,10 +1,27 @@--- Initial monad-log.cabal generated by cabal init.  For further --- documentation, see http://haskell.org/cabal/users-guide/- name:                monad-log-version:             0.1.0.0+version:             0.1.1.0 synopsis:            A simple and fast logging monad-description:         A simple and fast logging monad+description:         +    This package provide a mtl style `MonadLog` class and a concrete monad transformer `LogT`, the main difference between this package and monad-logger are:+    .+    * Base monad has to be an instance of `MonadIO`.+    .+    * Parametrized logging environment for extensibility.+    .+    * Basic logging environment type(`Label`,`Loc`,`NameSpace`,`ThreadId`) are included, and you can easily make your own.+    .+    * JSON logging built-in.+    .+    * default to fast-logger backend, with good stdout and file support.+    .+    If you are an application author, you can use `LogT` transformer, it's just a specialized reader monad to inject `Logger env`.+    .+    If you are a library author, you should do following two things:+    .+    * make your monad stack an instance of 'MonadLog', usually you can do this by embedding `Logger env` into your monad's reader part.+    .+    * provide a default formatter, and API to run with customized formatter.+ license:             MIT license-file:        LICENSE author:              winterland1989@@ -12,7 +29,7 @@ -- copyright:            category:            Development build-type:          Simple--- extra-source-files:  +extra-source-files:  CHANGELOG.md README.md cabal-version:       >=1.10  library@@ -24,7 +41,7 @@                     ,   Control.Monad.Log.LogThreadId   -- other-modules:          -- other-extensions:    -  build-depends:        base >=4.8 && <4.9+  build-depends:        base >=4.6 && <5                     ,   fast-logger >=2.4.5 && <2.5                     ,   monad-control >=0.3 && <1.1                     ,   lifted-base @@ -32,8 +49,8 @@                     ,   bytestring                     ,   text                     ,   text-show-                    ,   transformers >=0.2 && <0.5-                    ,   aeson        >= 0.10 && <0.12+                    ,   transformers >=0.2+                    ,   aeson        >= 0.4 && <0.12                     ,   template-haskell     -- hs-source-dirs: