{-|
Module      : Control.Monad.Metrics.Internal
Description : An easy interface to recording metrics.
Copyright   : (c) Matt Parsons, 2017
                  Taylor Fausak, 2016
License     : MIT
Maintainer  : parsonsmatt@gmail.com
Stability   : experimental
Portability : POSIX

This is an internal module. Depend upon it at your own risk -- breaking
changes in here will /not/ be reflected in the major API version.

-}
module Control.Monad.Metrics.Internal where

import           Data.HashMap.Strict         (HashMap)
import           Data.IORef
import           Data.Text                   (Text)
import           Lens.Micro                  (Lens')
import           System.Clock                (TimeSpec (..))
import           System.Metrics              (Store)
import           System.Metrics.Counter      (Counter)
import           System.Metrics.Distribution (Distribution)
import           System.Metrics.Gauge        (Gauge)
import           System.Metrics.Label        (Label)

-- | A container for metrics used by the 'MonadMetrics' class.
--
-- * /Since v0.1.0.0/
data Metrics = Metrics
    { Metrics -> IORef (HashMap Text Counter)
_metricsCounters      :: IORef (HashMap Text Counter)
    , Metrics -> IORef (HashMap Text Gauge)
_metricsGauges        :: IORef (HashMap Text Gauge)
    , Metrics -> IORef (HashMap Text Distribution)
_metricsDistributions :: IORef (HashMap Text Distribution)
    , Metrics -> IORef (HashMap Text Label)
_metricsLabels        :: IORef (HashMap Text Label)
    , Metrics -> Store
_metricsStore         :: Store
    }

-- | A lens into the 'Counter's provided by the 'Metrics'.
--
-- * /Since v0.1.0.0/
metricsCounters :: Lens' Metrics (IORef (HashMap Text Counter))
metricsCounters :: Lens' Metrics (IORef (HashMap Text Counter))
metricsCounters IORef (HashMap Text Counter) -> f (IORef (HashMap Text Counter))
f (Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l Store
s) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\IORef (HashMap Text Counter)
c' -> IORef (HashMap Text Counter)
-> IORef (HashMap Text Gauge)
-> IORef (HashMap Text Distribution)
-> IORef (HashMap Text Label)
-> Store
-> Metrics
Metrics IORef (HashMap Text Counter)
c' IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l Store
s) (IORef (HashMap Text Counter) -> f (IORef (HashMap Text Counter))
f IORef (HashMap Text Counter)
c)

-- | A lens into the 'Gauge's provided by the 'Metrics'.
--
-- * /Since v0.1.0.0/
metricsGauges :: Lens' Metrics (IORef (HashMap Text Gauge))
metricsGauges :: Lens' Metrics (IORef (HashMap Text Gauge))
metricsGauges IORef (HashMap Text Gauge) -> f (IORef (HashMap Text Gauge))
f (Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l Store
s) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\IORef (HashMap Text Gauge)
g' -> IORef (HashMap Text Counter)
-> IORef (HashMap Text Gauge)
-> IORef (HashMap Text Distribution)
-> IORef (HashMap Text Label)
-> Store
-> Metrics
Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g' IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l Store
s) (IORef (HashMap Text Gauge) -> f (IORef (HashMap Text Gauge))
f IORef (HashMap Text Gauge)
g)

-- | A lens into the 'Distribution's provided by the 'Metrics'.
--
-- * /Since v0.1.0.0/
metricsDistributions :: Lens' Metrics (IORef (HashMap Text Distribution))
metricsDistributions :: Lens' Metrics (IORef (HashMap Text Distribution))
metricsDistributions IORef (HashMap Text Distribution)
-> f (IORef (HashMap Text Distribution))
f (Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l Store
s) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\IORef (HashMap Text Distribution)
d' -> IORef (HashMap Text Counter)
-> IORef (HashMap Text Gauge)
-> IORef (HashMap Text Distribution)
-> IORef (HashMap Text Label)
-> Store
-> Metrics
Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d' IORef (HashMap Text Label)
l Store
s) (IORef (HashMap Text Distribution)
-> f (IORef (HashMap Text Distribution))
f IORef (HashMap Text Distribution)
d)

-- | A lens into the 'Label's provided by the 'Metrics'.
--
-- * /Since v0.1.0.0/
metricsLabels :: Lens' Metrics (IORef (HashMap Text Label))
metricsLabels :: Lens' Metrics (IORef (HashMap Text Label))
metricsLabels IORef (HashMap Text Label) -> f (IORef (HashMap Text Label))
f (Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l Store
s) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\IORef (HashMap Text Label)
l' -> IORef (HashMap Text Counter)
-> IORef (HashMap Text Gauge)
-> IORef (HashMap Text Distribution)
-> IORef (HashMap Text Label)
-> Store
-> Metrics
Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l' Store
s) (IORef (HashMap Text Label) -> f (IORef (HashMap Text Label))
f IORef (HashMap Text Label)
l)

-- | A lens into the 'Store' provided by the 'Metrics'.
--
-- * /Since v0.1.0.0/
metricsStore :: Lens' Metrics Store
metricsStore :: Lens' Metrics Store
metricsStore Store -> f Store
f (Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l Store
s) = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (IORef (HashMap Text Counter)
-> IORef (HashMap Text Gauge)
-> IORef (HashMap Text Distribution)
-> IORef (HashMap Text Label)
-> Store
-> Metrics
Metrics IORef (HashMap Text Counter)
c IORef (HashMap Text Gauge)
g IORef (HashMap Text Distribution)
d IORef (HashMap Text Label)
l) (Store -> f Store
f Store
s)

-- | A type representing the resolution of time to use for the 'timed'
-- metric.
--
-- * /Since v0.1.0.0/
data Resolution
    = Nanoseconds
    | Microseconds
    | Milliseconds
    | Seconds
    | Minutes
    | Hours
    | Days
    deriving (Resolution -> Resolution -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Resolution -> Resolution -> Bool
$c/= :: Resolution -> Resolution -> Bool
== :: Resolution -> Resolution -> Bool
$c== :: Resolution -> Resolution -> Bool
Eq, Int -> Resolution -> ShowS
[Resolution] -> ShowS
Resolution -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Resolution] -> ShowS
$cshowList :: [Resolution] -> ShowS
show :: Resolution -> String
$cshow :: Resolution -> String
showsPrec :: Int -> Resolution -> ShowS
$cshowsPrec :: Int -> Resolution -> ShowS
Show, Eq Resolution
Resolution -> Resolution -> Bool
Resolution -> Resolution -> Ordering
Resolution -> Resolution -> Resolution
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Resolution -> Resolution -> Resolution
$cmin :: Resolution -> Resolution -> Resolution
max :: Resolution -> Resolution -> Resolution
$cmax :: Resolution -> Resolution -> Resolution
>= :: Resolution -> Resolution -> Bool
$c>= :: Resolution -> Resolution -> Bool
> :: Resolution -> Resolution -> Bool
$c> :: Resolution -> Resolution -> Bool
<= :: Resolution -> Resolution -> Bool
$c<= :: Resolution -> Resolution -> Bool
< :: Resolution -> Resolution -> Bool
$c< :: Resolution -> Resolution -> Bool
compare :: Resolution -> Resolution -> Ordering
$ccompare :: Resolution -> Resolution -> Ordering
Ord, Int -> Resolution
Resolution -> Int
Resolution -> [Resolution]
Resolution -> Resolution
Resolution -> Resolution -> [Resolution]
Resolution -> Resolution -> Resolution -> [Resolution]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Resolution -> Resolution -> Resolution -> [Resolution]
$cenumFromThenTo :: Resolution -> Resolution -> Resolution -> [Resolution]
enumFromTo :: Resolution -> Resolution -> [Resolution]
$cenumFromTo :: Resolution -> Resolution -> [Resolution]
enumFromThen :: Resolution -> Resolution -> [Resolution]
$cenumFromThen :: Resolution -> Resolution -> [Resolution]
enumFrom :: Resolution -> [Resolution]
$cenumFrom :: Resolution -> [Resolution]
fromEnum :: Resolution -> Int
$cfromEnum :: Resolution -> Int
toEnum :: Int -> Resolution
$ctoEnum :: Int -> Resolution
pred :: Resolution -> Resolution
$cpred :: Resolution -> Resolution
succ :: Resolution -> Resolution
$csucc :: Resolution -> Resolution
Enum)

diffTime :: Resolution -> TimeSpec -> TimeSpec -> Double
diffTime :: Resolution -> TimeSpec -> TimeSpec -> Double
diffTime Resolution
res (TimeSpec Int64
seca Int64
nseca) (TimeSpec Int64
secb Int64
nsecb) =
    let sec' :: Int64
sec' = Int64
seca forall a. Num a => a -> a -> a
- Int64
secb
        nsec' :: Int64
nsec' = Int64
nseca forall a. Num a => a -> a -> a
- Int64
nsecb
     in Resolution -> TimeSpec -> Double
convertTimeSpecTo Resolution
res (Int64 -> Int64 -> TimeSpec
TimeSpec Int64
sec' Int64
nsec')

convertTimeSpecTo :: Resolution -> TimeSpec -> Double
convertTimeSpecTo :: Resolution -> TimeSpec -> Double
convertTimeSpecTo Resolution
res (TimeSpec Int64
secs' Int64
nsecs') =
    case Resolution
res of
        Resolution
Nanoseconds  -> Double
nsecs forall a. Num a => a -> a -> a
+ Double -> Double
sToNs Double
secs
        Resolution
Microseconds -> Double -> Double
nsToUs Double
nsecs forall a. Num a => a -> a -> a
+ Double -> Double
sToUs Double
secs
        Resolution
Milliseconds -> Double -> Double
nsToMs Double
nsecs forall a. Num a => a -> a -> a
+ Double -> Double
sToMs Double
secs
        Resolution
Seconds      -> Double -> Double
nsToS Double
nsecs forall a. Num a => a -> a -> a
+ Double
secs
        Resolution
Minutes      -> Double -> Double
sToMin (Double -> Double
nsToS Double
nsecs forall a. Num a => a -> a -> a
+ Double
secs)
        Resolution
Hours        -> Double -> Double
sToHour (Double -> Double
nsToS Double
nsecs forall a. Num a => a -> a -> a
+ Double
secs)
        Resolution
Days         -> Double -> Double
sToDay (Double -> Double
nsToS Double
nsecs forall a. Num a => a -> a -> a
+ Double
secs)
  where
    nsecs :: Double
nsecs = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
nsecs'
    secs :: Double
secs = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
secs'

nsToUs, nsToMs, nsToS, sToMin, sToHour, sToDay, sToNs, sToUs, sToMs :: Double -> Double
nsToUs :: Double -> Double
nsToUs = (forall a. Fractional a => a -> a -> a
/ Double
10forall a b. (Num a, Integral b) => a -> b -> a
^(Int
3 :: Int))
nsToMs :: Double -> Double
nsToMs = (forall a. Fractional a => a -> a -> a
/ Double
10forall a b. (Num a, Integral b) => a -> b -> a
^(Int
6 :: Int))
nsToS :: Double -> Double
nsToS = (forall a. Fractional a => a -> a -> a
/ Double
10forall a b. (Num a, Integral b) => a -> b -> a
^(Int
9 :: Int))
sToMin :: Double -> Double
sToMin = (forall a. Fractional a => a -> a -> a
/ Double
60)
sToHour :: Double -> Double
sToHour = Double -> Double
sToMin forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
sToMin
sToDay :: Double -> Double
sToDay = (forall a. Fractional a => a -> a -> a
/ Double
24) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
sToHour
sToNs :: Double -> Double
sToNs = (forall a. Num a => a -> a -> a
* Double
10forall a b. (Num a, Integral b) => a -> b -> a
^(Int
9 :: Int))
sToUs :: Double -> Double
sToUs = (forall a. Num a => a -> a -> a
* Double
10forall a b. (Num a, Integral b) => a -> b -> a
^(Int
6 :: Int))
sToMs :: Double -> Double
sToMs = (forall a. Num a => a -> a -> a
* Double
10forall a b. (Num a, Integral b) => a -> b -> a
^(Int
3 :: Int))