@@ -1,11 +1,12 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2module Network.Wai.Middleware.RequestLogger
2module Network.Wai.Middleware.RequestLogger
3 ( logStdout
3 ( logStdout
4− , logHandle
4+ , logCallback
5 , logStdoutDev
5 , logStdoutDev
6 , logHandleDev
9 , logHandleDev
11import System.IO (stdout, hFlush)
12import System.IO (stdout, hFlush)
@@ -15,37 +16,41 @@ import Control.Monad.IO.Class (liftIO)
15import Network.Wai (Request(..), Middleware)
16import Network.Wai (Request(..), Middleware)
16import System.Log.FastLogger
17import System.Log.FastLogger
17import Network.HTTP.Types as H
18import Network.HTTP.Types as H
18−import qualified Data.Text.Lazy as LT
19−import qualified Data.Text.Encoding as TE
21import Network.Wai.Parse (parseRequestBody, lbsSink, fileName, Param, File)
20import Network.Wai.Parse (parseRequestBody, lbsSink, fileName, Param, File)
22import qualified Data.ByteString.Lazy as LBS
21import qualified Data.ByteString.Lazy as LBS
23−import System.IO (hPutStrLn, stderr)
25import qualified Data.Conduit as C
23import qualified Data.Conduit as C
26import qualified Data.Conduit.List as CL
24import qualified Data.Conduit.List as CL
26+logHandle :: (BS.ByteString -> IO ()) -> Middleware
27+logHandle = logCallback
28+{-# DEPRECATED logHandle "Please use logCallback instead." #-}
29+logHandleDev :: (BS.ByteString -> IO ()) -> Middleware
30+logHandleDev = logCallbackDev
31+{-# DEPRECATED logHandleDev "Please use logCallbackDev instead." #-}
33+-- | Production request logger middleware.
28−-- | like @logHandle@, but prints to 'stdout'
34+-- Implemented on top of "logCallback", but prints to 'stdout'
29logStdout :: Middleware
35logStdout :: Middleware
30logStdout = logHandle $ \bs -> hPutLogStr stdout [LB bs]
36logStdout = logHandle $ \bs -> hPutLogStr stdout [LB bs]
38+-- | Development request logger middleware.
32−-- | like @logHandleDev@, but prints to 'stdout'
39+-- Implemented on top of "logCallbackDev", but prints to 'stdout'
34−-- Note that this flushes 'stdout' on each call to make it useful for
35−-- development. This is very inefficient for production use.
41+-- Flushes 'stdout' on each request, which would be inefficient in production use.
42+-- Use "logStdout" in production.
36logStdoutDev :: Middleware
43logStdoutDev :: Middleware
37logStdoutDev = logHandleDev $ \bs -> hPutLogStr stdout [LB bs] >> hFlush stdout
44logStdoutDev = logHandleDev $ \bs -> hPutLogStr stdout [LB bs] >> hFlush stdout
39−-- FIXME This is not appropriately named at all. It's not working on a Handle,
40−-- it's working on a function. I find the functions in this module to be very
44-- | Prints a message using the given callback function for each request.
46-- | Prints a message using the given callback function for each request.
45-- Designed for fast production use at the expense of convenience.
47-- Designed for fast production use at the expense of convenience.
46-- In particular, no POST parameter information is currently given
48-- In particular, no POST parameter information is currently given
50+-- This is lower-level - use "logStdout" unless you need this greater control
51+logCallback :: (BS.ByteString -> IO ()) -- ^ A function that logs the ByteString log message.
47−logHandle :: (BS.ByteString -> IO ()) -> Middleware
52+ -> Middleware
48−logHandle cb app req = do
53+logCallback cb app req = do
49 liftIO $ cb $ BS.concat
54 liftIO $ cb $ BS.concat
50 [ requestMethod req
55 [ requestMethod req
@@ -61,28 +66,14 @@ logHandle cb app req = do
61toBS :: H.Ascii -> BS.ByteString
66toBS :: H.Ascii -> BS.ByteString
64−-- FIXME: What's the purpose of this function? Why would it ever be preferable
65−-- to logStdoutDev? And why is it implemented via unpack instead of using a
66−-- more efficient Data.Text.IO function?
69−-- | Inefficient, but convenient Development load logger middleware
70−-- Prints a message to 'stderr' for each request using logHandleDevLT
71−logStdoutDevLT :: Middleware
72−logStdoutDevLT = logHandleDevLT $ hPutStrLn stderr . LT.unpack
74−-- | logHandleDev, but expects Lazy Text instead of a ByteString
75−logHandleDevLT :: (LT.Text -> IO ()) -> Middleware
76−logHandleDevLT cb app req =
77− logHandleDev (\msg -> cb $ LT.fromStrict $ TE.decodeUtf8 msg) app req
79-- | Prints a message using the given callback function for each request.
69-- | Prints a message using the given callback function for each request.
80-- This is not for serious production use- it is inefficient.
70-- This is not for serious production use- it is inefficient.
81-- It immediately consumes a POST body and fills it back in and is otherwise inefficient
71-- It immediately consumes a POST body and fills it back in and is otherwise inefficient
83−-- Note that this function will not flush output.
73+-- This is lower-level - use "logStdoutDev" unless you need this greater control
74+logCallbackDev :: (BS.ByteString -> IO ()) -- ^ A function that logs the ByteString log message.
84−logHandleDev :: (BS.ByteString -> IO ()) -> Middleware
75+ -> Middleware
85−logHandleDev cb app req = do
76+logCallbackDev cb app req = do
86 body <- requestBody req C.$$ CL.consume
77 body <- requestBody req C.$$ CL.consume
87 postParams <- if any (requestMethod req ==) ["GET", "HEAD"]
78 postParams <- if any (requestMethod req ==) ["GET", "HEAD"]
88 then return []
79 then return []
@@ -101,7 +92,7 @@ logHandleDev cb app req = do
101 , paramsToBS "POST " postParams
92 , paramsToBS "POST " postParams
104− -- we just consumed the body- fill the enumerator back up so it is available again
95+ -- The body was consumed. Fill it back up so it is available again
105 app req { requestBody = CL.sourceList body }
96 app req { requestBody = CL.sourceList body }
107 paramsToBS prefix params =
98 paramsToBS prefix params =