module Prometheus.Metric.Gauge (
Gauge
, gauge
, incGauge
, decGauge
, addGauge
, subGauge
, setGauge
, setGaugeToDuration
, getGauge
) where
import Prometheus.Info
import Prometheus.Metric
import Prometheus.Metric.Observer (timeAction)
import Prometheus.MonadMonitor
import Control.DeepSeq
import Control.Monad.IO.Class
import qualified Data.Atomics as Atomics
import qualified Data.ByteString.UTF8 as BS
import qualified Data.IORef as IORef
newtype Gauge = MkGauge (IORef.IORef Double)
instance NFData Gauge where
rnf (MkGauge ioref) = seq ioref ()
gauge :: Info -> Metric Gauge
gauge info = Metric $ do
ioref <- IORef.newIORef 0
return (MkGauge ioref, collectGauge info ioref)
withGauge :: MonadMonitor m
=> Gauge
-> (Double -> Double)
-> m ()
withGauge (MkGauge ioref) f =
doIO $ Atomics.atomicModifyIORefCAS_ ioref f
addGauge :: MonadMonitor m => Gauge -> Double -> m ()
addGauge g x = withGauge g add
where add i = i `seq` x `seq` i + x
subGauge :: MonadMonitor m => Gauge -> Double -> m ()
subGauge g x = withGauge g sub
where sub i = i `seq` x `seq` i - x
incGauge :: MonadMonitor m => Gauge -> m ()
incGauge g = withGauge g (+ 1)
decGauge :: MonadMonitor m => Gauge -> m ()
decGauge g = withGauge g (+ (-1))
setGauge :: MonadMonitor m => Gauge -> Double -> m ()
setGauge g r = withGauge g set
where set _ = r
getGauge :: MonadIO m => Gauge -> m Double
getGauge (MkGauge ioref) = liftIO $ IORef.readIORef ioref
setGaugeToDuration :: (MonadIO m, MonadMonitor m) => Gauge -> m a -> m a
setGaugeToDuration metric io = do
(result, duration) <- timeAction io
setGauge metric duration
return result
collectGauge :: Info -> IORef.IORef Double -> IO [SampleGroup]
collectGauge info c = do
value <- IORef.readIORef c
let sample = Sample (metricName info) [] (BS.fromString $ show value)
return [SampleGroup info GaugeType [sample]]