module Ceilometer.Fold
(
Known(..)
, FoldResult(..)
, foldCPU
, foldDiskRead
, foldDiskWrite
, foldNeutronRx
, foldNeutronTx
, foldVolume
, foldSSD
, foldImage
, foldImagePollster
, foldInstanceFlavor
, foldInstanceVCPU
, foldInstanceRAM
, foldInstanceDisk
, foldIP
, foldSnapshot
, timewrapFold
) where
import qualified Control.Foldl as L
import Control.Lens hiding (Fold, Simple)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M
import Data.Word
import Ceilometer.Types
import Vaultaire.Types
data FoldResult
= RSingle !Word64
| RMapNum32 !(Map PFValue32 Word64)
| RMapNum64 !(Map PFValue64 Word64)
| RMapText !(Map PFValueText Word64)
class Known a where
mkPrism :: Env -> APrism' Word64 a
mkFold :: Env -> L.Fold (Timed a) FoldResult
instance Known PDCPU where
mkPrism _ = prSimple . pdCPU
mkFold _ = fmap RSingle (timewrapFold foldCPU)
instance Known PDDiskRead where
mkPrism _ = prSimple . pdDiskRead
mkFold _ = fmap RSingle (timewrapFold foldDiskRead)
instance Known PDDiskWrite where
mkPrism _ = prSimple . pdDiskWrite
mkFold _ = fmap RSingle (timewrapFold foldDiskWrite)
instance Known PDNeutronTx where
mkPrism _ = prSimple . pdNeutronTx
mkFold _ = fmap RSingle (timewrapFold foldNeutronTx)
instance Known PDNeutronRx where
mkPrism _ = prSimple . pdNeutronRx
mkFold _ = fmap RSingle (timewrapFold foldNeutronRx)
instance Known PDImagePollster where
mkPrism _ = prSimple . pdImagePollster
mkFold _ = fmap RMapNum64 foldImagePollster
instance Known PDVolume where
mkPrism _ = prCompoundEvent . pdVolume
mkFold (Env _ _ _ (TimeStamp s) (TimeStamp e))
= fmap RSingle (foldVolume (s,e))
instance Known PDSSD where
mkPrism _ = prCompoundEvent . pdSSD
mkFold (Env _ _ _ (TimeStamp s) (TimeStamp e))
= fmap RSingle (foldSSD (s,e))
instance Known PDImage where
mkPrism _ = prCompoundEvent . pdImage
mkFold (Env _ _ _ (TimeStamp s) (TimeStamp e))
= fmap RSingle (foldImage (s,e))
instance Known PDSnapshot where
mkPrism _ = prCompoundEvent . pdSnapshot
mkFold (Env _ _ _ (TimeStamp s) (TimeStamp e))
= fmap RSingle (foldSnapshot (s,e))
instance Known PDIP where
mkPrism _ = prCompoundEvent . pdIP
mkFold (Env _ _ _ (TimeStamp s) (TimeStamp e))
= fmap RSingle (foldIP (s,e))
instance Known PDInstanceVCPU where
mkPrism _ = prCompoundPollster . pdInstanceVCPU
mkFold (Env _ _ f _ _) = fmap RMapNum32
$ foldInstanceVCPU
$ filterByInstanceStatus f (\(PDInstanceVCPU s _) -> s)
instance Known PDInstanceRAM where
mkPrism _ = prCompoundPollster . pdInstanceRAM
mkFold (Env _ _ f _ _) = fmap RMapNum32
$ foldInstanceRAM
$ filterByInstanceStatus f (\(PDInstanceRAM s _) -> s)
instance Known PDInstanceDisk where
mkPrism _ = prCompoundPollster . pdInstanceDisk
mkFold (Env _ _ f _ _) = fmap RMapNum32
$ foldInstanceDisk
$ filterByInstanceStatus f (\(PDInstanceDisk s _) -> s)
instance Known PDInstanceFlavor where
mkPrism (Env fm _ _ _ _) = prCompoundPollster . pdInstanceFlavor fm
mkFold (Env _ _ f _ _) = fmap RMapText
$ foldInstanceFlavor
$ filterByInstanceStatus f (\(PDInstanceFlavor s _) -> s)
foldCPU :: L.Fold PDCPU Word64
foldCPU = L.Fold sCumulative bCumulative eCumulative
foldDiskRead :: L.Fold PDDiskRead Word64
foldDiskRead = L.Fold sCumulative bCumulative eCumulative
foldDiskWrite :: L.Fold PDDiskWrite Word64
foldDiskWrite = L.Fold sCumulative bCumulative eCumulative
foldNeutronTx :: L.Fold PDNeutronTx Word64
foldNeutronTx = L.Fold sCumulative bCumulative eCumulative
foldNeutronRx :: L.Fold PDNeutronRx Word64
foldNeutronRx = L.Fold sCumulative bCumulative eCumulative
foldVolume :: Window -> L.Fold (Timed PDVolume) Word64
foldVolume window = L.Fold step bEvent (eEvent window standardEventFolder)
where step (prev, acc) (Timed end (PDVolume _ VolumeDelete _ _)) = (Nothing, go end acc prev)
step a x = sEvent window a x
go end acc (Just x) = insertVal x (end x ^. time) acc
go _ acc Nothing = acc
foldSSD :: Window -> L.Fold (Timed PDSSD) Word64
foldSSD window = L.Fold step bEvent (eEvent window standardEventFolder)
where step (prev, acc) (Timed end (PDSSD _ VolumeDelete _ _)) = (Nothing, go end acc prev)
step a x = sEvent window a x
go end acc (Just x) = insertVal x (end x ^. time) acc
go _ acc Nothing = acc
foldImage :: Window -> L.Fold (Timed PDImage) Word64
foldImage window = L.Fold step bEvent (eEvent window standardEventFolder)
where step (prev, acc) (Timed end (PDImage _ ImageDelete _ _)) = (Nothing, go end acc prev)
step a x = sEvent window a x
go end acc (Just x) = insertVal x (end x ^. time) acc
go _ acc Nothing = acc
foldSnapshot :: Window -> L.Fold (Timed PDSnapshot) Word64
foldSnapshot window = L.Fold step bEvent (eEvent window standardEventFolder)
where step (prev, acc) (Timed end (PDSnapshot _ SnapshotDelete _ _)) = (Nothing, go end acc prev)
step a x = sEvent window a x
go end acc (Just x) = insertVal x (end x ^. time) acc
go _ acc Nothing = acc
foldIP :: Window -> L.Fold (Timed PDIP) Word64
foldIP window = L.Fold step bEvent (eEvent window ipEventFolder)
where step (prev, acc) (Timed end (PDIP _ IPDelete _ _)) = (Nothing, go end acc prev)
step a x = sEvent window a x
go end acc (Just x) = insertVal x (end x ^. time) acc
go _ acc Nothing = acc
foldInstanceFlavor :: (PDInstanceFlavor -> Bool)
-> L.Fold (Timed PDInstanceFlavor) (Map PFValueText Word64)
foldInstanceFlavor f = L.Fold (sGaugePollster f) bGaugePollster snd
foldInstanceVCPU :: (PDInstanceVCPU -> Bool)
-> L.Fold (Timed PDInstanceVCPU) (Map PFValue32 Word64)
foldInstanceVCPU f = L.Fold (sGaugePollster f) bGaugePollster snd
foldInstanceRAM :: (PDInstanceRAM -> Bool)
-> L.Fold (Timed PDInstanceRAM) (Map PFValue32 Word64)
foldInstanceRAM f = L.Fold (sGaugePollster f) bGaugePollster snd
foldInstanceDisk :: (PDInstanceDisk -> Bool)
-> L.Fold (Timed PDInstanceDisk) (Map PFValue32 Word64)
foldInstanceDisk f = L.Fold (sGaugePollster f) bGaugePollster snd
foldImagePollster :: L.Fold (Timed PDImagePollster) (Map PFValue64 Word64)
foldImagePollster = L.Fold (sGaugePollster $ const True) bGaugePollster snd
timewrapFold :: L.Fold x y -> L.Fold (Timed x) y
timewrapFold (L.Fold s b e) = L.Fold (\a (Timed _ x) -> s a x) b e
type Window = (Word64, Word64)
insertVal x = M.insertWith (+) (x ^. value)
type ACumulative x = ( Maybe ( PFValue x
, PFValue x)
, Word64 )
sCumulative :: (Valued x, Ord (PFValue x), Integral (PFValue x))
=> ACumulative x -> x -> ACumulative x
sCumulative (Nothing, acc) x | v <- x ^. value = (Just (v, v), acc)
sCumulative (Just (f, latest), acc) x | v <- x ^. value =
if v < latest
then (Just (f, v), acc + fromIntegral latest)
else (Just (f, v), acc)
bCumulative = (Nothing, 0)
eCumulative (Just (first, latest), acc) = acc + latest first
eCumulative (_, acc) = acc
type AGaugePollster x = ( Maybe (Timed x)
, Map (PFValue x) Word64 )
sGaugePollster
:: (Valued x, Ord (PFValue x))
=> (x -> Bool) -> AGaugePollster x -> Timed x -> AGaugePollster x
sGaugePollster _ (Nothing, acc) x = (Just x, acc)
sGaugePollster isBillable (Just (Timed t1 v1), acc) x@(Timed t2 _)
= let delta = t2 t1
!acc' = if isBillable v1
then insertVal v1 (fromIntegral delta) acc
else acc
in (Just x, acc')
bGaugePollster = (Nothing, M.empty)
type AEvent x = ( Maybe (Timed x)
, Map (PFValue x) Word64 )
bEvent = (Nothing, M.empty)
sEvent :: (Valued x, Ord (PFValue x), Show (PFValue x))
=> Window -> AEvent x -> Timed x -> AEvent x
sEvent _ (Nothing, acc) x = (Just x, acc)
sEvent (start, end) (Just prev, acc) x
= if | prev ^. time > end -> (Nothing, acc)
| prev ^. time < start -> (Just x, acc)
| d <= 0 -> (Nothing, acc)
| otherwise -> (Just x, insertVal prev d acc)
where s = max start (prev ^. time)
e = min end (x ^. time)
d = e s
eEvent (start, end) f = M.foldlWithKey f 0 . go
where s x = max start (x ^. time)
go (Just x, acc)
| d <- end s x, d > 0 = insertVal x d acc
go a@_ = snd a
standardEventFolder a k v = a + (fromIntegral k * v)
ipEventFolder a _ v = a + v