module System.Metrics.Prometheus.Encode.Text (
    encodeMetrics,
) where

import Data.ByteString.Builder (Builder)
import Data.Function (on)
import Data.List (
    groupBy,
    intersperse,
 )
import qualified Data.Map as Map
import Data.Monoid ((<>))

import System.Metrics.Prometheus.Encode.Text.Histogram (encodeHistogram)
import System.Metrics.Prometheus.Encode.Text.MetricId (
    encodeDouble,
    encodeHeader,
    encodeInt,
    encodeMetricId,
    newline,
    space,
 )
import System.Metrics.Prometheus.Metric (
    MetricSample (..),
    metricSample,
 )
import System.Metrics.Prometheus.Metric.Counter (CounterSample (..))
import System.Metrics.Prometheus.Metric.Gauge (GaugeSample (..))
import System.Metrics.Prometheus.MetricId (MetricId (..))
import System.Metrics.Prometheus.Registry (RegistrySample (..))


encodeMetrics :: RegistrySample -> Builder
encodeMetrics :: RegistrySample -> Builder
encodeMetrics =
    (forall a. Semigroup a => a -> a -> a
<> Builder
newline) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a] -> [a]
intersperse Builder
newline forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map [(MetricId, MetricSample)] -> Builder
encodeMetricGroup
        forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {b}. [(MetricId, b)] -> [[(MetricId, b)]]
groupByName
        forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Map k a -> [(k, a)]
Map.toList
        forall b c a. (b -> c) -> (a -> b) -> a -> c
. RegistrySample -> Map MetricId MetricSample
unRegistrySample
  where
    groupByName :: [(MetricId, b)] -> [[(MetricId, b)]]
groupByName = forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (MetricId -> Name
name forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst))


encodeMetricGroup :: [(MetricId, MetricSample)] -> Builder
encodeMetricGroup :: [(MetricId, MetricSample)] -> Builder
encodeMetricGroup [(MetricId, MetricSample)]
group =
    MetricId -> MetricSample -> Builder
encodeHeader MetricId
mid MetricSample
sample forall a. Semigroup a => a -> a -> a
<> Builder
newline
        forall a. Semigroup a => a -> a -> a
<> forall a. Monoid a => [a] -> a
mconcat (forall a. a -> [a] -> [a]
intersperse Builder
newline forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (MetricId, MetricSample) -> Builder
encodeMetric [(MetricId, MetricSample)]
group)
  where
    (MetricId
mid, MetricSample
sample) = forall a. [a] -> a
head [(MetricId, MetricSample)]
group


encodeMetric :: (MetricId, MetricSample) -> Builder
encodeMetric :: (MetricId, MetricSample) -> Builder
encodeMetric (MetricId
mid, MetricSample
sample) =
    forall a.
(CounterSample -> a)
-> (GaugeSample -> a)
-> (HistogramSample -> a)
-> (SummarySample -> a)
-> MetricSample
-> a
metricSample
        (MetricId -> CounterSample -> Builder
encodeCounter MetricId
mid)
        (MetricId -> GaugeSample -> Builder
encodeGauge MetricId
mid)
        (MetricId -> HistogramSample -> Builder
encodeHistogram MetricId
mid)
        (forall {a}. a
encodeSummary MetricId
mid)
        MetricSample
sample
  where
    encodeSummary :: a
encodeSummary = forall a. HasCallStack => a
undefined


encodeCounter :: MetricId -> CounterSample -> Builder
encodeCounter :: MetricId -> CounterSample -> Builder
encodeCounter MetricId
mid CounterSample
counter = MetricId -> Builder
encodeMetricId MetricId
mid forall a. Semigroup a => a -> a -> a
<> Builder
space forall a. Semigroup a => a -> a -> a
<> Int -> Builder
encodeInt (CounterSample -> Int
unCounterSample CounterSample
counter)


encodeGauge :: MetricId -> GaugeSample -> Builder
encodeGauge :: MetricId -> GaugeSample -> Builder
encodeGauge MetricId
mid GaugeSample
gauge = MetricId -> Builder
encodeMetricId MetricId
mid forall a. Semigroup a => a -> a -> a
<> Builder
space forall a. Semigroup a => a -> a -> a
<> forall f. RealFloat f => f -> Builder
encodeDouble (GaugeSample -> Double
unGaugeSample GaugeSample
gauge)