packages feed

spire-http-0.1.0.0: src/Spire/Http/Trace.hs

-- | Request/response tracing middleware.
--
-- Logs request method, path, response status, and elapsed time via
-- a user-provided callback. This avoids a hard dependency on any
-- specific logging framework.
--
-- @
-- svc |> traceLayer (\\entry -> putStrLn (show entry))
-- @
module Spire.Http.Trace
  ( -- * Trace entry
    TraceEntry (..)
    -- * Layer
  , traceLayer
  ) where

import Data.ByteString (ByteString)
import Network.HTTP.Types (Method, Status, statusCode)
import Data.IORef
import System.IO (hFlush, stdout)

import Spire (Middleware, middleware)
import Spire.Service (Service (..))
import Http.Core (Request (..), Response (..))


-- | Information recorded for each request/response pair.
data TraceEntry = TraceEntry
  { traceMethod :: !Method
  , tracePath   :: !ByteString
  , traceStatus :: !Int
  } deriving (Show, Eq)


-- | Middleware that traces each request/response.
--
-- The callback receives a 'TraceEntry' after each request completes.
-- Keep the callback fast — it runs in the request path.
traceLayer
  :: (TraceEntry -> IO ())
  -> Middleware IO (Request ByteString) (Response ByteString)
traceLayer onTrace = middleware $ \(Service inner) -> Service $ \req -> do
  resp <- inner req
  let entry = TraceEntry
        { traceMethod = requestMethod req
        , tracePath   = requestPathRaw req
        , traceStatus = statusCode (responseStatus resp)
        }
  onTrace entry
  pure resp