@@ -19,6 +19,7 @@ import Data.Aeson (ToJSON)
19import qualified Data.Aeson as A
19import qualified Data.Aeson as A
20import qualified Data.Map.Strict as M
20import qualified Data.Map.Strict as M
21import Data.Monoid
21import Data.Monoid
22import Data.Text (Text)
23import Data.Text (Text)
23import Data.Time
24import Data.Time
24import GHC.Generics hiding (to)
25import GHC.Generics hiding (to)
@@ -27,10 +28,10 @@ import Network.HostName
29newtype AppName = AppName { getAppName :: Text }
30newtype AppName = AppName { getAppName :: Text }
30− deriving (Eq,Show,Read,Ord,Generic,ToJSON)
31+ deriving (Eq,Show,Read,Ord,Generic,ToJSON,IsString)
32newtype Environment = Environment { getEnvironment :: Text }
33newtype Environment = Environment { getEnvironment :: Text }
33− deriving (Eq,Show,Read,Ord,Generic,ToJSON)
34+ deriving (Eq,Show,Read,Ord,Generic,ToJSON,IsString)
36-------------------------------------------------------------------------------
37-------------------------------------------------------------------------------
@@ -63,7 +64,9 @@ renderSeverity s = case s of
63instance ToJSON Severity where
64instance ToJSON Severity where
64 toJSON s = A.String (renderSeverity s)
65 toJSON s = A.String (renderSeverity s)
66-------------------------------------------------------------------------------
68-------------------------------------------------------------------------------
69+-- | This has everything each log message will contain.
67data Item a = Item {
70data Item a = Item {
68 itemApp :: AppName
71 itemApp :: AppName
69 , itemEnv :: Environment
72 , itemEnv :: Environment
@@ -91,7 +94,9 @@ instance ToJSON a => ToJSON (Item a) where
93-------------------------------------------------------------------------------
96-------------------------------------------------------------------------------
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 {
95 lhPush :: forall a. ToJSON a => Item a -> IO ()
100 lhPush :: forall a. ToJSON a => Item a -> IO ()
@@ -102,7 +107,7 @@ data LogEnv = LogEnv {
102 , _logEnvApp :: AppName
107 , _logEnvApp :: AppName
103 , _logEnvEnv :: Environment
108 , _logEnvEnv :: Environment
104 , _logEnvTimer :: IO UTCTime
109 , _logEnvTimer :: IO UTCTime
105− , _logEnvHandlers :: M.Map Text LogHandler
110+ , _logEnvHandlers :: M.Map Text Scribe
107makeLenses ''LogEnv
112makeLenses ''LogEnv
@@ -121,7 +126,7 @@ initLogEnv an env = LogEnv
121registerHandler
126registerHandler
123 -- ^ Name the handler
128 -- ^ Name the handler
124− -> LogHandler
129+ -> Scribe
125 -> LogEnv
130 -> LogEnv
126 -> LogEnv
131 -> LogEnv
127registerHandler nm h = logEnvHandlers . at nm .~ Just h
132registerHandler nm h = logEnvHandlers . at nm .~ Just h
@@ -136,24 +141,38 @@ unregisterHandler
136unregisterHandler nm = logEnvHandlers . at nm .~ Nothing
141unregisterHandler nm = logEnvHandlers . at nm .~ Nothing
146+ getLogEnv :: m LogEnv
139-------------------------------------------------------------------------------
150-------------------------------------------------------------------------------
140−logM
151+-- | The generic *full* logging function.
141− :: (Applicative m, MonadIO m, ToJSON a, MonadReader LogEnv m)
153+ :: (Applicative m, MonadIO m, ToJSON a, Katip m)
142 => Severity
154 => Severity
156+ -- ^ Contextual payload for the log
158+ -- ^ The log message
146−logM sev a msg = do
160+logF sev a msg = do
161+ LogEnv{..} <- getLogEnv
147 item <- Item
162 item <- Item
148− <$> view logEnvApp
163+ <$> pure _logEnvApp
149− <*> view logEnvEnv
164+ <*> pure _logEnvEnv
150 <*> pure sev
165 <*> pure sev
151 <*> liftIO myThreadId
166 <*> liftIO myThreadId
152− <*> view logEnvHost
167+ <*> pure _logEnvHost
153 <*> pure a
168 <*> pure a
154 <*> pure msg
169 <*> pure msg
155− <*> (view logEnvTimer >>= liftIO)
170+ <*> liftIO _logEnvTimer
156− hs <- view $ logEnvHandlers . to M.elems
171+ liftIO $ forM_ (M.elems _logEnvHandlers) $ \ (Scribe h) -> h item
157− liftIO $ forM_ hs $ \ (LogHandler h) -> h item
172+
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