packages feed

borel-0.18.0: lib/Borel/Ceilometer.hs

{-# LANGUAGE TupleSections #-}

module Borel.Ceilometer
     ( ceilometer
     , module Borel.Ceilometer.Instance
     )
where

import           Control.Applicative
import           Control.Monad.Reader
import qualified Data.Bimap           as BM
import qualified Data.List            as L
import qualified Data.Map             as M
import           Data.Maybe
import           Data.Monoid
import           Pipes                hiding (Proxy)
import           System.Log.Logger

-- friends
import           Ceilometer.Client
import           Vaultaire.Types

import           Borel.Ceilometer.Instance
import           Borel.Types


--------------------------------------------------------------------------------

-- | Use Ceilometer to decode and aggregate a stream of raw data points.
--
ceilometer
    :: (MonadIO m, Applicative m)
    => FlavorMap                 -- ^ Instance flavor mapping
    -> GroupedMetric             -- ^ Requested metrics, this determines how we present the fold result
    -> Env                       -- ^ Ceilometer arguments
    -> Producer SimplePoint m () -- ^ Raw points
    -> m [Result]
ceilometer flavors metrics cenv@(Env _ sd _ _ _) raw = do
  liftIO $ debugM "borel" ("using ceilometer to decode data with " <> show sd)
  fromMaybe [] <$> fmap handleResult <$> decodeFold cenv raw

  where handleResult :: FoldResult -> [Result]
        handleResult x = case (x, metrics) of
          (RSingle   val,  [m]) -> [(m,val)]
          (RMapNum32 vals, [m]) -> [(m, M.foldlWithKey (\a k v -> a + (fromIntegral k * v)) 0 vals)]
          (RMapNum64 vals, [m]) -> [(m, M.foldlWithKey (\a k v -> a + (fromIntegral k * v)) 0 vals)]
          (RMapText  vals,  _)  -> let ms = intersect metrics flavors
                                   in  map (\(metric, flavor) -> (metric,) $ fromMaybe 0 $ M.lookup flavor vals) ms
          _                     -> []

        --  Intersect the flavor map and the list of metrics requested. Flatten the result.
        intersect :: [Metric] -> FlavorMap -> [(Metric, Flavor)]
        intersect ms = BM.fold (\k1 _ acc -> maybe acc ((:acc) . (,k1))
                                          $  L.find (== mkInstance k1) ms) []