\subsection{Cardano.BM.Data.Aggregated}
\label{code:Cardano.BM.Data.Aggregated}
%if style == newcode
\begin{code}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE StandaloneDeriving #-}
module Cardano.BM.Data.Aggregated
( Aggregated (..)
, Stats (..)
, BaseStats (..)
, EWMA (..)
, Measurable (..)
, showSI
, showUnits
, getInteger
, getDouble
, subtractMeasurable
, meanOfStats
, stdevOfStats
, stats2Text
, singletonStats
, updateAggregation
, ewma
) where
import GHC.Generics (Generic)
import Data.Aeson (FromJSON, ToJSON)
import Data.Scientific (fromFloatDigits)
import Data.Text (Text, pack)
import Data.Word (Word64)
import qualified Cardano.BM.Data.Severity as S
\end{code}
%endif
\subsubsection{Measurable}\label{code:Measurable}\index{Measurable}
A |Measurable| may consist of different types of values.
Time measurements are strict, so are |Bytes| which are externally measured.
The real or integral numeric values are lazily linked, so we can decide later
to drop them.
\begin{code}
data Measurable = Microseconds {-# UNPACK #-} !Word64
| Nanoseconds {-# UNPACK #-} !Word64
| Seconds {-# UNPACK #-} !Word64
| Bytes {-# UNPACK #-} !Word64
| PureD !Double
| PureI !Integer
| Severity S.Severity
deriving (Measurable -> Measurable -> Bool
(Measurable -> Measurable -> Bool)
-> (Measurable -> Measurable -> Bool) -> Eq Measurable
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Measurable -> Measurable -> Bool
$c/= :: Measurable -> Measurable -> Bool
== :: Measurable -> Measurable -> Bool
$c== :: Measurable -> Measurable -> Bool
Eq, ReadPrec [Measurable]
ReadPrec Measurable
Int -> ReadS Measurable
ReadS [Measurable]
(Int -> ReadS Measurable)
-> ReadS [Measurable]
-> ReadPrec Measurable
-> ReadPrec [Measurable]
-> Read Measurable
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Measurable]
$creadListPrec :: ReadPrec [Measurable]
readPrec :: ReadPrec Measurable
$creadPrec :: ReadPrec Measurable
readList :: ReadS [Measurable]
$creadList :: ReadS [Measurable]
readsPrec :: Int -> ReadS Measurable
$creadsPrec :: Int -> ReadS Measurable
Read, (forall x. Measurable -> Rep Measurable x)
-> (forall x. Rep Measurable x -> Measurable) -> Generic Measurable
forall x. Rep Measurable x -> Measurable
forall x. Measurable -> Rep Measurable x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Measurable x -> Measurable
$cfrom :: forall x. Measurable -> Rep Measurable x
Generic, [Measurable] -> Encoding
[Measurable] -> Value
Measurable -> Encoding
Measurable -> Value
(Measurable -> Value)
-> (Measurable -> Encoding)
-> ([Measurable] -> Value)
-> ([Measurable] -> Encoding)
-> ToJSON Measurable
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Measurable] -> Encoding
$ctoEncodingList :: [Measurable] -> Encoding
toJSONList :: [Measurable] -> Value
$ctoJSONList :: [Measurable] -> Value
toEncoding :: Measurable -> Encoding
$ctoEncoding :: Measurable -> Encoding
toJSON :: Measurable -> Value
$ctoJSON :: Measurable -> Value
ToJSON, Value -> Parser [Measurable]
Value -> Parser Measurable
(Value -> Parser Measurable)
-> (Value -> Parser [Measurable]) -> FromJSON Measurable
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Measurable]
$cparseJSONList :: Value -> Parser [Measurable]
parseJSON :: Value -> Parser Measurable
$cparseJSON :: Value -> Parser Measurable
FromJSON)
\end{code}
|Measurable| can be transformed to an integral value.
\begin{code}
instance Ord Measurable where
compare :: Measurable -> Measurable -> Ordering
compare (Seconds Word64
a) (Seconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a Word64
b
compare (Microseconds Word64
a) (Microseconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a Word64
b
compare (Nanoseconds Word64
a) (Nanoseconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a Word64
b
compare (Seconds Word64
a) (Microseconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64
a Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000) Word64
b
compare (Nanoseconds Word64
a) (Microseconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a (Word64
b Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000)
compare (Seconds Word64
a) (Nanoseconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64
a Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000) Word64
b
compare (Microseconds Word64
a) (Nanoseconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64
a Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000) Word64
b
compare (Microseconds Word64
a) (Seconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a (Word64
b Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000)
compare (Nanoseconds Word64
a) (Seconds Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a (Word64
b Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000)
compare (Bytes Word64
a) (Bytes Word64
b) = Word64 -> Word64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word64
a Word64
b
compare (PureD Double
a) (PureD Double
b) = Double -> Double -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Double
a Double
b
compare (PureI Integer
a) (PureI Integer
b) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a Integer
b
compare (Severity Severity
a) (Severity Severity
b) = Severity -> Severity -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Severity
a Severity
b
compare (PureI Integer
a) (Seconds Word64
b) | Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
b)
compare (PureI Integer
a) (Microseconds Word64
b) | Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
b)
compare (PureI Integer
a) (Nanoseconds Word64
b) | Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
b)
compare (PureI Integer
a) (Bytes Word64
b) | Integer
a Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
b)
compare (Seconds Word64
a) (PureI Integer
b) | Integer
b Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a) Integer
b
compare (Microseconds Word64
a) (PureI Integer
b) | Integer
b Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a) Integer
b
compare (Nanoseconds Word64
a) (PureI Integer
b) | Integer
b Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a) Integer
b
compare (Bytes Word64
a) (PureI Integer
b) | Integer
b Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a) Integer
b
compare a :: Measurable
a@(PureD Double
_) (PureI Integer
b) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Measurable -> Integer
getInteger Measurable
a) Integer
b
compare (PureI Integer
a) b :: Measurable
b@(PureD Double
_) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a (Measurable -> Integer
getInteger Measurable
b)
compare Measurable
_a Measurable
_b = Ordering
LT
\end{code}
|Measurable| can be transformed to an integral value.
\begin{code}
getInteger :: Measurable -> Integer
getInteger :: Measurable -> Integer
getInteger (Microseconds Word64
a) = Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a
getInteger (Nanoseconds Word64
a) = Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a
getInteger (Seconds Word64
a) = Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a
getInteger (Bytes Word64
a) = Word64 -> Integer
forall a. Integral a => a -> Integer
toInteger Word64
a
getInteger (PureI Integer
a) = Integer
a
getInteger (PureD Double
a) = Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round Double
a
getInteger (Severity Severity
a) = Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Severity -> Int
forall a. Enum a => a -> Int
fromEnum Severity
a)
\end{code}
|Measurable| can be transformed to a rational value.
\begin{code}
getDouble :: Measurable -> Double
getDouble :: Measurable -> Double
getDouble (Microseconds Word64
a) = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a
getDouble (Nanoseconds Word64
a) = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a
getDouble (Seconds Word64
a) = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a
getDouble (Bytes Word64
a) = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a
getDouble (PureI Integer
a) = Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
a
getDouble (PureD Double
a) = Double
a
getDouble (Severity Severity
a) = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Severity -> Int
forall a. Enum a => a -> Int
fromEnum Severity
a)
\end{code}
It is a numerical value, thus supports functions to operate on numbers.
\index{Measurable!instance of Num}
\begin{code}
instance Num Measurable where
+ :: Measurable -> Measurable -> Measurable
(+) (Microseconds Word64
a) (Microseconds Word64
b) = Word64 -> Measurable
Microseconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+Word64
b)
(+) (Nanoseconds Word64
a) (Nanoseconds Word64
b) = Word64 -> Measurable
Nanoseconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+Word64
b)
(+) (Seconds Word64
a) (Seconds Word64
b) = Word64 -> Measurable
Seconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+Word64
b)
(+) (Bytes Word64
a) (Bytes Word64
b) = Word64 -> Measurable
Bytes (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+Word64
b)
(+) (PureI Integer
a) (PureI Integer
b) = Integer -> Measurable
PureI (Integer
aInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
b)
(+) (PureD Double
a) (PureD Double
b) = Double -> Measurable
PureD (Double
aDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
b)
(+) Measurable
a Measurable
_ = Measurable
a
* :: Measurable -> Measurable -> Measurable
(*) (Microseconds Word64
a) (Microseconds Word64
b) = Word64 -> Measurable
Microseconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
*Word64
b)
(*) (Nanoseconds Word64
a) (Nanoseconds Word64
b) = Word64 -> Measurable
Nanoseconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
*Word64
b)
(*) (Seconds Word64
a) (Seconds Word64
b) = Word64 -> Measurable
Seconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
*Word64
b)
(*) (Bytes Word64
a) (Bytes Word64
b) = Word64 -> Measurable
Bytes (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
*Word64
b)
(*) (PureI Integer
a) (PureI Integer
b) = Integer -> Measurable
PureI (Integer
aInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
b)
(*) (PureD Double
a) (PureD Double
b) = Double -> Measurable
PureD (Double
aDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
b)
(*) Measurable
a Measurable
_ = Measurable
a
abs :: Measurable -> Measurable
abs (Microseconds Word64
a) = Word64 -> Measurable
Microseconds (Word64 -> Word64
forall a. Num a => a -> a
abs Word64
a)
abs (Nanoseconds Word64
a) = Word64 -> Measurable
Nanoseconds (Word64 -> Word64
forall a. Num a => a -> a
abs Word64
a)
abs (Seconds Word64
a) = Word64 -> Measurable
Seconds (Word64 -> Word64
forall a. Num a => a -> a
abs Word64
a)
abs (Bytes Word64
a) = Word64 -> Measurable
Bytes (Word64 -> Word64
forall a. Num a => a -> a
abs Word64
a)
abs (PureI Integer
a) = Integer -> Measurable
PureI (Integer -> Integer
forall a. Num a => a -> a
abs Integer
a)
abs (PureD Double
a) = Double -> Measurable
PureD (Double -> Double
forall a. Num a => a -> a
abs Double
a)
abs Measurable
a = Measurable
a
signum :: Measurable -> Measurable
signum (Microseconds Word64
a) = Word64 -> Measurable
Microseconds (Word64 -> Word64
forall a. Num a => a -> a
signum Word64
a)
signum (Nanoseconds Word64
a) = Word64 -> Measurable
Nanoseconds (Word64 -> Word64
forall a. Num a => a -> a
signum Word64
a)
signum (Seconds Word64
a) = Word64 -> Measurable
Seconds (Word64 -> Word64
forall a. Num a => a -> a
signum Word64
a)
signum (Bytes Word64
a) = Word64 -> Measurable
Bytes (Word64 -> Word64
forall a. Num a => a -> a
signum Word64
a)
signum (PureI Integer
a) = Integer -> Measurable
PureI (Integer -> Integer
forall a. Num a => a -> a
signum Integer
a)
signum (PureD Double
a) = Double -> Measurable
PureD (Double -> Double
forall a. Num a => a -> a
signum Double
a)
signum Measurable
a = Measurable
a
negate :: Measurable -> Measurable
negate (Microseconds Word64
a) = Word64 -> Measurable
Microseconds (Word64 -> Word64
forall a. Num a => a -> a
negate Word64
a)
negate (Nanoseconds Word64
a) = Word64 -> Measurable
Nanoseconds (Word64 -> Word64
forall a. Num a => a -> a
negate Word64
a)
negate (Seconds Word64
a) = Word64 -> Measurable
Seconds (Word64 -> Word64
forall a. Num a => a -> a
negate Word64
a)
negate (Bytes Word64
a) = Word64 -> Measurable
Bytes (Word64 -> Word64
forall a. Num a => a -> a
negate Word64
a)
negate (PureI Integer
a) = Integer -> Measurable
PureI (Integer -> Integer
forall a. Num a => a -> a
negate Integer
a)
negate (PureD Double
a) = Double -> Measurable
PureD (Double -> Double
forall a. Num a => a -> a
negate Double
a)
negate Measurable
a = Measurable
a
fromInteger :: Integer -> Measurable
fromInteger = Integer -> Measurable
PureI
subtractMeasurable :: Measurable -> Measurable -> Measurable
subtractMeasurable :: Measurable -> Measurable -> Measurable
subtractMeasurable (Microseconds Word64
a) (Microseconds Word64
b) = Word64 -> Measurable
Microseconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
b)
subtractMeasurable (Nanoseconds Word64
a) (Nanoseconds Word64
b) = Word64 -> Measurable
Nanoseconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
b)
subtractMeasurable (Seconds Word64
a) (Seconds Word64
b) = Word64 -> Measurable
Seconds (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
b)
subtractMeasurable (Bytes Word64
a) (Bytes Word64
b) = Word64 -> Measurable
Bytes (Word64
aWord64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
-Word64
b)
subtractMeasurable (PureI Integer
a) (PureI Integer
b) = Integer -> Measurable
PureI (Integer
aInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
b)
subtractMeasurable (PureD Double
a) (PureD Double
b) = Double -> Measurable
PureD (Double
aDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
b)
subtractMeasurable Measurable
a Measurable
_ = Measurable
a
\end{code}
Pretty printing of |Measurable|. \index{Measurable!instance of Show}
\begin{code}
instance Show Measurable where
show :: Measurable -> String
show v :: Measurable
v@(Microseconds Word64
a) = Word64 -> String
forall a. Show a => a -> String
show Word64
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
show v :: Measurable
v@(Nanoseconds Word64
a) = Word64 -> String
forall a. Show a => a -> String
show Word64
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
show v :: Measurable
v@(Seconds Word64
a) = Word64 -> String
forall a. Show a => a -> String
show Word64
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
show v :: Measurable
v@(Bytes Word64
a) = Word64 -> String
forall a. Show a => a -> String
show Word64
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
show v :: Measurable
v@(PureI Integer
a) = Integer -> String
forall a. Show a => a -> String
show Integer
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
show v :: Measurable
v@(PureD Double
a) = Double -> String
forall a. Show a => a -> String
show Double
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
show v :: Measurable
v@(Severity Severity
a) = Severity -> String
forall a. Show a => a -> String
show Severity
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
showUnits :: Measurable -> String
showUnits :: Measurable -> String
showUnits (Microseconds Word64
_) = String
" µs"
showUnits (Nanoseconds Word64
_) = String
" ns"
showUnits (Seconds Word64
_) = String
" s"
showUnits (Bytes Word64
_) = String
" B"
showUnits (PureI Integer
_) = String
""
showUnits (PureD Double
_) = String
""
showUnits (Severity Severity
_) = String
""
showSI :: Measurable -> String
showSI :: Measurable -> String
showSI (Microseconds Word64
a) = Scientific -> String
forall a. Show a => a -> String
show (Float -> Scientific
forall a. RealFloat a => a -> Scientific
fromFloatDigits ((Word64 -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
1000::Float) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
1000::Float))) String -> ShowS
forall a. [a] -> [a] -> [a]
++
Measurable -> String
showUnits (Word64 -> Measurable
Seconds Word64
a)
showSI (Nanoseconds Word64
a) = Scientific -> String
forall a. Show a => a -> String
show (Float -> Scientific
forall a. RealFloat a => a -> Scientific
fromFloatDigits ((Word64 -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
a) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
1000::Float) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
1000::Float) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
1000::Float))) String -> ShowS
forall a. [a] -> [a] -> [a]
++
Measurable -> String
showUnits (Word64 -> Measurable
Seconds Word64
a)
showSI v :: Measurable
v@(Seconds Word64
a) = Word64 -> String
forall a. Show a => a -> String
show Word64
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
showSI v :: Measurable
v@(Bytes Word64
a) = Word64 -> String
forall a. Show a => a -> String
show Word64
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
showSI v :: Measurable
v@(PureI Integer
a) = Integer -> String
forall a. Show a => a -> String
show Integer
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
showSI v :: Measurable
v@(PureD Double
a) = Double -> String
forall a. Show a => a -> String
show Double
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
showSI v :: Measurable
v@(Severity Severity
a) = Severity -> String
forall a. Show a => a -> String
show Severity
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits Measurable
v
\end{code}
\subsubsection{Stats}\label{code:Stats}\index{Stats}
A |Stats| statistics is strictly computed.
\begin{code}
data BaseStats = BaseStats {
BaseStats -> Measurable
fmin :: !Measurable,
BaseStats -> Measurable
fmax :: !Measurable,
BaseStats -> Word64
fcount :: {-# UNPACK #-} !Word64,
BaseStats -> Double
fsum_A :: {-# UNPACK #-} !Double,
BaseStats -> Double
fsum_B :: {-# UNPACK #-} !Double
} deriving (Int -> BaseStats -> ShowS
[BaseStats] -> ShowS
BaseStats -> String
(Int -> BaseStats -> ShowS)
-> (BaseStats -> String)
-> ([BaseStats] -> ShowS)
-> Show BaseStats
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BaseStats] -> ShowS
$cshowList :: [BaseStats] -> ShowS
show :: BaseStats -> String
$cshow :: BaseStats -> String
showsPrec :: Int -> BaseStats -> ShowS
$cshowsPrec :: Int -> BaseStats -> ShowS
Show, (forall x. BaseStats -> Rep BaseStats x)
-> (forall x. Rep BaseStats x -> BaseStats) -> Generic BaseStats
forall x. Rep BaseStats x -> BaseStats
forall x. BaseStats -> Rep BaseStats x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep BaseStats x -> BaseStats
$cfrom :: forall x. BaseStats -> Rep BaseStats x
Generic, [BaseStats] -> Encoding
[BaseStats] -> Value
BaseStats -> Encoding
BaseStats -> Value
(BaseStats -> Value)
-> (BaseStats -> Encoding)
-> ([BaseStats] -> Value)
-> ([BaseStats] -> Encoding)
-> ToJSON BaseStats
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [BaseStats] -> Encoding
$ctoEncodingList :: [BaseStats] -> Encoding
toJSONList :: [BaseStats] -> Value
$ctoJSONList :: [BaseStats] -> Value
toEncoding :: BaseStats -> Encoding
$ctoEncoding :: BaseStats -> Encoding
toJSON :: BaseStats -> Value
$ctoJSON :: BaseStats -> Value
ToJSON, Value -> Parser [BaseStats]
Value -> Parser BaseStats
(Value -> Parser BaseStats)
-> (Value -> Parser [BaseStats]) -> FromJSON BaseStats
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [BaseStats]
$cparseJSONList :: Value -> Parser [BaseStats]
parseJSON :: Value -> Parser BaseStats
$cparseJSON :: Value -> Parser BaseStats
FromJSON)
instance Eq BaseStats where
(BaseStats Measurable
mina Measurable
maxa Word64
counta Double
sumAa Double
sumBa) == :: BaseStats -> BaseStats -> Bool
== (BaseStats Measurable
minb Measurable
maxb Word64
countb Double
sumAb Double
sumBb) =
Measurable
mina Measurable -> Measurable -> Bool
forall a. Eq a => a -> a -> Bool
== Measurable
minb Bool -> Bool -> Bool
&& Measurable
maxa Measurable -> Measurable -> Bool
forall a. Eq a => a -> a -> Bool
== Measurable
maxb Bool -> Bool -> Bool
&& Word64
counta Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
countb Bool -> Bool -> Bool
&&
Double -> Double
forall a. Num a => a -> a
abs (Double
sumAa Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
sumAb) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1.0e-4 Bool -> Bool -> Bool
&&
Double -> Double
forall a. Num a => a -> a
abs (Double
sumBa Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
sumBb) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1.0e-4
data Stats = Stats {
Stats -> Measurable
flast :: !Measurable,
Stats -> Measurable
fold :: !Measurable,
Stats -> BaseStats
fbasic :: !BaseStats,
Stats -> BaseStats
fdelta :: !BaseStats,
Stats -> BaseStats
ftimed :: !BaseStats
} deriving (Int -> Stats -> ShowS
[Stats] -> ShowS
Stats -> String
(Int -> Stats -> ShowS)
-> (Stats -> String) -> ([Stats] -> ShowS) -> Show Stats
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Stats] -> ShowS
$cshowList :: [Stats] -> ShowS
show :: Stats -> String
$cshow :: Stats -> String
showsPrec :: Int -> Stats -> ShowS
$cshowsPrec :: Int -> Stats -> ShowS
Show, Stats -> Stats -> Bool
(Stats -> Stats -> Bool) -> (Stats -> Stats -> Bool) -> Eq Stats
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Stats -> Stats -> Bool
$c/= :: Stats -> Stats -> Bool
== :: Stats -> Stats -> Bool
$c== :: Stats -> Stats -> Bool
Eq, (forall x. Stats -> Rep Stats x)
-> (forall x. Rep Stats x -> Stats) -> Generic Stats
forall x. Rep Stats x -> Stats
forall x. Stats -> Rep Stats x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Stats x -> Stats
$cfrom :: forall x. Stats -> Rep Stats x
Generic, [Stats] -> Encoding
[Stats] -> Value
Stats -> Encoding
Stats -> Value
(Stats -> Value)
-> (Stats -> Encoding)
-> ([Stats] -> Value)
-> ([Stats] -> Encoding)
-> ToJSON Stats
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Stats] -> Encoding
$ctoEncodingList :: [Stats] -> Encoding
toJSONList :: [Stats] -> Value
$ctoJSONList :: [Stats] -> Value
toEncoding :: Stats -> Encoding
$ctoEncoding :: Stats -> Encoding
toJSON :: Stats -> Value
$ctoJSON :: Stats -> Value
ToJSON, Value -> Parser [Stats]
Value -> Parser Stats
(Value -> Parser Stats)
-> (Value -> Parser [Stats]) -> FromJSON Stats
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Stats]
$cparseJSONList :: Value -> Parser [Stats]
parseJSON :: Value -> Parser Stats
$cparseJSON :: Value -> Parser Stats
FromJSON)
\end{code}
\begin{code}
meanOfStats :: BaseStats -> Double
meanOfStats :: BaseStats -> Double
meanOfStats = BaseStats -> Double
fsum_A
\end{code}
\begin{code}
stdevOfStats :: BaseStats -> Double
stdevOfStats :: BaseStats -> Double
stdevOfStats BaseStats
s =
Word64 -> Double
calculate (BaseStats -> Word64
fcount BaseStats
s)
where
calculate :: Word64 -> Double
calculate :: Word64 -> Double
calculate Word64
n =
if Word64
n Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word64
2
then Double -> Double
forall a. Floating a => a -> a
sqrt (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ (BaseStats -> Double
fsum_B BaseStats
s) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Integer -> Double
forall a. Num a => Integer -> a
fromInteger (Integer -> Double) -> Integer -> Double
forall a b. (a -> b) -> a -> b
$ Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
n Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
1))
else Double
0
\end{code}
\index{Stats!instance of Semigroup}
\todo[inline]{|instance Semigroup Stats| disabled for the moment, because not needed.}
We use a parallel algorithm to update the estimation of mean and variance from two sample statistics.
(see \url{https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm})
\begin{spec}
instance Semigroup Stats where
(<>) a b = let counta = fcount a
countb = fcount b
newcount = counta + countb
delta = fsum_A b - fsum_A a
in
Stats { flast = flast b
, fmin = min (fmin a) (fmin b)
, fmax = max (fmax a) (fmax b)
, fcount = newcount
, fsum_A = fsum_A a + (delta / fromInteger newcount)
, fsum_B = fsum_B a + fsum_B b + (delta * delta) * (fromInteger (counta * countb) / fromInteger newcount)
}
\end{spec}
\label{code:stats2Text}\index{stats2Text}
\begin{code}
stats2Text :: Stats -> Text
stats2Text :: Stats -> Text
stats2Text (Stats Measurable
slast Measurable
_ BaseStats
sbasic BaseStats
sdelta BaseStats
stimed) =
String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
String
"{ last=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
forall a. Show a => a -> String
show Measurable
slast String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
", basic-stats=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ BaseStats -> String
showStats' (BaseStats
sbasic) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
", delta-stats=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ BaseStats -> String
showStats' (BaseStats
sdelta) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
", timed-stats=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ BaseStats -> String
showStats' (BaseStats
stimed) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
" }"
where
showStats' :: BaseStats -> String
showStats' :: BaseStats -> String
showStats' BaseStats
s =
String
", { min=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
forall a. Show a => a -> String
show (BaseStats -> Measurable
fmin BaseStats
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
", max=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
forall a. Show a => a -> String
show (BaseStats -> Measurable
fmax BaseStats
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
", mean=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show (BaseStats -> Double
meanOfStats BaseStats
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++ Measurable -> String
showUnits (BaseStats -> Measurable
fmin BaseStats
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
", std-dev=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show (BaseStats -> Double
stdevOfStats BaseStats
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
", count=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word64 -> String
forall a. Show a => a -> String
show (BaseStats -> Word64
fcount BaseStats
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++
String
" }"
\end{code}
\subsubsection{Exponentially Weighted Moving Average (EWMA)}\label{code:EWMA}\index{EWMA}
Following \url{https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average} we calculate
the exponential moving average for a series of values $ Y_t $ according to:
$$
S_t =
\begin{cases}
Y_1, & t = 1 \\
\alpha \cdot Y_t + (1 - \alpha) \cdot S_{t-1}, & t > 1
\end{cases}
$$
\begin{code}
data EWMA = EmptyEWMA { EWMA -> Double
alpha :: !Double }
| EWMA { alpha :: !Double
, EWMA -> Measurable
avg :: !Measurable
} deriving (Int -> EWMA -> ShowS
[EWMA] -> ShowS
EWMA -> String
(Int -> EWMA -> ShowS)
-> (EWMA -> String) -> ([EWMA] -> ShowS) -> Show EWMA
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EWMA] -> ShowS
$cshowList :: [EWMA] -> ShowS
show :: EWMA -> String
$cshow :: EWMA -> String
showsPrec :: Int -> EWMA -> ShowS
$cshowsPrec :: Int -> EWMA -> ShowS
Show, EWMA -> EWMA -> Bool
(EWMA -> EWMA -> Bool) -> (EWMA -> EWMA -> Bool) -> Eq EWMA
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EWMA -> EWMA -> Bool
$c/= :: EWMA -> EWMA -> Bool
== :: EWMA -> EWMA -> Bool
$c== :: EWMA -> EWMA -> Bool
Eq, (forall x. EWMA -> Rep EWMA x)
-> (forall x. Rep EWMA x -> EWMA) -> Generic EWMA
forall x. Rep EWMA x -> EWMA
forall x. EWMA -> Rep EWMA x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep EWMA x -> EWMA
$cfrom :: forall x. EWMA -> Rep EWMA x
Generic, [EWMA] -> Encoding
[EWMA] -> Value
EWMA -> Encoding
EWMA -> Value
(EWMA -> Value)
-> (EWMA -> Encoding)
-> ([EWMA] -> Value)
-> ([EWMA] -> Encoding)
-> ToJSON EWMA
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [EWMA] -> Encoding
$ctoEncodingList :: [EWMA] -> Encoding
toJSONList :: [EWMA] -> Value
$ctoJSONList :: [EWMA] -> Value
toEncoding :: EWMA -> Encoding
$ctoEncoding :: EWMA -> Encoding
toJSON :: EWMA -> Value
$ctoJSON :: EWMA -> Value
ToJSON, Value -> Parser [EWMA]
Value -> Parser EWMA
(Value -> Parser EWMA) -> (Value -> Parser [EWMA]) -> FromJSON EWMA
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [EWMA]
$cparseJSONList :: Value -> Parser [EWMA]
parseJSON :: Value -> Parser EWMA
$cparseJSON :: Value -> Parser EWMA
FromJSON)
\end{code}
\subsubsection{Aggregated}\label{code:Aggregated}\index{Aggregated}
\begin{code}
data Aggregated = AggregatedStats !Stats
| AggregatedEWMA !EWMA
deriving (Aggregated -> Aggregated -> Bool
(Aggregated -> Aggregated -> Bool)
-> (Aggregated -> Aggregated -> Bool) -> Eq Aggregated
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Aggregated -> Aggregated -> Bool
$c/= :: Aggregated -> Aggregated -> Bool
== :: Aggregated -> Aggregated -> Bool
$c== :: Aggregated -> Aggregated -> Bool
Eq, (forall x. Aggregated -> Rep Aggregated x)
-> (forall x. Rep Aggregated x -> Aggregated) -> Generic Aggregated
forall x. Rep Aggregated x -> Aggregated
forall x. Aggregated -> Rep Aggregated x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Aggregated x -> Aggregated
$cfrom :: forall x. Aggregated -> Rep Aggregated x
Generic, [Aggregated] -> Encoding
[Aggregated] -> Value
Aggregated -> Encoding
Aggregated -> Value
(Aggregated -> Value)
-> (Aggregated -> Encoding)
-> ([Aggregated] -> Value)
-> ([Aggregated] -> Encoding)
-> ToJSON Aggregated
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [Aggregated] -> Encoding
$ctoEncodingList :: [Aggregated] -> Encoding
toJSONList :: [Aggregated] -> Value
$ctoJSONList :: [Aggregated] -> Value
toEncoding :: Aggregated -> Encoding
$ctoEncoding :: Aggregated -> Encoding
toJSON :: Aggregated -> Value
$ctoJSON :: Aggregated -> Value
ToJSON, Value -> Parser [Aggregated]
Value -> Parser Aggregated
(Value -> Parser Aggregated)
-> (Value -> Parser [Aggregated]) -> FromJSON Aggregated
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Aggregated]
$cparseJSONList :: Value -> Parser [Aggregated]
parseJSON :: Value -> Parser Aggregated
$cparseJSON :: Value -> Parser Aggregated
FromJSON)
\end{code}
\index{Aggregated!instance of Semigroup}
\todo[inline]{|instance Semigroup Aggregated| disabled for the moment, because not needed.}
\begin{spec}
instance Semigroup Aggregated where
(<>) (AggregatedStats a) (AggregatedStats b) =
AggregatedStats (a <> b)
(<>) a _ = a
\end{spec}
\label{code:singletonStats}\index{singletonStats}
\begin{code}
singletonStats :: Measurable -> Aggregated
singletonStats :: Measurable -> Aggregated
singletonStats Measurable
a =
let stats :: Stats
stats = Stats :: Measurable
-> Measurable -> BaseStats -> BaseStats -> BaseStats -> Stats
Stats { flast :: Measurable
flast = Measurable
a
, fold :: Measurable
fold = Word64 -> Measurable
Nanoseconds Word64
0
, fbasic :: BaseStats
fbasic = BaseStats :: Measurable -> Measurable -> Word64 -> Double -> Double -> BaseStats
BaseStats
{ fmin :: Measurable
fmin = Measurable
a
, fmax :: Measurable
fmax = Measurable
a
, fcount :: Word64
fcount = Word64
1
, fsum_A :: Double
fsum_A = Measurable -> Double
getDouble Measurable
a
, fsum_B :: Double
fsum_B = Double
0 }
, fdelta :: BaseStats
fdelta = BaseStats :: Measurable -> Measurable -> Word64 -> Double -> Double -> BaseStats
BaseStats
{ fmin :: Measurable
fmin = Measurable
0
, fmax :: Measurable
fmax = Measurable
0
, fcount :: Word64
fcount = Word64
1
, fsum_A :: Double
fsum_A = Double
0
, fsum_B :: Double
fsum_B = Double
0 }
, ftimed :: BaseStats
ftimed = BaseStats :: Measurable -> Measurable -> Word64 -> Double -> Double -> BaseStats
BaseStats
{ fmin :: Measurable
fmin = Word64 -> Measurable
Nanoseconds Word64
0
, fmax :: Measurable
fmax = Word64 -> Measurable
Nanoseconds Word64
0
, fcount :: Word64
fcount = Word64
1
, fsum_A :: Double
fsum_A = Double
0
, fsum_B :: Double
fsum_B = Double
0 }
}
in
Stats -> Aggregated
AggregatedStats Stats
stats
\end{code}
\index{Aggregated!instance of Show}
\begin{code}
instance Show Aggregated where
show :: Aggregated -> String
show (AggregatedStats Stats
astats) =
String
"{ stats = " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Stats -> String
forall a. Show a => a -> String
show Stats
astats String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" }"
show (AggregatedEWMA EWMA
a) = EWMA -> String
forall a. Show a => a -> String
show EWMA
a
\end{code}
\subsubsection{Update aggregation}\label{code:updateAggregation}\index{updateAggregation}
We distinguish an unitialized from an already initialized aggregation. The latter is properly initialized.
\\
We use Welford's online algorithm to update the estimation of mean and variance of the sample statistics.
(see \url{https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_Online_algorithm})
\begin{code}
updateAggregation :: Measurable -> Aggregated -> Word64 -> Either Text Aggregated
updateAggregation :: Measurable -> Aggregated -> Word64 -> Either Text Aggregated
updateAggregation Measurable
v (AggregatedStats Stats
s) Word64
tstamp =
Aggregated -> Either Text Aggregated
forall a b. b -> Either a b
Right (Aggregated -> Either Text Aggregated)
-> Aggregated -> Either Text Aggregated
forall a b. (a -> b) -> a -> b
$ Stats -> Aggregated
AggregatedStats (Stats -> Aggregated) -> Stats -> Aggregated
forall a b. (a -> b) -> a -> b
$! Stats :: Measurable
-> Measurable -> BaseStats -> BaseStats -> BaseStats -> Stats
Stats { flast :: Measurable
flast = Measurable
v
, fold :: Measurable
fold = Measurable
mkTimestamp
, fbasic :: BaseStats
fbasic = Word64 -> Measurable -> BaseStats -> BaseStats
updateBaseStats Word64
1 Measurable
v (Stats -> BaseStats
fbasic Stats
s)
, fdelta :: BaseStats
fdelta = Word64 -> Measurable -> BaseStats -> BaseStats
updateBaseStats Word64
2 Measurable
deltav (Stats -> BaseStats
fdelta Stats
s)
, ftimed :: BaseStats
ftimed = Word64 -> Measurable -> BaseStats -> BaseStats
updateBaseStats Word64
2 Measurable
timediff (Stats -> BaseStats
ftimed Stats
s)
}
where
deltav :: Measurable
deltav = Measurable -> Measurable -> Measurable
subtractMeasurable Measurable
v (Stats -> Measurable
flast Stats
s)
mkTimestamp :: Measurable
mkTimestamp = Word64 -> Measurable
Nanoseconds (Word64 -> Measurable) -> Word64 -> Measurable
forall a b. (a -> b) -> a -> b
$ Word64
tstamp
timediff :: Measurable
timediff = Word64 -> Measurable
Nanoseconds (Word64 -> Measurable) -> Word64 -> Measurable
forall a b. (a -> b) -> a -> b
$ Integer -> Word64
forall a. Num a => Integer -> a
fromInteger (Integer -> Word64) -> Integer -> Word64
forall a b. (a -> b) -> a -> b
$ (Measurable -> Integer
getInteger Measurable
mkTimestamp) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- (Measurable -> Integer
getInteger (Measurable -> Integer) -> Measurable -> Integer
forall a b. (a -> b) -> a -> b
$ Stats -> Measurable
fold Stats
s)
updateAggregation Measurable
v (AggregatedEWMA EWMA
e) Word64
_ =
let !eitherAvg :: Either Text EWMA
eitherAvg = EWMA -> Measurable -> Either Text EWMA
ewma EWMA
e Measurable
v
in
EWMA -> Aggregated
AggregatedEWMA (EWMA -> Aggregated) -> Either Text EWMA -> Either Text Aggregated
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either Text EWMA
eitherAvg
updateBaseStats :: Word64 -> Measurable -> BaseStats -> BaseStats
updateBaseStats :: Word64 -> Measurable -> BaseStats -> BaseStats
updateBaseStats Word64
startAt Measurable
v BaseStats
s =
let newcount :: Word64
newcount = BaseStats -> Word64
fcount BaseStats
s Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1 in
if (Word64
startAt Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
newcount)
then BaseStats
s {fcount :: Word64
fcount = BaseStats -> Word64
fcount BaseStats
s Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1}
else
let newcountRel :: Word64
newcountRel = Word64
newcount Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
startAt Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1
newvalue :: Double
newvalue = Measurable -> Double
getDouble Measurable
v
delta :: Double
delta = Double
newvalue Double -> Double -> Double
forall a. Num a => a -> a -> a
- BaseStats -> Double
fsum_A BaseStats
s
dincr :: Double
dincr = (Double
delta Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
newcountRel)
delta2 :: Double
delta2 = Double
newvalue Double -> Double -> Double
forall a. Num a => a -> a -> a
- BaseStats -> Double
fsum_A BaseStats
s Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
dincr
(Measurable
minim, Measurable
maxim) =
if Word64
startAt Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
newcount
then (Measurable
v, Measurable
v)
else (Measurable -> Measurable -> Measurable
forall a. Ord a => a -> a -> a
min Measurable
v (BaseStats -> Measurable
fmin BaseStats
s), Measurable -> Measurable -> Measurable
forall a. Ord a => a -> a -> a
max Measurable
v (BaseStats -> Measurable
fmax BaseStats
s))
in
BaseStats :: Measurable -> Measurable -> Word64 -> Double -> Double -> BaseStats
BaseStats { fmin :: Measurable
fmin = Measurable
minim
, fmax :: Measurable
fmax = Measurable
maxim
, fcount :: Word64
fcount = Word64
newcount
, fsum_A :: Double
fsum_A = BaseStats -> Double
fsum_A BaseStats
s Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
dincr
, fsum_B :: Double
fsum_B = BaseStats -> Double
fsum_B BaseStats
s Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
delta Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
delta2)
}
\end{code}
\subsubsection{Calculation of EWMA}\label{code:ewma}\index{ewma}
Following \url{https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average} we calculate
the exponential moving average for a series of values $ Y_t $ according to:
$$
S_t =
\begin{cases}
Y_1, & t = 1 \\
\alpha \cdot Y_t + (1 - \alpha) \cdot S_{t-1}, & t > 1
\end{cases}
$$
\\
The pattern matching below ensures that the |EWMA| will start with the first value passed in,
and will not change type, once determined.
\begin{code}
ewma :: EWMA -> Measurable -> Either Text EWMA
ewma :: EWMA -> Measurable -> Either Text EWMA
ewma (EmptyEWMA Double
a) Measurable
v = EWMA -> Either Text EWMA
forall a b. b -> Either a b
Right (EWMA -> Either Text EWMA) -> EWMA -> Either Text EWMA
forall a b. (a -> b) -> a -> b
$ Double -> Measurable -> EWMA
EWMA Double
a Measurable
v
ewma (EWMA Double
a s :: Measurable
s@(Microseconds Word64
_)) y :: Measurable
y@(Microseconds Word64
_) =
EWMA -> Either Text EWMA
forall a b. b -> Either a b
Right (EWMA -> Either Text EWMA) -> EWMA -> Either Text EWMA
forall a b. (a -> b) -> a -> b
$ Double -> Measurable -> EWMA
EWMA Double
a (Measurable -> EWMA) -> Measurable -> EWMA
forall a b. (a -> b) -> a -> b
$ Word64 -> Measurable
Microseconds (Word64 -> Measurable) -> Word64 -> Measurable
forall a b. (a -> b) -> a -> b
$ Double -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Word64) -> Double -> Word64
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Measurable -> Double
getDouble Measurable
y) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Measurable -> Double
getDouble Measurable
s)
ewma (EWMA Double
a s :: Measurable
s@(Seconds Word64
_)) y :: Measurable
y@(Seconds Word64
_) =
EWMA -> Either Text EWMA
forall a b. b -> Either a b
Right (EWMA -> Either Text EWMA) -> EWMA -> Either Text EWMA
forall a b. (a -> b) -> a -> b
$ Double -> Measurable -> EWMA
EWMA Double
a (Measurable -> EWMA) -> Measurable -> EWMA
forall a b. (a -> b) -> a -> b
$ Word64 -> Measurable
Seconds (Word64 -> Measurable) -> Word64 -> Measurable
forall a b. (a -> b) -> a -> b
$ Double -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Word64) -> Double -> Word64
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Measurable -> Double
getDouble Measurable
y) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Measurable -> Double
getDouble Measurable
s)
ewma (EWMA Double
a s :: Measurable
s@(Bytes Word64
_)) y :: Measurable
y@(Bytes Word64
_) =
EWMA -> Either Text EWMA
forall a b. b -> Either a b
Right (EWMA -> Either Text EWMA) -> EWMA -> Either Text EWMA
forall a b. (a -> b) -> a -> b
$ Double -> Measurable -> EWMA
EWMA Double
a (Measurable -> EWMA) -> Measurable -> EWMA
forall a b. (a -> b) -> a -> b
$ Word64 -> Measurable
Bytes (Word64 -> Measurable) -> Word64 -> Measurable
forall a b. (a -> b) -> a -> b
$ Double -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Word64) -> Double -> Word64
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Measurable -> Double
getDouble Measurable
y) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Measurable -> Double
getDouble Measurable
s)
ewma (EWMA Double
a (PureI Integer
s)) (PureI Integer
y) =
EWMA -> Either Text EWMA
forall a b. b -> Either a b
Right (EWMA -> Either Text EWMA) -> EWMA -> Either Text EWMA
forall a b. (a -> b) -> a -> b
$ Double -> Measurable -> EWMA
EWMA Double
a (Measurable -> EWMA) -> Measurable -> EWMA
forall a b. (a -> b) -> a -> b
$ Integer -> Measurable
PureI (Integer -> Measurable) -> Integer -> Measurable
forall a b. (a -> b) -> a -> b
$ Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> Integer) -> Double -> Integer
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
y) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Integer -> Double
forall a. Num a => Integer -> a
fromInteger Integer
s)
ewma (EWMA Double
a (PureD Double
s)) (PureD Double
y) =
EWMA -> Either Text EWMA
forall a b. b -> Either a b
Right (EWMA -> Either Text EWMA) -> EWMA -> Either Text EWMA
forall a b. (a -> b) -> a -> b
$ Double -> Measurable -> EWMA
EWMA Double
a (Measurable -> EWMA) -> Measurable -> EWMA
forall a b. (a -> b) -> a -> b
$ Double -> Measurable
PureD (Double -> Measurable) -> Double -> Measurable
forall a b. (a -> b) -> a -> b
$ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
s
ewma EWMA
_ Measurable
_ = Text -> Either Text EWMA
forall a b. a -> Either a b
Left Text
"EWMA: Cannot compute average on values of different types"
\end{code}