{-|
Module      : Control.Monad.Logger.Timed
Description : Add time stamps to log messages
Copyright   : (c) Westfalenwind Service GmbH & Co. KG
License     : GPL-3
Maintainer  : olaf.klinke@phymetric.de
Stability   : experimental

The standard 'LoggingT' logger prints the log level and log message, 
but not the (local) time at which the message was logged. 
This module adds that capability 
at the cost of additional two 'IO' operations for each logged message. 
-}
module Control.Monad.Logger.Timed (logTimeStamp) where
import Control.Monad.Logger
import Control.Applicative (liftA2)
import Data.Time.Format
import Data.Time.Clock     (getCurrentTime)
import Data.Time.LocalTime (getCurrentTimeZone,utcToZonedTime)
import Data.String (fromString)

-- | @'logTimeStamp' locale fmt@ 
-- prepends the current local time using @'formatTime' locale fmt@ 
-- to each log message. 
-- Consult the documentation of 'formatTime' for the syntax of @fmt@.  
logTimeStamp :: TimeLocale -> String -> LoggingT m a -> LoggingT m a
logTimeStamp loc fmt (LoggingT untimedLog) = LoggingT (untimedLog . prefixTime loc fmt)

-- | format the current local time 
localTime :: TimeLocale -> String -> IO LogStr
localTime locale fmt = liftA2 f getCurrentTimeZone getCurrentTime where
    fmtSpace = fmt <> " "
    f z u = fromString (formatTime locale fmtSpace (utcToZonedTime z u))

-- | alter the standard logging action to prefix the time
prefixTime :: TimeLocale -> String -> 
    (a -> b -> c -> LogStr -> IO ()) -> 
    a -> b -> c -> LogStr -> IO ()
prefixTime locale fmt withoutTime = \a b c message -> localTime locale fmt >>= 
    \timestamp -> withoutTime a b c (timestamp <> message)
