{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
module Network.Wai.Logger (
ApacheLogger
, withStdoutLogger
, ServerPushLogger
, ApacheLoggerActions
, apacheLogger
, serverpushLogger
, logRotator
, logRemover
, initLoggerUser
, 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 :: forall a. (ApacheLogger -> IO a) -> IO a
withStdoutLogger ApacheLogger -> IO a
app = IO (ApacheLogger, IO ())
-> ((ApacheLogger, IO ()) -> IO ())
-> ((ApacheLogger, IO ()) -> IO a)
-> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO (ApacheLogger, IO ())
setup (ApacheLogger, IO ()) -> IO ()
forall {f :: * -> *} {a} {a}. Functor f => (a, f a) -> f ()
teardown (((ApacheLogger, IO ()) -> IO a) -> IO a)
-> ((ApacheLogger, IO ()) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \(ApacheLogger
aplogger, IO ()
_) ->
ApacheLogger -> IO a
app ApacheLogger
aplogger
where
setup :: IO (ApacheLogger, IO ())
setup = do
IO ByteString
tgetter <- ByteString -> IO (IO ByteString)
newTimeCache ByteString
simpleTimeFormat
ApacheLoggerActions
apf <- IPAddrSource -> LogType -> IO ByteString -> IO ApacheLoggerActions
initLogger IPAddrSource
FromFallback (BufSize -> LogType
LogStdout BufSize
4096) IO ByteString
tgetter
let aplogger :: ApacheLogger
aplogger = ApacheLoggerActions -> ApacheLogger
apacheLogger ApacheLoggerActions
apf
remover :: IO ()
remover = ApacheLoggerActions -> IO ()
logRemover ApacheLoggerActions
apf
(ApacheLogger, IO ()) -> IO (ApacheLogger, IO ())
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ApacheLogger
aplogger, IO ()
remover)
teardown :: (a, f a) -> f ()
teardown (a
_, f a
remover) = f a -> f ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void f a
remover
type ApacheLogger = Request -> Status -> Maybe Integer -> IO ()
type ServerPushLogger = Request -> ByteString -> Integer -> IO ()
data ApacheLoggerActions = ApacheLoggerActions {
ApacheLoggerActions -> ApacheLogger
apacheLogger :: ApacheLogger
, ApacheLoggerActions -> ServerPushLogger
serverpushLogger :: ServerPushLogger
, ApacheLoggerActions -> IO ()
logRotator :: IO ()
, ApacheLoggerActions -> IO ()
logRemover :: IO ()
}
initLoggerUser :: ToLogStr user => Maybe (Request -> Maybe user) -> IPAddrSource -> LogType -> IO FormattedTime
-> IO ApacheLoggerActions
initLoggerUser :: forall user.
ToLogStr user =>
Maybe (Request -> Maybe user)
-> IPAddrSource
-> LogType
-> IO ByteString
-> IO ApacheLoggerActions
initLoggerUser Maybe (Request -> Maybe user)
ugetter IPAddrSource
ipsrc LogType
typ IO ByteString
tgetter = do
(LogStr -> IO ()
fl, IO ()
cleanUp) <- LogType -> IO (LogStr -> IO (), IO ())
forall v. LogType' v -> IO (v -> IO (), IO ())
newFastLogger LogType
typ
ApacheLoggerActions -> IO ApacheLoggerActions
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ApacheLoggerActions -> IO ApacheLoggerActions)
-> ApacheLoggerActions -> IO ApacheLoggerActions
forall a b. (a -> b) -> a -> b
$ ApacheLoggerActions {
apacheLogger :: ApacheLogger
apacheLogger = (LogStr -> IO ())
-> IPAddrSource
-> Maybe (Request -> Maybe user)
-> IO ByteString
-> ApacheLogger
forall user.
ToLogStr user =>
(LogStr -> IO ())
-> IPAddrSource
-> Maybe (Request -> Maybe user)
-> IO ByteString
-> ApacheLogger
apache LogStr -> IO ()
fl IPAddrSource
ipsrc Maybe (Request -> Maybe user)
ugetter IO ByteString
tgetter
, serverpushLogger :: ServerPushLogger
serverpushLogger = (LogStr -> IO ())
-> IPAddrSource
-> Maybe (Request -> Maybe user)
-> IO ByteString
-> ServerPushLogger
forall user.
ToLogStr user =>
(LogStr -> IO ())
-> IPAddrSource
-> Maybe (Request -> Maybe user)
-> IO ByteString
-> ServerPushLogger
serverpush LogStr -> IO ()
fl IPAddrSource
ipsrc Maybe (Request -> Maybe user)
ugetter IO ByteString
tgetter
, logRotator :: IO ()
logRotator = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
, logRemover :: IO ()
logRemover = IO ()
cleanUp
}
initLogger :: IPAddrSource -> LogType -> IO FormattedTime
-> IO ApacheLoggerActions
initLogger :: IPAddrSource -> LogType -> IO ByteString -> IO ApacheLoggerActions
initLogger = Maybe (Request -> Maybe ByteString)
-> IPAddrSource
-> LogType
-> IO ByteString
-> IO ApacheLoggerActions
forall user.
ToLogStr user =>
Maybe (Request -> Maybe user)
-> IPAddrSource
-> LogType
-> IO ByteString
-> IO ApacheLoggerActions
initLoggerUser Maybe (Request -> Maybe ByteString)
nouser
where
nouser :: Maybe (Request -> Maybe ByteString)
nouser :: Maybe (Request -> Maybe ByteString)
nouser = Maybe (Request -> Maybe ByteString)
forall a. Maybe a
Nothing
logCheck :: LogType -> IO ()
logCheck :: LogType -> IO ()
logCheck LogType
LogNone = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
logCheck (LogStdout BufSize
_) = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
logCheck (LogStderr BufSize
_) = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
logCheck (LogFileNoRotate FilePath
fp BufSize
_) = FilePath -> IO ()
check FilePath
fp
logCheck (LogFile FileLogSpec
spec BufSize
_) = FilePath -> IO ()
check (FileLogSpec -> FilePath
log_file FileLogSpec
spec)
logCheck (LogFileTimedRotate TimedFileLogSpec
spec BufSize
_) = FilePath -> IO ()
check (TimedFileLogSpec -> FilePath
timed_log_file TimedFileLogSpec
spec)
logCheck (LogCallback LogStr -> IO ()
_ IO ()
_) = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
apache :: ToLogStr user => (LogStr -> IO ()) -> IPAddrSource -> Maybe (Request -> Maybe user) -> IO FormattedTime -> ApacheLogger
apache :: forall user.
ToLogStr user =>
(LogStr -> IO ())
-> IPAddrSource
-> Maybe (Request -> Maybe user)
-> IO ByteString
-> ApacheLogger
apache LogStr -> IO ()
cb IPAddrSource
ipsrc Maybe (Request -> Maybe user)
userget IO ByteString
dateget Request
req Status
st Maybe Integer
mlen = do
ByteString
zdata <- IO ByteString
dateget
LogStr -> IO ()
cb (IPAddrSource
-> (Request -> Maybe user)
-> ByteString
-> Request
-> Status
-> Maybe Integer
-> LogStr
forall user.
ToLogStr user =>
IPAddrSource
-> (Request -> Maybe user)
-> ByteString
-> Request
-> Status
-> Maybe Integer
-> LogStr
apacheLogStr IPAddrSource
ipsrc (Maybe (Request -> Maybe user) -> Request -> Maybe user
forall user. Maybe (Request -> Maybe user) -> Request -> Maybe user
justGetUser Maybe (Request -> Maybe user)
userget) ByteString
zdata Request
req Status
st Maybe Integer
mlen)
serverpush :: ToLogStr user => (LogStr -> IO ()) -> IPAddrSource -> Maybe (Request -> Maybe user) -> IO FormattedTime -> ServerPushLogger
serverpush :: forall user.
ToLogStr user =>
(LogStr -> IO ())
-> IPAddrSource
-> Maybe (Request -> Maybe user)
-> IO ByteString
-> ServerPushLogger
serverpush LogStr -> IO ()
cb IPAddrSource
ipsrc Maybe (Request -> Maybe user)
userget IO ByteString
dateget Request
req ByteString
path Integer
size = do
ByteString
zdata <- IO ByteString
dateget
LogStr -> IO ()
cb (IPAddrSource
-> (Request -> Maybe user)
-> ByteString
-> Request
-> ByteString
-> Integer
-> LogStr
forall user.
ToLogStr user =>
IPAddrSource
-> (Request -> Maybe user)
-> ByteString
-> Request
-> ByteString
-> Integer
-> LogStr
serverpushLogStr IPAddrSource
ipsrc (Maybe (Request -> Maybe user) -> Request -> Maybe user
forall user. Maybe (Request -> Maybe user) -> Request -> Maybe user
justGetUser Maybe (Request -> Maybe user)
userget) ByteString
zdata Request
req ByteString
path Integer
size)
type DateCacheGetter = IO ZonedDate
type DateCacheUpdater = IO ()
type ZonedDate = FormattedTime
clockDateCacher :: IO (DateCacheGetter, DateCacheUpdater)
clockDateCacher :: IO (IO ByteString, IO ())
clockDateCacher = do
IO ByteString
tgetter <- ByteString -> IO (IO ByteString)
newTimeCache ByteString
simpleTimeFormat
(IO ByteString, IO ()) -> IO (IO ByteString, IO ())
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (IO ByteString
tgetter, () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
justGetUser :: Maybe (Request -> Maybe user) -> (Request -> Maybe user)
justGetUser :: forall user. Maybe (Request -> Maybe user) -> Request -> Maybe user
justGetUser (Just Request -> Maybe user
getter) = Request -> Maybe user
getter
justGetUser Maybe (Request -> Maybe user)
Nothing = \Request
_ -> Maybe user
forall a. Maybe a
Nothing