{-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-} module System.Metrics.Prometheus.Ridley.Metrics.CPU.Unix ( getLoadAvg , processCPULoad ) where import Control.Applicative ((<|>)) import Data.Maybe (fromJust) import qualified Data.Text as T import Data.Traversable import qualified Data.Vector as V import Shelly import qualified System.Metrics.Prometheus.Metric.Gauge as P import System.Metrics.Prometheus.Ridley.Types import Text.Read (readMaybe) -------------------------------------------------------------------------------- getLoadAvg :: IO (V.Vector Double) getLoadAvg = do rawOutput <- shelly $ silently $ T.strip <$> run "cat" ["/proc/loadavg"] let standardFormat = case traverse (readMaybe . T.unpack) (take 3 . T.lines $ rawOutput) of Just [a,b,c] -> Just [a,b,c] _ -> Nothing -- See: https://github.com/iconnect/ridley/issues/8 let alternativeFormat = case traverse (readMaybe . T.unpack) (take 3 . T.splitOn " " $ rawOutput) of Just [a,b,c] -> Just [a,b,c] _ -> Nothing return . V.fromList . fromJust $ standardFormat <|> alternativeFormat <|> Just noAvgInfo where noAvgInfo = [-1.0, -1.0, -1.0] -------------------------------------------------------------------------------- -- | As we have 3 gauges, it makes no sense flushing them. updateCPULoad :: (P.Gauge, P.Gauge, P.Gauge) -> Bool -> IO () updateCPULoad (cpu1m, cpu5m, cpu15m) _ = do loadVec <- getLoadAvg P.set (loadVec `V.unsafeIndex` 0) cpu1m P.set (loadVec `V.unsafeIndex` 1) cpu5m P.set (loadVec `V.unsafeIndex` 2) cpu15m -------------------------------------------------------------------------------- processCPULoad :: (P.Gauge, P.Gauge, P.Gauge) -> RidleyMetricHandler processCPULoad g = RidleyMetricHandler { metric = g , updateMetric = updateCPULoad , flush = False }