haskellyesodhaskell-warp

Controlling Wai logger messages


I have a Haskell yesod web-server which works fine1,2, and logs fine3:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE TypeFamilies      #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE OverloadedStrings #-}

import Yesod
import Prelude
import Data.Aeson()
import GHC.Generics
import Data.Text
import Data.Time
import Yesod.Core.Types
import System.Log.FastLogger
import Network.Wai.Handler.Warp

-- Wai stuff
import qualified Network.Wai
import qualified Network.Wai.Logger
import qualified Network.HTTP.Types.Status
import qualified Network.Wai.Middleware.RequestLogger as Wai

data Healthy = Healthy Bool deriving ( Generic )

-- | This is just for the health check ...
instance ToJSON Healthy where toJSON (Healthy status) = object [ "healthy" .= status ]

data App = App

mkYesod "App" [parseRoutes|
/healthcheck HealthcheckR GET
|]

instance Yesod App where
    makeLogger = \_app -> myLogger

getHealthcheckR :: Handler Value
getHealthcheckR = do
    $logInfoS "(HealthCheck)" "Good !"
    returnJson $ Healthy True

myLogger :: IO Logger
myLogger = do
    _loggerSet <- newStdoutLoggerSet defaultBufSize
    formatter <- newTimeCache "[%d/%m/%Y ( %H:%M:%S )]"
    return $ Logger _loggerSet formatter

dateFormatter :: String -> String
dateFormatter date = let
    date' = parseTimeOrError True defaultTimeLocale "%d/%b/%Y:%T %Z" date :: UTCTime
    in formatTime defaultTimeLocale "[%Y/%m/%d ( %H:%M:%S )]" date'

formatter :: Network.Wai.Logger.ZonedDate -> Network.Wai.Request -> Network.HTTP.Types.Status.Status -> Maybe Integer -> LogStr
formatter zonedDate req status responseSize = "[ 17/17/2017 ]\n"

main :: IO ()
main = do
    waiApp <- toWaiApp App
    middleware <- Wai.mkRequestLogger (Wai.defaultRequestLoggerSettings { Wai.outputFormat = Wai.CustomOutputFormat formatter })
    run 3000 $ middleware waiApp

When I inspect the logs, I see three messages, two of them are mine

[23/10/2024 ( 15:07:06 )] [Info#(HealthCheck)] Good ! @(main:Main src/Main.hs:41:6)
172.17.0.1 - - [23/Oct/2024:15:07:06 +0000] "GET /healthcheck HTTP/1.1" 200 16 "" "curl/8.9.1"
[ 17/17/2017 ]

Where does the 172.17.0.1 - - ... message come from ?! It seems it must come from the Wai layer (right ?) But then again, I thought I configured the Wai logs


1,2 complete source code here, edited for minimality according to comments

3 well, almost !


Solution

  • The toWaiApp function adds default middleware that includes request logging. To add the default middleware excluding logging, you need to use toWaiAppPlain and then add a logging-free default set of middleware:

    main :: IO ()
    main = do
        waiApp <- toWaiAppPlain App
        myLoggingMiddleware <- Wai.mkRequestLogger (Wai.defaultRequestLoggerSettings { Wai.outputFormat = Wai.CustomOutputFormat formatter })
        let middleware = myLoggingMiddleware . defaultMiddlewaresNoLogging
        run 3000 $ middleware waiApp
    

    After this change, the test program in the question generates just two lines for a request:

    [23/10/2024 ( 11:18:56 )] [Info#(HealthCheck)] Good ! @(main:Main WaiLogger.hs:43:6)
    [ 17/17/2017 ]