module Hakyll.Core.Logger
( Verbosity (..)
, Logger
, new
, flush
, error
, header
, message
, debug
) where
import Control.Concurrent (forkIO)
import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, takeMVar)
import Control.Monad (forever)
import Control.Monad.Trans (MonadIO, liftIO)
import Data.List (intercalate)
import Prelude hiding (error)
data Verbosity
= Error
| Message
| Debug
deriving (Eq, Ord, Show)
data Logger = Logger
{ loggerChan :: Chan (Maybe String)
, loggerSync :: MVar ()
, loggerSink :: String -> IO ()
, loggerVerbosity :: Verbosity
}
new :: Verbosity -> IO Logger
new vbty = do
logger <- Logger <$>
newChan <*> newEmptyMVar <*> pure putStrLn <*> pure vbty
_ <- forkIO $ loggerThread logger
return logger
where
loggerThread logger = forever $ do
msg <- readChan $ loggerChan logger
case msg of
Nothing -> putMVar (loggerSync logger) ()
Just m -> loggerSink logger m
flush :: Logger -> IO ()
flush logger = do
writeChan (loggerChan logger) Nothing
() <- takeMVar $ loggerSync logger
return ()
string :: MonadIO m
=> Logger
-> Verbosity
-> String
-> m ()
string l v m
| loggerVerbosity l >= v = liftIO $ writeChan (loggerChan l) (Just m)
| otherwise = return ()
error :: MonadIO m => Logger -> String -> m ()
error l m = string l Error $ " [ERROR] " ++ indent m
header :: MonadIO m => Logger -> String -> m ()
header l = string l Message
message :: MonadIO m => Logger -> String -> m ()
message l m = string l Message $ " " ++ indent m
debug :: MonadIO m => Logger -> String -> m ()
debug l m = string l Debug $ " [DEBUG] " ++ indent m
indent :: String -> String
indent = intercalate "\n " . lines