@@ -31,7 +31,6 @@ import qualified Control.Concurrent.STM.TBQueue as BQ
31import Control.Exception.Safe
31import Control.Exception.Safe
32import Control.Monad (unless, void, when)
32import Control.Monad (unless, void, when)
33import Control.Monad.Base
33import Control.Monad.Base
34−import Data.Text.Encoding as T
35#if MIN_VERSION_base(4, 9, 0)
34#if MIN_VERSION_base(4, 9, 0)
36import qualified Control.Monad.Fail as MF
35import qualified Control.Monad.Fail as MF
@@ -45,7 +44,8 @@ import Control.Monad.Trans.Either
45import Control.Monad.Trans.Except
44import Control.Monad.Trans.Except
46import Control.Monad.Trans.Maybe
45import Control.Monad.Trans.Maybe
47import Control.Monad.Trans.Reader
46import Control.Monad.Trans.Reader
48−import Control.Monad.Trans.Resource (ResourceT, transResourceT)
47+import Control.Monad.Trans.Resource (MonadResource, ResourceT,
49import Control.Monad.Trans.RWS.Lazy (RWST, mapRWST)
49import Control.Monad.Trans.RWS.Lazy (RWST, mapRWST)
50import qualified Control.Monad.Trans.RWS.Strict as Strict (RWST, mapRWST)
50import qualified Control.Monad.Trans.RWS.Strict as Strict (RWST, mapRWST)
51import Control.Monad.Trans.State.Lazy (StateT, mapStateT)
51import Control.Monad.Trans.State.Lazy (StateT, mapStateT)
@@ -56,7 +56,6 @@ import qualified Control.Monad.Trans.Writer.Strict as Strict (WriterT,
56import Data.Aeson (FromJSON (..), ToJSON (..),
56import Data.Aeson (FromJSON (..), ToJSON (..),
58import qualified Data.Aeson as A
58import qualified Data.Aeson as A
59−import qualified Data.ByteString.Builder as B
60import Data.Foldable as FT
59import Data.Foldable as FT
61import qualified Data.HashMap.Strict as HM
60import qualified Data.HashMap.Strict as HM
62import Data.List
61import Data.List
@@ -67,6 +66,7 @@ import Data.String
67import Data.String.Conv
66import Data.String.Conv
68import Data.Text (Text)
67import Data.Text (Text)
69import qualified Data.Text as T
68import qualified Data.Text as T
69+import qualified Data.Text.Lazy.Builder as B
70import Data.Time
70import Data.Time
71import GHC.Generics hiding (to)
71import GHC.Generics hiding (to)
72#if MIN_VERSION_base(4, 8, 0)
72#if MIN_VERSION_base(4, 8, 0)
@@ -200,15 +200,13 @@ instance FromJSON Verbosity where
200 _ -> fail $ "Invalid Verbosity " ++ toS s
200 _ -> fail $ "Invalid Verbosity " ++ toS s
205-------------------------------------------------------------------------------
203-------------------------------------------------------------------------------
206-- | Log message with Builder underneath; use '<>' to concat in O(1).
204-- | Log message with Builder underneath; use '<>' to concat in O(1).
207newtype LogStr = LogStr { unLogStr :: B.Builder }
205newtype LogStr = LogStr { unLogStr :: B.Builder }
208− deriving (Generic)
206+ deriving (Generic, Show, Eq)
210instance IsString LogStr where
208instance IsString LogStr where
211− fromString = LogStr . logStrText . T.pack
209+ fromString = LogStr . B.fromString
214instance Semigroup LogStr where
212instance Semigroup LogStr where
@@ -220,20 +218,18 @@ instance Monoid LogStr where
220 mempty = LogStr mempty
218 mempty = LogStr mempty
223−-- instance FromJSON LogStr where
221+instance FromJSON LogStr where
224−-- parseJSON = A.withText "LogStr" parseLogStr
222+ parseJSON = A.withText "LogStr" parseLogStr
226−-- parseLogStr = return . LogStr . B.fromText
224+ parseLogStr = return . LogStr . B.fromText
228-------------------------------------------------------------------------------
226-------------------------------------------------------------------------------
229-- | Pack any string-like thing into a 'LogStr'. This will
227-- | Pack any string-like thing into a 'LogStr'. This will
230-- automatically work on 'String', 'ByteString', 'Text' and any of the
228-- automatically work on 'String', 'ByteString', 'Text' and any of the
231-- lazy variants.
229-- lazy variants.
232logStr :: StringConv a Text => a -> LogStr
230logStr :: StringConv a Text => a -> LogStr
233−logStr t = logStrText . toS
231+logStr t = LogStr (B.fromText $ toS t)
235−logStrText :: Text -> LogStr
236−logStrText = LogStr . B.byteString . T.encodeUtf8
238-------------------------------------------------------------------------------
234-------------------------------------------------------------------------------
239-- | Shorthand for 'logStr'
235-- | Shorthand for 'logStr'
@@ -669,7 +665,7 @@ makeLenses ''LogEnv
671-------------------------------------------------------------------------------
667-------------------------------------------------------------------------------
672−-- | Create a reasonable default InitLogEnv. Uses an 'AutoUdate' which
668+-- | Create a reasonable default InitLogEnv. Uses an 'AutoUpdate' which
673-- updates the timer every 1ms. If you need even more timestamp
669-- updates the timer every 1ms. If you need even more timestamp
674-- precision at the cost of performance, consider setting
670-- precision at the cost of performance, consider setting
675-- '_logEnvTimer' with 'getCurrentTime'.
671-- '_logEnvTimer' with 'getCurrentTime'.
@@ -884,7 +880,8 @@ instance (Katip m) => Katip (ResourceT m) where
884-- opposed to implementing 'Katip' for your monad.
880-- opposed to implementing 'Katip' for your monad.
885newtype KatipT m a = KatipT { unKatipT :: ReaderT LogEnv m a }
881newtype KatipT m a = KatipT { unKatipT :: ReaderT LogEnv m a }
886 deriving ( Functor, Applicative, Monad, MonadIO
882 deriving ( Functor, Applicative, Monad, MonadIO
887− , MonadMask, MonadCatch, MonadThrow, MonadTrans, MonadBase b)
883+ , MonadMask, MonadCatch, MonadThrow, MonadResource, MonadTrans
890instance MonadIO m => Katip (KatipT m) where
887instance MonadIO m => Katip (KatipT m) where
@@ -906,9 +903,14 @@ instance (MonadBaseControl b m) => MonadBaseControl b (KatipT m) where
906 restoreM = defaultRestoreM
903 restoreM = defaultRestoreM
908instance MonadUnliftIO m => MonadUnliftIO (KatipT m) where
905instance MonadUnliftIO m => MonadUnliftIO (KatipT m) where
906+#if MIN_VERSION_unliftio_core(0, 2, 0)
907+ withRunInIO inner = KatipT $ ReaderT $ \le -> withRunInIO $ \run ->
908+ inner (run . runKatipT le)
909 askUnliftIO = KatipT $
910 askUnliftIO = KatipT $
910− withUnliftIO $ \u ->
911+ withUnliftIO $ \u ->
911− pure (UnliftIO (unliftIO u . unKatipT))
912+ pure (UnliftIO (unliftIO u . unKatipT))
913#if MIN_VERSION_base(4, 9, 0)
915#if MIN_VERSION_base(4, 9, 0)
914instance MF.MonadFail m => MF.MonadFail (KatipT m) where
916instance MF.MonadFail m => MF.MonadFail (KatipT m) where
@@ -946,19 +948,29 @@ logItem
947logItem a ns loc sev msg = do
949logItem a ns loc sev msg = do
948 LogEnv{..} <- getLogEnv
950 LogEnv{..} <- getLogEnv
949− liftIO $ do
951+ logKatipItem =<< liftIO
951− <$> pure _logEnvApp
952+ (Item <$> pure _logEnvApp
952− <*> pure _logEnvEnv
953+ <*> pure _logEnvEnv
953− <*> pure sev
954+ <*> pure sev
954− <*> (mkThreadIdText <$> myThreadId)
955+ <*> (mkThreadIdText <$> myThreadId)
955− <*> pure _logEnvHost
956+ <*> pure _logEnvHost
956− <*> pure _logEnvPid
957+ <*> pure _logEnvPid
957− <*> pure a
958+ <*> pure a
958− <*> pure msg
959+ <*> pure msg
959− <*> _logEnvTimer
960+ <*> _logEnvTimer
960− <*> pure (_logEnvApp <> ns)
961+ <*> pure (_logEnvApp <> ns)
961− <*> pure loc
962+ <*> pure loc)
964+-- | Log already constructed 'Item'. This is the lowest level function that other log*
966+-- It can be useful when implementing centralised logging services.
968+ :: (A.Applicative m, LogItem a, Katip m)
971+logKatipItem item = do
972+ LogEnv{..} <- getLogEnv
962 FT.forM_ (M.elems _logEnvScribes) $ \ ScribeHandle {..} -> do
974 FT.forM_ (M.elems _logEnvScribes) $ \ ScribeHandle {..} -> do
963 whenM (scribePermitItem shScribe item) $
975 whenM (scribePermitItem shScribe item) $
964 void $ atomically (tryWriteTBQueue shChan (NewItem item))
976 void $ atomically (tryWriteTBQueue shChan (NewItem item))
@@ -1007,7 +1019,7 @@ logException
1007logException a ns sev action = action `catchAny` \e -> f e >> throwM e
1019logException a ns sev action = action `catchAny` \e -> f e >> throwM e
1009 f e = logF a ns sev (msg e)
1021 f e = logF a ns sev (msg e)
1010− msg e = ls (T.pack "An exception has occured: ") <> showLS e
1022+ msg e = ls (T.pack "An exception has occurred: ") <> showLS e
1013-------------------------------------------------------------------------------
1025-------------------------------------------------------------------------------