summaryrefslogtreecommitdiff
path: root/src/Hakyll/Core/Logger.hs
diff options
context:
space:
mode:
authorJasper Van der Jeugt <jaspervdj@gmail.com>2011-03-01 14:50:41 +0100
committerJasper Van der Jeugt <jaspervdj@gmail.com>2011-03-01 14:50:41 +0100
commit90b25105830d6e4b0943ab55f9317bd142533acf (patch)
tree6eefb80a8a84724e70539dd8fa449530f7b17fe0 /src/Hakyll/Core/Logger.hs
parent8ef5a3ed0307be5d34a9564d02af3ed494f8e228 (diff)
parent8b727b994d482d593046f9b01a5c40b97c166d62 (diff)
downloadhakyll-90b25105830d6e4b0943ab55f9317bd142533acf.tar.gz
Merge branch 'hakyll3'
Conflicts: hakyll.cabal src/Text/Hakyll/Tags.hs
Diffstat (limited to 'src/Hakyll/Core/Logger.hs')
-rw-r--r--src/Hakyll/Core/Logger.hs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/Hakyll/Core/Logger.hs b/src/Hakyll/Core/Logger.hs
new file mode 100644
index 0000000..720dee0
--- /dev/null
+++ b/src/Hakyll/Core/Logger.hs
@@ -0,0 +1,90 @@
+-- | Produce pretty, thread-safe logs
+--
+{-# LANGUAGE BangPatterns #-}
+module Hakyll.Core.Logger
+ ( Logger
+ , makeLogger
+ , flushLogger
+ , section
+ , timed
+ , report
+ ) where
+
+import Control.Monad (forever)
+import Control.Monad.Trans (MonadIO, liftIO)
+import Control.Applicative ((<$>), (<*>))
+import Control.Concurrent (forkIO)
+import Control.Concurrent.Chan.Strict (Chan, newChan, readChan, writeChan)
+import Control.Concurrent.MVar.Strict (MVar, newEmptyMVar, takeMVar, putMVar)
+import Text.Printf (printf)
+
+import Data.Time (getCurrentTime, diffUTCTime)
+
+-- | Logger structure. Very complicated.
+--
+data Logger = Logger
+ { loggerChan :: Chan (Maybe String) -- Nothing marks the end
+ , loggerSync :: MVar () -- Used for sync on quit
+ }
+
+-- | Create a new logger
+--
+makeLogger :: IO Logger
+makeLogger = do
+ logger <- Logger <$> newChan <*> newEmptyMVar
+ _ <- forkIO $ loggerThread logger
+ return logger
+ where
+ loggerThread logger = forever $ do
+ msg <- readChan $ loggerChan logger
+ case msg of
+ -- Stop: sync
+ Nothing -> putMVar (loggerSync logger) ()
+ -- Print and continue
+ Just m -> putStrLn m
+
+-- | Flush the logger (blocks until flushed)
+--
+flushLogger :: Logger -> IO ()
+flushLogger logger = do
+ writeChan (loggerChan logger) Nothing
+ () <- takeMVar $ loggerSync logger
+ return ()
+
+-- | Send a raw message to the logger
+--
+message :: Logger -> String -> IO ()
+message logger = writeChan (loggerChan logger) . Just
+
+-- | Start a section in the log
+--
+section :: MonadIO m
+ => Logger -- ^ Logger
+ -> String -- ^ Section name
+ -> m () -- ^ No result
+section logger = liftIO . message logger
+
+-- | Execute a monadic action and log the duration
+--
+timed :: MonadIO m
+ => Logger -- ^ Logger
+ -> String -- ^ Message
+ -> m a -- ^ Action
+ -> m a -- ^ Timed and logged action
+timed logger msg action = do
+ start <- liftIO getCurrentTime
+ !result <- action
+ stop <- liftIO getCurrentTime
+ let diff = fromEnum $ diffUTCTime stop start
+ ms = diff `div` 10 ^ (9 :: Int)
+ formatted = printf " [%4dms] %s" ms msg
+ liftIO $ message logger formatted
+ return result
+
+-- | Log something at the same level as 'timed', but without the timing
+--
+report :: MonadIO m
+ => Logger -- ^ Logger
+ -> String -- ^ Message
+ -> m () -- ^ No result
+report logger msg = liftIO $ message logger $ " [ ] " ++ msg