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 qualified Data.Atomics as Atomics
import qualified Data.ByteString.UTF8 as BS
import qualified Data.IORef as IORef
newtype Gauge = MkGauge (IORef.IORef Double)
gauge :: Info -> IO (Metric Gauge)
gauge info = do
ioref <- IORef.newIORef 0
return Metric {
handle = MkGauge ioref
, collect = collectGauge info ioref
}
withGauge :: MonadMonitor m
=> Metric Gauge
-> (Double -> Double)
-> m ()
withGauge (Metric {handle = MkGauge ioref}) f =
doIO $ Atomics.atomicModifyIORefCAS_ ioref f
addGauge :: MonadMonitor m => Double -> Metric Gauge -> m ()
addGauge x g = withGauge g add
where add i = i `seq` x `seq` i + x
subGauge :: MonadMonitor m => Double -> Metric Gauge -> m ()
subGauge x g = withGauge g sub
where sub i = i `seq` x `seq` i x
incGauge :: MonadMonitor m => Metric Gauge -> m ()
incGauge g = withGauge g (+ 1)
decGauge :: MonadMonitor m => Metric Gauge -> m ()
decGauge g = withGauge g (+ (1))
setGauge :: MonadMonitor m => Double -> Metric Gauge -> m ()
setGauge r g = withGauge g set
where set _ = r
getGauge :: Metric Gauge -> IO Double
getGauge (Metric {handle = MkGauge ioref}) = IORef.readIORef ioref
setGaugeToDuration :: IO a -> Metric Gauge -> IO a
setGaugeToDuration io metric = do
(result, duration) <- timeAction io
setGauge duration metric
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]]