{-# LANGUAGE TypeFamilies, DataKinds, ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} module System.Metrics.ExtraTrackers ( Timestamp , TimerMagnitude(..) , Timer(..) , timed ) where import qualified Data.Text as T import Control.Monad.IO.Class import Data.Proxy import Data.Time.Clock.POSIX import Data.Typeable import GHC.TypeLits import System.CPUTime import System.Metrics import System.Metrics.Distribution as TD import System.Metrics.Label as TL import System.Metrics.Extensible newtype Timestamp = Timestamp Label instance TrackerLike Timestamp where type TrackAction Timestamp m = m () track metric = do Timestamp l <- getTracker metric liftIO $ do utc <- getCurrentTime TL.set l $ T.pack $ show utc createTracker name store = Timestamp <$> createLabel name store newtype Timer (magn :: TimerMagnitude) = Timer { getTimerDistribution :: Distribution } data TimerMagnitude = Msecs | Usecs | Nsecs deriving (Typeable) class MagnitudeOps (magn :: TimerMagnitude) where toString :: Proxy magn -> T.Text secFraction :: Proxy magn -> Double instance MagnitudeOps 'Msecs where toString _ = "ms" secFraction _ = 1e-3 instance MagnitudeOps 'Usecs where toString _ = "us" secFraction _ = 1e-6 instance MagnitudeOps 'Nsecs where toString _ = "ns" secFraction _ = 1e-9 instance (Typeable magn, MagnitudeOps magn) => TrackerLike (Timer magn) where type TrackAction (Timer magn) m = Double -> m () track metric timing = do Timer timer <- getTracker metric liftIO $ TD.add timer timing createTracker name store = Timer <$> createDistribution (name <> "_" <> toString (Proxy :: Proxy magn)) store -- Returns the number of picoseconds time :: MonadIO m => m a -> m (Integer, a) time act = do start <- liftIO getCPUTime res <- act end <- liftIO getCPUTime pure (end - start, res) timed :: forall m metric magn name a. (MonadMetrics m, KnownSymbol name, Typeable metric, Typeable magn, MagnitudeOps magn, Ord (metric (Timer magn) name)) => metric (Timer magn) name -> m a -> m a timed metric act = do (cpuTime, res) <- time act track metric $ fromIntegral cpuTime / (1e12 * secFraction (Proxy :: Proxy magn)) pure res