{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances  #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Instrument.ClientClass
-- Copyright   :  Soostone Inc
-- License     :  BSD3
--
-- Maintainer  :  Ozgun Ataman
-- Stability   :  experimental
--
-- This module mimics the functionality of Instrument.Client but
-- instead exposes a typeclass facilitated interface. Once you define
-- the typeclass for your application's main monad, you can call all
-- the mesaurement functions directly.
----------------------------------------------------------------------------

module Instrument.ClientClass
    ( I.Instrument
    , I.initInstrument
    , HasInstrument (..)
    , sampleI
    , timeI
    , countI
    , incrementI
    ) where

-------------------------------------------------------------------------------
import           Control.Monad.IO.Class
import           Control.Monad.Reader
-------------------------------------------------------------------------------
import qualified Instrument.Client      as I
import           Instrument.Types
-------------------------------------------------------------------------------


class HasInstrument m where
  getInstrument :: m I.Instrument

instance (Monad m) => HasInstrument (ReaderT I.Instrument m) where
  getInstrument :: ReaderT Instrument m Instrument
getInstrument = ReaderT Instrument m Instrument
forall r (m :: * -> *). MonadReader r m => m r
ask


-- | Run a monadic action while measuring its runtime
timeI :: (MonadIO m, HasInstrument m)
     => MetricName
     -> HostDimensionPolicy
     -> Dimensions
     -> m a
     -> m a
timeI :: MetricName -> HostDimensionPolicy -> Dimensions -> m a -> m a
timeI MetricName
name HostDimensionPolicy
hostDimPolicy Dimensions
dims m a
act = do
  Instrument
i <- m Instrument
forall (m :: * -> *). HasInstrument m => m Instrument
getInstrument
  MetricName
-> HostDimensionPolicy -> Dimensions -> Instrument -> m a -> m a
forall (m :: * -> *) a.
MonadIO m =>
MetricName
-> HostDimensionPolicy -> Dimensions -> Instrument -> m a -> m a
I.timeI MetricName
name HostDimensionPolicy
hostDimPolicy Dimensions
dims Instrument
i m a
act


-- | Record a measurement sample
sampleI :: (MonadIO m, HasInstrument m )
       => MetricName
       -> HostDimensionPolicy
       -> Dimensions
       -> Double
       -> m ()
sampleI :: MetricName -> HostDimensionPolicy -> Dimensions -> Double -> m ()
sampleI MetricName
name HostDimensionPolicy
hostDimPolicy Dimensions
dims Double
val =
  MetricName
-> HostDimensionPolicy
-> Dimensions
-> Double
-> Instrument
-> m ()
forall (m :: * -> *).
MonadIO m =>
MetricName
-> HostDimensionPolicy
-> Dimensions
-> Double
-> Instrument
-> m ()
I.sampleI MetricName
name HostDimensionPolicy
hostDimPolicy Dimensions
dims Double
val (Instrument -> m ()) -> m Instrument -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m Instrument
forall (m :: * -> *). HasInstrument m => m Instrument
getInstrument


-------------------------------------------------------------------------------
incrementI
  :: ( MonadIO m
     , HasInstrument m
     )
  => MetricName
  -> HostDimensionPolicy
  -> Dimensions
  -> m ()
incrementI :: MetricName -> HostDimensionPolicy -> Dimensions -> m ()
incrementI MetricName
m HostDimensionPolicy
hostDimPolicy Dimensions
dims =
  MetricName
-> HostDimensionPolicy -> Dimensions -> Instrument -> m ()
forall (m :: * -> *).
MonadIO m =>
MetricName
-> HostDimensionPolicy -> Dimensions -> Instrument -> m ()
I.incrementI MetricName
m HostDimensionPolicy
hostDimPolicy Dimensions
dims (Instrument -> m ()) -> m Instrument -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m Instrument
forall (m :: * -> *). HasInstrument m => m Instrument
getInstrument


-------------------------------------------------------------------------------
countI
  :: ( MonadIO m
     , HasInstrument m
     )
  => MetricName
  -> HostDimensionPolicy
  -> Dimensions
  -> Int
  -> m ()
countI :: MetricName -> HostDimensionPolicy -> Dimensions -> Int -> m ()
countI MetricName
m HostDimensionPolicy
hostDimPolicy Dimensions
dims Int
v =
  MetricName
-> HostDimensionPolicy -> Dimensions -> Int -> Instrument -> m ()
forall (m :: * -> *).
MonadIO m =>
MetricName
-> HostDimensionPolicy -> Dimensions -> Int -> Instrument -> m ()
I.countI MetricName
m HostDimensionPolicy
hostDimPolicy Dimensions
dims Int
v (Instrument -> m ()) -> m Instrument -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m Instrument
forall (m :: * -> *). HasInstrument m => m Instrument
getInstrument