{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
module Network.Wai.Logger (
ApacheLogger
, withStdoutLogger
, ServerPushLogger
, ApacheLoggerActions
, apacheLogger
, serverpushLogger
, logRotator
, logRemover
, initLogger
, IPAddrSource(..)
, LogType'(..), LogType
, FileLogSpec(..)
, showSockAddr
, logCheck
, clockDateCacher
, ZonedDate
, DateCacheGetter
, DateCacheUpdater
) where
#if __GLASGOW_HASKELL__ < 709
import Control.Applicative ((<$>))
#endif
import Control.Exception (bracket)
import Control.Monad (void)
import Data.ByteString (ByteString)
import Network.HTTP.Types (Status)
import Network.Wai (Request)
import System.Log.FastLogger
import Network.Wai.Logger.Apache
import Network.Wai.Logger.IP (showSockAddr)
withStdoutLogger :: (ApacheLogger -> IO a) -> IO a
withStdoutLogger app = bracket setup teardown $ \(aplogger, _) ->
app aplogger
where
setup = do
tgetter <- newTimeCache simpleTimeFormat
apf <- initLogger FromFallback (LogStdout 4096) tgetter
let aplogger = apacheLogger apf
remover = logRemover apf
return (aplogger, remover)
teardown (_, remover) = void remover
type ApacheLogger = Request -> Status -> Maybe Integer -> IO ()
type ServerPushLogger = Request -> ByteString -> Integer -> IO ()
data ApacheLoggerActions = ApacheLoggerActions {
apacheLogger :: ApacheLogger
, serverpushLogger :: ServerPushLogger
, logRotator :: IO ()
, logRemover :: IO ()
}
initLogger :: IPAddrSource -> LogType -> IO FormattedTime
-> IO ApacheLoggerActions
initLogger ipsrc typ tgetter = do
(fl, cleanUp) <- newFastLogger typ
return $ ApacheLoggerActions {
apacheLogger = apache fl ipsrc tgetter
, serverpushLogger = serverpush fl ipsrc tgetter
, logRotator = return ()
, logRemover = cleanUp
}
logCheck :: LogType -> IO ()
logCheck LogNone = return ()
logCheck (LogStdout _) = return ()
logCheck (LogStderr _) = return ()
logCheck (LogFileNoRotate fp _) = check fp
logCheck (LogFile spec _) = check (log_file spec)
logCheck (LogFileTimedRotate spec _) = check (timed_log_file spec)
logCheck (LogCallback _ _) = return ()
apache :: (LogStr -> IO ()) -> IPAddrSource -> IO FormattedTime -> ApacheLogger
apache cb ipsrc dateget req st mlen = do
zdata <- dateget
cb (apacheLogStr ipsrc zdata req st mlen)
serverpush :: (LogStr -> IO ()) -> IPAddrSource -> IO FormattedTime -> ServerPushLogger
serverpush cb ipsrc dateget req path size = do
zdata <- dateget
cb (serverpushLogStr ipsrc zdata req path size)
type DateCacheGetter = IO ZonedDate
type DateCacheUpdater = IO ()
type ZonedDate = FormattedTime
clockDateCacher :: IO (DateCacheGetter, DateCacheUpdater)
clockDateCacher = do
tgetter <- newTimeCache simpleTimeFormat
return (tgetter, return ())