prometheus-2.2.4: src/System/Metrics/Prometheus/Http/Scrape.hs
{-# LANGUAGE OverloadedStrings #-}
module System.Metrics.Prometheus.Http.Scrape (
Path,
serveMetrics,
serveMetricsT,
prometheusApp,
) where
import Control.Applicative ((<$>))
import Control.Monad.IO.Class (
MonadIO,
liftIO,
)
import Data.Text (Text)
import Network.HTTP.Types (
hContentType,
methodGet,
status200,
status404,
)
import Network.Wai (
Application,
Request,
Response,
pathInfo,
requestMethod,
responseBuilder,
responseLBS,
)
import Network.Wai.Handler.Warp (Port, run)
import System.Metrics.Prometheus.Concurrent.RegistryT (
RegistryT,
sample,
)
import System.Metrics.Prometheus.Encode.Text (encodeMetrics)
import System.Metrics.Prometheus.Registry (RegistrySample)
-- | The HTTP web route on which to serve data
--
-- For example:
--
-- * @http://localhost:9090/metrics@ should use a path of @["metrics"]@.
-- * @http://localhost/@ should use a path of @[]@.
type Path = [Text]
serveMetrics :: MonadIO m => Port -> Path -> IO RegistrySample -> m ()
serveMetrics port path = liftIO . run port . prometheusApp path
serveMetricsT :: MonadIO m => Port -> Path -> RegistryT m ()
serveMetricsT port path = liftIO . serveMetrics port path =<< sample
prometheusApp :: Path -> IO RegistrySample -> Application
prometheusApp path runSample request respond
| isPrometheusRequest path request = respond =<< prometheusResponse <$> runSample
| otherwise = respond response404
where
prometheusResponse = responseBuilder status200 headers . encodeMetrics
headers = [(hContentType, "text/plain; version=0.0.4")]
response404 :: Response
response404 = responseLBS status404 header404 body404
where
header404 = [(hContentType, "text/plain")]
body404 = "404"
isPrometheusRequest :: Path -> Request -> Bool
isPrometheusRequest path request = isGet && matchesPath
where
matchesPath = pathInfo request == path
isGet = requestMethod request == methodGet