{-# language OverloadedStrings #-} module Prometheus.Export.Text ( exportMetricsAsText ) where import Prometheus.Info import Prometheus.Metric import Prometheus.Registry import Control.Monad.IO.Class import qualified Data.ByteString.Builder as Build import qualified Data.ByteString.Lazy as BS import Data.Foldable (foldMap) import Data.Monoid ((<>), mempty, mconcat) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Encoding as T -- $setup -- >>> :module +Prometheus -- >>> :set -XOverloadedStrings -- >>> unregisterAll -- | Export all registered metrics in the Prometheus 0.0.4 text exposition -- format. -- -- For the full specification of the format, see the official Prometheus -- . -- -- >>> :m +Data.ByteString -- >>> myCounter <- register $ counter (Info "my_counter" "Example counter") -- >>> incCounter myCounter -- >>> exportMetricsAsText >>= Data.ByteString.Lazy.putStr -- # HELP my_counter Example counter -- # TYPE my_counter counter -- my_counter 1.0 exportMetricsAsText :: MonadIO m => m BS.ByteString exportMetricsAsText = do samples <- collectMetrics return $ Build.toLazyByteString $ foldMap exportSampleGroup samples exportSampleGroup :: SampleGroup -> Build.Builder exportSampleGroup (SampleGroup info ty samples) = if null samples then mempty else prefix <> exportedSamples where exportedSamples = exportSamples samples name = metricName info help = metricHelp info prefix = Build.byteString $ T.encodeUtf8 $ T.unlines [ "# HELP " <> name <> " " <> T.concatMap escape help , "# TYPE " <> name <> " " <> T.pack (show ty) ] escape '\n' = "\\n" escape '\\' = "\\\\" escape other = T.pack [other] exportSamples :: [Sample] -> Build.Builder exportSamples samples = mconcat [ exportSample s <> Build.charUtf8 '\n' | s <- samples ] exportSample :: Sample -> Build.Builder exportSample (Sample name labels value) = Build.byteString (T.encodeUtf8 name) <> (case labels of [] -> mempty l:ls -> Build.charUtf8 '{' <> exportLabel l <> mconcat [ Build.charUtf8 ',' <> exportLabel l' | l' <- ls ] <> Build.charUtf8 '}') <> Build.charUtf8 ' ' <> Build.byteString value exportLabel :: (Text, Text) -> Build.Builder exportLabel (key, value) = Build.byteString (T.encodeUtf8 key) <> Build.charUtf8 '=' <> Build.stringUtf8 (show value)