{-# 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
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)