katip-wai-0.2.0.0: test/Katip/Wai/LogEntry.hs
module Katip.Wai.LogEntry
( Request (..)
, Status (..)
, ResponseTime (..)
, Response (..)
, LogData (..)
, LogEntry (..)
, requestHeaders
, responseHeaders
, toLogEntry
, shouldBe
)
where
import Data.Aeson ((.:))
import qualified Data.Aeson as Aeson
import Data.Function (on)
import Data.Map.Strict (Map)
import Data.Text (Text)
import Data.UUID (UUID)
import GHC.Generics (Generic)
import GHC.Natural (Natural)
import GHC.Stack (HasCallStack)
import qualified Katip
import qualified Test.Hspec as Hspec
data Request = Request
{ id :: UUID
, method :: Text
, httpVersion :: Text
, path :: Text
, headers :: Map Text Text
, isSecure :: Bool
, remoteHost :: Text
, queryString :: [(Text, Maybe Text)]
, receivedAt :: Text
}
deriving (Show, Eq, Generic)
instance Aeson.FromJSON Request
requestHeaders :: Request -> Map Text Text
requestHeaders Request{headers} =
headers
data ResponseTime = ResponseTime
{ unit :: Text
, time :: Double
}
deriving (Show, Eq, Generic)
instance Aeson.FromJSON ResponseTime
data Status = Status
{ code :: Natural
, message :: Text
}
deriving (Show, Eq, Generic)
instance Aeson.FromJSON Status
data Response = Response
{ status :: Status
, headers :: Map Text Text
, respondedAt :: Text
, responseTime :: ResponseTime
}
deriving (Show, Eq, Generic)
responseHeaders :: Response -> Map Text Text
responseHeaders Response{headers} =
headers
instance Aeson.FromJSON Response
data LogData = LogData
{ request :: Maybe Request
, response :: Maybe Response
}
deriving (Generic, Show)
instance Aeson.FromJSON LogData
data LogEntry = LogEntry
{ logMessage :: Text
, logData :: LogData
, logSeverity :: Katip.Severity
}
deriving (Show)
instance Aeson.FromJSON LogEntry where
parseJSON = Aeson.withObject "LogEntry" $ \obj ->
LogEntry <$> (obj .: "msg") <*> (obj .: "data") <*> (obj .: "sev")
toLogEntry :: Aeson.Value -> IO LogEntry
toLogEntry value =
case Aeson.fromJSON value of
Aeson.Success entry -> pure entry
Aeson.Error reason -> fail reason
shouldBe :: HasCallStack => LogEntry -> LogEntry -> IO ()
shouldBe log1 log2 = do
on Hspec.shouldBe logMessage log1 log2
on Hspec.shouldBe (fmap method . request . logData) log1 log2
on Hspec.shouldBe (fmap httpVersion . request . logData) log1 log2
on Hspec.shouldBe (fmap path . request . logData) log1 log2
on Hspec.shouldBe (fmap isSecure . request . logData) log1 log2
on Hspec.shouldBe (fmap queryString . request . logData) log1 log2
on Hspec.shouldBe (fmap status . response . logData) log1 log2
on Hspec.shouldBe logSeverity log1 log2