module Data.Metrics.Meter (
Meter,
meter,
mark,
mark',
mkMeter,
fromMeter,
module Data.Metrics.Types
) where
import Control.Lens
import Control.Monad.Base
import Control.Monad.Primitive
import Data.Primitive.MutVar
import Data.Time.Clock
import Data.Time.Clock.POSIX
import qualified Data.HashMap.Strict as H
import Data.Metrics.Internal
import qualified Data.Metrics.Meter.Internal as P
import qualified Data.Metrics.MovingAverage as A
import qualified Data.Metrics.MovingAverage.ExponentiallyWeighted as EWMA
import Data.Metrics.Types
data Meter m = Meter
{ fromMeter :: !(MV m P.Meter)
, meterGetSeconds :: !(m NominalDiffTime)
}
instance Rate IO IO (Meter IO) where
oneMinuteRate m = liftBase $ do
t <- meterGetSeconds m
updateAndApplyToRef (fromMeter m) (P.tickIfNecessary t) (A.rate . P.oneMinuteAverage)
fiveMinuteRate m = liftBase $ do
t <- meterGetSeconds m
updateAndApplyToRef (fromMeter m) (P.tickIfNecessary t) (A.rate . P.fiveMinuteAverage)
fifteenMinuteRate m = liftBase $ do
t <- meterGetSeconds m
updateAndApplyToRef (fromMeter m) (P.tickIfNecessary t) (A.rate . P.fifteenMinuteAverage)
meanRate m = liftBase $ do
t <- meterGetSeconds m
m' <- readMutVar (fromMeter m)
applyWithRef (fromMeter m) $ P.meanRate t
instance (MonadBase b m, PrimMonad m) => Count b m (Meter m) where
count = fmap (view P.count) . readMutVar . fromMeter
mark' :: PrimMonad m => Meter m -> Int -> m ()
mark' m x = do
t <- meterGetSeconds m
updateRef (fromMeter m) (P.mark t x)
mark :: PrimMonad m => Meter m -> m ()
mark = flip mark' 1
meter :: IO (Meter IO)
meter = mkMeter getPOSIXTime
mkMeter :: PrimMonad m => m NominalDiffTime -> m (Meter m)
mkMeter m = do
t <- m
v <- newMutVar $ ewmaMeter t
return $! Meter v m
ewmaMeter :: NominalDiffTime
-> P.Meter
ewmaMeter = P.meterData 5 EWMA.movingAverage