wai-middleware-prometheus 0.1.0.1 → 0.1.1
raw patch · 2 files changed
+36/−20 lines, 2 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Network.Wai.Middleware.Prometheus: instance Default PrometheusSettings
- Network.Wai.Middleware.Prometheus: prometheusEndPoint :: PrometheusSettings -> [Text]
- Network.Wai.Middleware.Prometheus: prometheusInstrumentApp :: PrometheusSettings -> Bool
- Network.Wai.Middleware.Prometheus: prometheusInstrumentPrometheus :: PrometheusSettings -> Bool
+ Network.Wai.Middleware.Prometheus: [prometheusEndPoint] :: PrometheusSettings -> [Text]
+ Network.Wai.Middleware.Prometheus: [prometheusInstrumentApp] :: PrometheusSettings -> Bool
+ Network.Wai.Middleware.Prometheus: [prometheusInstrumentPrometheus] :: PrometheusSettings -> Bool
+ Network.Wai.Middleware.Prometheus: instance Data.Default.Class.Default Network.Wai.Middleware.Prometheus.PrometheusSettings
+ Network.Wai.Middleware.Prometheus: metricsApp :: Application
Files
src/Network/Wai/Middleware/Prometheus.hs view
@@ -8,11 +8,14 @@ , Default.def , instrumentApp , instrumentIO+, metricsApp ) where -import Data.Time.Clock (diffUTCTime, getCurrentTime)+import Data.Time.Clock (UTCTime, diffUTCTime, getCurrentTime) import qualified Data.ByteString.Builder as BS+import qualified Data.ByteString.Char8 as BS import qualified Data.Default as Default+import Data.Maybe (fromMaybe) import qualified Data.Text as T import qualified Network.HTTP.Types as HTTP import qualified Network.Wai as Wai@@ -43,8 +46,10 @@ } {-# NOINLINE requestLatency #-}-requestLatency :: Prom.Metric (Prom.Vector Prom.Label1 Prom.Summary)-requestLatency = Prom.unsafeRegisterIO $ Prom.vector "handler"+-- XXX: https://prometheus.io/docs/practices/naming/ says this should be+-- _seconds, not _microseconds.+requestLatency :: Prom.Metric (Prom.Vector Prom.Label3 Prom.Summary)+requestLatency = Prom.unsafeRegisterIO $ Prom.vector ("handler", "method", "status_code") $ Prom.summary info Prom.defaultQuantiles where info = Prom.Info "http_request_duration_microseconds" "The HTTP request latencies in microseconds."@@ -57,8 +62,14 @@ instrumentApp :: String -- ^ The label used to identify this app -> Wai.Application -- ^ The app to instrument -> Wai.Application -- ^ The instrumented app-instrumentApp handler app req respond =- observeMicroSeconds handler (app req respond)+instrumentApp handler app req respond = do+ start <- getCurrentTime+ app req $ \res -> do+ end <- getCurrentTime+ let method = Just $ BS.unpack (Wai.requestMethod req)+ let status = Just $ show (HTTP.statusCode (Wai.responseStatus res))+ observeMicroSeconds handler method status start end+ respond res -- | Instrument an IO action with timing metrics. This function can be used if -- you would like to get more fine grained metrics, for instance this can be@@ -70,31 +81,36 @@ instrumentIO :: String -- ^ The label used to identify this IO operation -> IO a -- ^ The IO action to instrument -> IO a -- ^ The instrumented app-instrumentIO = observeMicroSeconds--observeMicroSeconds :: String -> IO a -> IO a-observeMicroSeconds handler io = do+instrumentIO label io = do start <- getCurrentTime result <- io end <- getCurrentTime- let latency = fromRational $ toRational (end `diffUTCTime` start) * 1000000- Prom.withLabel handler (Prom.observe latency) requestLatency+ observeMicroSeconds label Nothing Nothing start end return result +observeMicroSeconds :: String -> Maybe String -> Maybe String -> UTCTime -> UTCTime -> IO ()+observeMicroSeconds handler method status start end = do+ let latency = fromRational $ toRational (end `diffUTCTime` start) * 1000000+ Prom.withLabel (handler, fromMaybe "" method, fromMaybe "" status)+ (Prom.observe latency)+ requestLatency+ -- | Expose Prometheus metrics and instrument an application with some basic -- metrics (e.g. request latency). prometheus :: PrometheusSettings -> Wai.Middleware prometheus PrometheusSettings{..} app req respond = if Wai.requestMethod req == HTTP.methodGet && Wai.pathInfo req == prometheusEndPoint- then measure measureMetrics "prometheus" $ respondWithMetrics respond- else measure measureApp "app" $ app req respond- where- measureMetrics = prometheusInstrumentPrometheus- measureApp = prometheusInstrumentApp- measure shouldInstrument handler io- | shouldInstrument = observeMicroSeconds handler io- | otherwise = io+ -- XXX: Should probably be "metrics" rather than "prometheus", since+ -- "prometheus" can be confused with actual prometheus.+ then instrumentApp "prometheus" (const respondWithMetrics) req respond+ else instrumentApp "app" app req respond+++-- | WAI Application that serves the Prometheus metrics page regardless of+-- what the request is.+metricsApp :: Wai.Application+metricsApp = const respondWithMetrics respondWithMetrics :: (Wai.Response -> IO Wai.ResponseReceived) -> IO Wai.ResponseReceived
wai-middleware-prometheus.cabal view
@@ -1,5 +1,5 @@ name: wai-middleware-prometheus-version: 0.1.0.1+version: 0.1.1 synopsis: WAI middlware for exposing http://prometheus.io metrics. description: