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) -- | Create a new gauge metric with a given name and help string. 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 -- | Adds a value to a gauge metric. addGauge :: MonadMonitor m => Double -> Metric Gauge -> m () addGauge x g = withGauge g add where add i = i `seq` x `seq` i + x -- | Subtracts a value from a gauge metric. subGauge :: MonadMonitor m => Double -> Metric Gauge -> m () subGauge x g = withGauge g sub where sub i = i `seq` x `seq` i - x -- | Increments a gauge metric by 1. incGauge :: MonadMonitor m => Metric Gauge -> m () incGauge g = withGauge g (+ 1) -- | Decrements a gauge metric by 1. decGauge :: MonadMonitor m => Metric Gauge -> m () decGauge g = withGauge g (+ (-1)) -- | Sets a gauge metric to a specific value. setGauge :: MonadMonitor m => Double -> Metric Gauge -> m () setGauge r g = withGauge g set where set _ = r -- | Retrieves the current value of a gauge metric. getGauge :: Metric Gauge -> IO Double getGauge (Metric {handle = MkGauge ioref}) = IORef.readIORef ioref -- | Sets a gauge metric to the duration in seconds of an IO action. 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]]