{-# 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 = 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 :: forall (m :: * -> *) a.
(MonadIO m, HasInstrument m) =>
MetricName -> HostDimensionPolicy -> Dimensions -> m a -> m a
timeI MetricName
name HostDimensionPolicy
hostDimPolicy Dimensions
dims m a
act = do
  Instrument
i <- forall (m :: * -> *). HasInstrument m => m Instrument
getInstrument
  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 :: forall (m :: * -> *).
(MonadIO m, HasInstrument m) =>
MetricName -> HostDimensionPolicy -> Dimensions -> Double -> m ()
sampleI MetricName
name HostDimensionPolicy
hostDimPolicy Dimensions
dims Double
val =
  forall (m :: * -> *).
MonadIO m =>
MetricName
-> HostDimensionPolicy
-> Dimensions
-> Double
-> Instrument
-> m ()
I.sampleI MetricName
name HostDimensionPolicy
hostDimPolicy Dimensions
dims Double
val forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *). HasInstrument m => m Instrument
getInstrument

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

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