{-# LANGUAGE OverloadedStrings #-}

module System.Metrics.Prometheus.Http.Push
       ( pushHttpTextMetrics
       )
       where

import           Control.Concurrent                    (threadDelay)
import           Control.Monad                         (forever)
import           Data.ByteString.Builder               (toLazyByteString)
import           Data.Map                              (foldMapWithKey)
import           Data.Text                             (Text, unpack)
import           Network.HTTP.Client                   (Request,
                                                        RequestBody (..),
                                                        requestBody,
                                                        requestHeaders)
import           Network.HTTP.Types                    (hContentType)
import           Network.Wreq.Session                  (newSession, put)
import           Network.Wreq.Types                    (Putable (..))

import           System.Metrics.Prometheus.Encode.Text (encodeMetrics)
import           System.Metrics.Prometheus.MetricId    (Labels (..))
import           System.Metrics.Prometheus.Registry    (RegistrySample)


-- | Push text metrics to a pushgateway.
pushHttpTextMetrics :: String            -- ^ The base URL of the pushgateway, including the port number.
                    -> Text              -- ^ The name of this job.
                    -> Labels            -- ^ The label set to use as a grouping key for these metrics.
                    -> Int               -- ^ Push frequency, in microseconds.
                    -> IO RegistrySample -- ^ The action to get the latest metrics.
                    -> IO ()
pushHttpTextMetrics base job (Labels ls) frequency getSample = do
    session <- newSession
    forever $ getSample >>= put session url >> threadDelay frequency
  where
    url = base ++ "/metrics/job/" ++ unpack job ++
        foldMapWithKey (\k v -> "/" ++ unpack k ++ "/" ++ unpack v) ls


instance Putable RegistrySample where
    putPayload = (pure .) . metricsRequest


metricsRequest :: RegistrySample -> Request -> Request
metricsRequest s req = req
    { requestBody    = RequestBodyLBS . toLazyByteString $ encodeMetrics s
    , requestHeaders = contentType : requestHeaders req
    }
  where contentType = (hContentType, "text/plain; version=0.0.4")