on master help sign in
Flesh out a bit more
commit134d78022aa920ab0cb43e36cdf2e8cc4585a850 authorOzgun Ataman <ozgun.ataman@soostone.com> dateSat 31 Jan 2015, 17:16 (12 years ago) parent60e4ef6
3 files changed+70−27
katip.cabal+9−8 src/Katip/Core.hs+33−14 src/Katip/Backends/Handle.hs → src/Katip/Scribes/Handle.hs+28−5
katip.cabal+9−8
@@ -17,17 +17,18 @@ cabal-version: >=1.10
1717library
1818 exposed-modules:
1919 Katip.Core
20− Katip.Backends.Handle
20+ Katip.Scribes.Handle
2121
2222 -- other-modules:
23− other-extensions:
24− DeriveGeneric,
25− FlexibleContexts,
26− GeneralizedNewtypeDeriving,
27− MultiParamTypeClasses,
28− RankNTypes,
29− RecordWildCards,
23+ default-extensions:
24+ DeriveGeneric
25+ FlexibleContexts
26+ GeneralizedNewtypeDeriving
27+ MultiParamTypeClasses
28+ RankNTypes
29+ RecordWildCards
3030 TemplateHaskell
31+ OverloadedStrings
3132
3233 build-depends:
3334 base >=4.6 && <4.7
src/Katip/Core.hs+33−14
@@ -19,6 +19,7 @@ import Data.Aeson (ToJSON)
1919import qualified Data.Aeson as A
2020import qualified Data.Map.Strict as M
2121import Data.Monoid
22+import Data.String
2223import Data.Text (Text)
2324import Data.Time
2425import GHC.Generics hiding (to)
@@ -27,10 +28,10 @@ import Network.HostName
2728
2829
2930newtype AppName = AppName { getAppName :: Text }
30− deriving (Eq,Show,Read,Ord,Generic,ToJSON)
31+ deriving (Eq,Show,Read,Ord,Generic,ToJSON,IsString)
3132
3233newtype Environment = Environment { getEnvironment :: Text }
33− deriving (Eq,Show,Read,Ord,Generic,ToJSON)
34+ deriving (Eq,Show,Read,Ord,Generic,ToJSON,IsString)
3435
3536
3637-------------------------------------------------------------------------------
@@ -63,7 +64,9 @@ renderSeverity s = case s of
6364instance ToJSON Severity where
6465 toJSON s = A.String (renderSeverity s)
6566
67+
6668-------------------------------------------------------------------------------
69+-- | This has everything each log message will contain.
6770data Item a = Item {
6871 itemApp :: AppName
6972 , itemEnv :: Environment
@@ -91,7 +94,9 @@ instance ToJSON a => ToJSON (Item a) where
9194
9295
9396-------------------------------------------------------------------------------
94−data LogHandler = LogHandler {
97+-- | Scribes are handlers of incoming items. Each registered scribe
98+-- knows how to push a log item somewhere.
99+data Scribe = Scribe {
95100 lhPush :: forall a. ToJSON a => Item a -> IO ()
96101 }
97102
@@ -102,7 +107,7 @@ data LogEnv = LogEnv {
102107 , _logEnvApp :: AppName
103108 , _logEnvEnv :: Environment
104109 , _logEnvTimer :: IO UTCTime
105− , _logEnvHandlers :: M.Map Text LogHandler
110+ , _logEnvHandlers :: M.Map Text Scribe
106111 }
107112makeLenses ''LogEnv
108113
@@ -121,7 +126,7 @@ initLogEnv an env = LogEnv
121126registerHandler
122127 :: Text
123128 -- ^ Name the handler
124− -> LogHandler
129+ -> Scribe
125130 -> LogEnv
126131 -> LogEnv
127132registerHandler nm h = logEnvHandlers . at nm .~ Just h
@@ -136,24 +141,38 @@ unregisterHandler
136141unregisterHandler nm = logEnvHandlers . at nm .~ Nothing
137142
138143
144+
145+class Katip m where
146+ getLogEnv :: m LogEnv
147+
148+
149+
139150-------------------------------------------------------------------------------
140−logM
141− :: (Applicative m, MonadIO m, ToJSON a, MonadReader LogEnv m)
151+-- | The generic *full* logging function.
152+logF
153+ :: (Applicative m, MonadIO m, ToJSON a, Katip m)
142154 => Severity
143155 -> a
156+ -- ^ Contextual payload for the log
144157 -> Text
158+ -- ^ The log message
145159 -> m ()
146−logM sev a msg = do
160+logF sev a msg = do
161+ LogEnv{..} <- getLogEnv
147162 item <- Item
148− <$> view logEnvApp
149− <*> view logEnvEnv
163+ <$> pure _logEnvApp
164+ <*> pure _logEnvEnv
150165 <*> pure sev
151166 <*> liftIO myThreadId
152− <*> view logEnvHost
167+ <*> pure _logEnvHost
153168 <*> pure a
154169 <*> pure msg
155− <*> (view logEnvTimer >>= liftIO)
156− hs <- view $ logEnvHandlers . to M.elems
157− liftIO $ forM_ hs $ \ (LogHandler h) -> h item
170+ <*> liftIO _logEnvTimer
171+ liftIO $ forM_ (M.elems _logEnvHandlers) $ \ (Scribe h) -> h item
172+
158173
174+-------------------------------------------------------------------------------
175+-- | Log a message without any context.
176+logM :: (Applicative m, MonadIO m, Katip m) => Severity -> Text -> m ()
177+logM sev msg = logF sev () msg
159178
src/Katip/Backends/Handle.hs → src/Katip/Scribes/Handle.hsrenamed+28−5
@@ -1,5 +1,8 @@
11{-# LANGUAGE RecordWildCards #-}
2−module Katip.Backends.Handle where
2+
3+module Katip.Scribes.Handle
4+ ( mkHandleScribe
5+ ) where
36
47-------------------------------------------------------------------------------
58import Blaze.ByteString.Builder
@@ -13,6 +16,7 @@ import Data.Monoid
1316import Data.Text (Text)
1417import Data.Time
1518import System.IO
19+import System.IO.Unsafe (unsafePerformIO)
1620import System.Locale
1721-------------------------------------------------------------------------------
1822import Katip.Core
@@ -40,10 +44,10 @@ renderPrim NullPrim = fromByteString "null"
4044
4145
4246-------------------------------------------------------------------------------
43−mkHandleHandler :: Handle -> [Text] -> IO LogHandler
44−mkHandleHandler h keys = do
47+mkHandleScribe :: Handle -> [Text] -> Severity -> IO Scribe
48+mkHandleScribe h keys sev = do
4549 hSetBuffering h LineBuffering
46− return $ LogHandler $ \ Item{..} -> do
50+ return $ Scribe $ \ Item{..} -> do
4751 let nowStr = fromString $ formatTime defaultTimeLocale "%Y-%m-%d %H:%M:%S" itemTime
4852 ks = map brackets $ getKeys itemPayload keys
4953 msg = brackets nowStr <>
@@ -52,5 +56,24 @@ mkHandleHandler h keys = do
5256 brackets (fromString (show itemThread)) <>
5357 mconcat ks <>
5458 fromText " " <> fromText itemMessage
55− B.putStrLn $ toByteString msg
59+ if itemSeverity >= sev
60+ then B.putStrLn $ toByteString msg
61+ else return ()
62+
63+
64+
65+-------------------------------------------------------------------------------
66+-- | An implicit environment to enable logging directly ouf of the IO monad.
67+_ioLogEnv :: LogEnv
68+_ioLogEnv = unsafePerformIO $ do
69+ le <- initLogEnv "io" "io"
70+ lh <- mkHandleScribe stdout [] Debug
71+ return $ registerHandler "stdout" lh le
72+{-# NOINLINE _ioLogEnv #-}
73+
74+
75+-------------------------------------------------------------------------------
76+-- | A default IO instance to make prototype development easy. User
77+-- your own 'Monad' for production.
78+instance Katip IO where getLogEnv = return _ioLogEnv
5679