ngx-export-tools-extra 0.5.4.1 → 0.5.5.0
raw patch · 3 files changed
+78/−40 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- Changelog.md +5/−0
- NgxExport/Tools/Prometheus.hs +72/−39
- ngx-export-tools-extra.cabal +1/−1
Changelog.md view
@@ -1,3 +1,8 @@+### 0.5.5.0++- Added content handler *prometheusMetrics*.+- Using lazy text for encoding Prometheus metrics.+ ### 0.5.4.0 - Added handler *extractRequestStatusFromFullResponse* to retrieve completion
NgxExport/Tools/Prometheus.hs view
@@ -41,7 +41,8 @@ import Data.IORef import Data.Text (Text) import qualified Data.Text as T-import qualified Data.Text.Encoding as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TL import Data.Aeson import Data.Maybe import Data.Function@@ -100,12 +101,14 @@ -- -- This module is aimed to convert custom counters from -- [nginx-custom-counters-module](https://github.com/lyokha/nginx-custom-counters-module)--- to Prometheus metrics. For this, it exposes three exporters:+-- to Prometheus metrics. For this, it exposes four exporters: -- __/prometheusConf/__ which is an 'ignitionService' in terms of module -- "NgxExport.Tools", __/toPrometheusMetrics/__ to convert /custom counters/ to--- Prometheus metrics, and __/scale1000/__: a small utility to convert small--- floating point numbers to integers by multiplying them by /1000/ (this fits--- well for dealing with request durations, for instance).+-- Prometheus metrics, __/prometheusMetrics/__ which is a content handler aiming+-- to return Prometheus metrics to the client, and a handy utility+-- __/scale1000/__ to convert small floating point numbers to integers by+-- multiplying them by /1000/ (which fits well for dealing with request+-- durations). -- -- The module makes use of a few custom data types which are not exported while -- still needed when writing Nginx configurations. In the following example they@@ -238,6 +241,8 @@ -- return 503; -- } --+-- default_type \"text/plain; version=0.0.4; charset=utf-8\";+-- -- echo -n $hs_prom_metrics; -- } --@@ -289,6 +294,24 @@ -- histogram /hst_request_time/ has 11 buckets, the map for /bytes_sent_bucket/ -- has 5 range boundaries while histogram /hst_bytes_sent/ has 6 buckets. --+-- Notice that the variable handler /toPrometheusMetrics/ and directive /echo/+-- in location /\// can be replaced with a single content handler+-- /prometheusMetrics/ like in the following block.+--+-- @+-- location \/ {+-- haskell_async_content __/prometheusMetrics/__+-- '[\"__/main/__\"+-- ,$__/cnt_collection/__+-- ,$__/cnt_histograms/__+-- ,{\"cnt_stub_status_active\": $cnt_stub_status_active+-- ,\"cnt_uptime\": $cnt_uptime+-- ,\"cnt_uptime_reload\": $cnt_uptime_reload+-- }+-- ]';+-- }+-- @+-- -- ==== A simple test -- -- Let's look at the metrics right after starting Nginx.@@ -428,10 +451,7 @@ in (M.map Histogram cntsH'', M.mapWithKey cType cntsC') cntsA = cntsH `M.union` cntsC `M.union` M.mapWithKey cType (toValues ocnts)- in M.mapWithKey (\k v -> case M.lookup k pcMetrics of- Nothing -> ("", v)- Just h -> (h, v)- ) cntsA+ in M.mapWithKey (\k -> (fromMaybe "" (M.lookup k pcMetrics),)) cntsA where labeledRange = M.union . M.filter (not . T.null) . range hCounter (ks, ts) k = const $ k `M.member` ts ||@@ -448,10 +468,7 @@ else Counter v toHistogram cs hk rs = let ranges = M.mapWithKey- (\k l -> case M.lookup k cs of- Just v -> (l, v)- Nothing -> (l, 0.0)- ) rs+ (\k -> (, fromMaybe 0.0 (M.lookup k cs))) rs sums = let v1 = hk `T.append` "_sum" v2 = hk `T.append` "_cnt" withZeroLabel = return . ("",)@@ -463,42 +480,52 @@ in ranges `M.union` sums showPrometheusMetrics :: PrometheusMetrics -> L.ByteString-showPrometheusMetrics = L.fromStrict . T.encodeUtf8 . M.foldlWithKey- (\a k (h, m) -> T.concat [a, "# HELP ", k, " ", h, "\n"- , "# TYPE ", k, " ", showType m, "\n"- ,case m of- Counter v ->- T.concat [k, " ", T.pack $ show v, "\n"]- Gauge v ->- T.concat [k, " ", T.pack $ show v, "\n"]- Histogram h' -> fst $- M.foldlWithKey (showHistogram k)- ("", 0.0) h'- ]+showPrometheusMetrics = TL.encodeUtf8 . M.foldlWithKey+ (\a k (h, m) ->+ let k' = TL.fromStrict k+ in TL.concat [a, "# HELP ", k', " ", TL.fromStrict h, "\n"+ , "# TYPE ", k', " ", showType m, "\n"+ ,case m of+ Counter v -> TL.concat+ [k', " ", TL.pack $ show v, "\n"]+ Gauge v -> TL.concat+ [k', " ", TL.pack $ show v, "\n"]+ Histogram h' -> fst $+ M.foldlWithKey (showHistogram k k') ("", 0.0) h'+ ] ) "" where showType (Counter _) = "counter" showType (Gauge _) = "gauge" showType (Histogram _) = "histogram"- showHistogram k a@(t, n) c (l, v) =+ showHistogram k k' a@(t, n) c (l, v) = if T.null l then if k `T.append` "_sum" == c- then (T.concat [t, c, " ", T.pack $ show v, "\n"]+ then (TL.concat [t+ ,TL.fromStrict c+ ," "+ ,TL.pack $ show v+ ,"\n"+ ] ,n ) else if k `T.append` "_cnt" == c- then (T.concat [t, k, "_count "- ,T.pack $- show (round v :: Word64)- ,"\n"- ]+ then (TL.concat [t+ ,k'+ ,"_count "+ ,TL.pack $+ show (round v :: Word64)+ ,"\n"+ ] ,n ) else a else let n' = n + v- in (T.concat [t, k, "_bucket{le=\"", l, "\"} "- ,T.pack $ show (round n' :: Word64)- ,"\n"- ]+ in (TL.concat [t+ ,k'+ ,"_bucket{le=\"", TL.fromStrict l, "\"} "+ ,TL.pack $ show (round n' :: Word64)+ ,"\n"+ ] ,n' ) @@ -506,11 +533,17 @@ toPrometheusMetrics v = do let cs = fromJust $ readFromByteStringAsJSON @AllMetrtics v pc <- readIORef conf- return $ case pc of- Just c -> showPrometheusMetrics $ toPrometheusMetrics' c cs- Nothing -> ""+ return $ maybe "" (showPrometheusMetrics . flip toPrometheusMetrics' cs) pc ngxExportIOYY 'toPrometheusMetrics++text_plain :: ByteString+text_plain = "text/plain; version=0.0.4; charset=utf-8"++prometheusMetrics :: ByteString -> IO ContentHandlerResult+prometheusMetrics = fmap (, text_plain, 200, []) . toPrometheusMetrics++ngxExportAsyncHandler 'prometheusMetrics -- | Multiplies a floating point value by a factor. --
ngx-export-tools-extra.cabal view
@@ -1,5 +1,5 @@ name: ngx-export-tools-extra-version: 0.5.4.1+version: 0.5.5.0 synopsis: More extra tools for Nginx haskell module description: More extra tools for <https://github.com/lyokha/nginx-haskell-module Nginx haskell module>.