module System.Metrics.Prometheus.Metric.Counter ( Counter, CounterSample (..), new, add, inc, sample, addAndSample, set, ) where import Control.Applicative ((<$>)) import Control.Monad (when) import Data.Atomics.Counter (AtomicCounter, incrCounter, newCounter, writeCounter) newtype Counter = Counter {unCounter :: AtomicCounter} newtype CounterSample = CounterSample {unCounterSample :: Int} new :: IO Counter new = Counter <$> newCounter 0 addAndSample :: Int -> Counter -> IO CounterSample addAndSample by | by >= 0 = fmap CounterSample . incrCounter by . unCounter | otherwise = error "must be >= 0" add :: Int -> Counter -> IO () add by c = addAndSample by c >> pure () inc :: Counter -> IO () inc = add 1 sample :: Counter -> IO CounterSample sample = addAndSample 0 -- | Write @i@ to the counter, if @i@ is more than the current value. This is -- useful for when the count is maintained by a separate system (e.g. GHC's GC -- counter). -- -- WARNING: For multiple writers, the most recent one wins, which may not -- preserve the increasing property. If you have stronger requirements than this, -- please check with the maintainers. -- See for discussion. set :: Int -> Counter -> IO () set i (Counter c) = writeCounter c i