yesod/yesod-core/Yesod/Logger.hs
2011-12-25 14:04:14 -03:00

112 lines
3.0 KiB
Haskell

{-# LANGUAGE BangPatterns #-}
module Yesod.Logger
( Logger
, makeLogger
, makeLoggerWithHandle
, makeDefaultLogger
, flushLogger
, timed
, logText
, logLazyText
, logString
, logBS
, logMsg
, formatLogText
) where
import System.IO (Handle, stdout, hFlush)
import Data.ByteString (ByteString)
import Data.ByteString.Char8 (pack)
import Data.ByteString.Lazy (toChunks)
import qualified Data.Text.Lazy as TL
import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8)
import qualified Data.Text.Lazy.Encoding as TLE
import System.Log.FastLogger
import Network.Wai.Logger.Date (DateRef, dateInit, getDate)
-- for timed logging
import Data.Time (getCurrentTime, diffUTCTime)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Text.Printf (printf)
import Data.Text (unpack)
-- for formatter
import Language.Haskell.TH.Syntax (Loc)
import Yesod.Core (LogLevel, fileLocationToString)
data Logger = Logger {
loggerHandle :: Handle
, loggerDateRef :: DateRef
}
makeLogger :: IO Logger
makeLogger = makeDefaultLogger
{-# DEPRECATED makeLogger "Use makeDefaultLogger instead" #-}
makeLoggerWithHandle :: Handle -> IO Logger
makeLoggerWithHandle handle = dateInit >>= return . Logger handle
-- | uses stdout handle
makeDefaultLogger :: IO Logger
makeDefaultLogger = makeLoggerWithHandle stdout
flushLogger :: Logger -> IO ()
flushLogger = hFlush . loggerHandle
logMsg :: Logger -> [LogStr] -> IO ()
logMsg = hPutLogStr . loggerHandle
logLazyText :: Logger -> TL.Text -> IO ()
logLazyText logger msg = logMsg logger $
map LB (toChunks $ TLE.encodeUtf8 msg) ++ [newLine]
logText :: Logger -> Text -> IO ()
logText logger = logBS logger . encodeUtf8
logBS :: Logger -> ByteString -> IO ()
logBS logger msg = logMsg logger [LB msg, newLine]
logString :: Logger -> String -> IO ()
logString logger msg = logMsg logger [LS msg, newLine]
formatLogText :: Logger -> Loc -> LogLevel -> Text -> IO [LogStr]
formatLogText logger loc level msg = formatLogMsg logger loc level (toLB msg)
toLB :: Text -> LogStr
toLB = LB . encodeUtf8
formatLogMsg :: Logger -> Loc -> LogLevel -> LogStr -> IO [LogStr]
formatLogMsg logger loc level msg = do
date <- liftIO $ getDate $ loggerDateRef logger
return
[ LB date
, LB $ pack" ["
, LS (drop 5 $ show level)
, LB $ pack "] "
, msg
, LB $ pack " @("
, LS (fileLocationToString loc)
, LB $ pack ") "
]
newLine :: LogStr
newLine = LB $ pack "\"\n"
-- | Execute a monadic action and log the duration
--
timed :: MonadIO m
=> Logger -- ^ Logger
-> Text -- ^ 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 (unpack msg)
liftIO $ logString logger formatted
return result