Values output by /proc/stat are total values of time since the last reboot, in ticks that usually are 0.01s; so after roughly 250 CPU-days, the total time can no longer be represented as a 32-bit signed integer. Note that this can actually happen on a node with a high enough number of CPUs or long enough uptime. Therefore, take Integer as data type, to avoid being hit by overflows.
Signed-off-by: Klaus Aehlig <[email protected]> --- src/Ganeti/Cpu/LoadParser.hs | 20 ++++++++++---------- src/Ganeti/Cpu/Types.hs | 20 ++++++++++---------- src/Ganeti/DataCollectors/CPUload.hs | 10 +++++----- src/Ganeti/DataCollectors/Types.hs | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Ganeti/Cpu/LoadParser.hs b/src/Ganeti/Cpu/LoadParser.hs index c321101..e2ffa01 100644 --- a/src/Ganeti/Cpu/LoadParser.hs +++ b/src/Ganeti/Cpu/LoadParser.hs @@ -53,16 +53,16 @@ import Ganeti.Cpu.Types oneCPUstatParser :: Parser CPUstat oneCPUstatParser = let nameP = stringP - userP = numberP - niceP = numberP - systemP = numberP - idleP = numberP - iowaitP = numberP - irqP = numberP - softirqP = numberP - stealP = numberP - guestP = numberP - guest_niceP = numberP + userP = integerP + niceP = integerP + systemP = integerP + idleP = integerP + iowaitP = integerP + irqP = integerP + softirqP = integerP + stealP = integerP + guestP = integerP + guest_niceP = integerP in CPUstat <$> nameP <*> userP <*> niceP <*> systemP <*> idleP <*> iowaitP <*> irqP <*> softirqP <*> stealP <*> guestP <*> guest_niceP diff --git a/src/Ganeti/Cpu/Types.hs b/src/Ganeti/Cpu/Types.hs index 9fc31ef..5786435 100644 --- a/src/Ganeti/Cpu/Types.hs +++ b/src/Ganeti/Cpu/Types.hs @@ -61,14 +61,14 @@ emptyCPUavgload = CPUavgload { cavCpuNumber = 1 -- | This is the format of the data parsed by the input file. $(buildObject "CPUstat" "cs" [ simpleField "name" [t| String |] - , simpleField "user" [t| Int |] - , simpleField "nice" [t| Int |] - , simpleField "system" [t| Int |] - , simpleField "idle" [t| Int |] - , simpleField "iowait" [t| Int |] - , simpleField "irq" [t| Int |] - , simpleField "softirq" [t| Int |] - , simpleField "steal" [t| Int |] - , simpleField "guest" [t| Int |] - , simpleField "guest_nice" [t| Int |] + , simpleField "user" [t| Integer |] + , simpleField "nice" [t| Integer |] + , simpleField "system" [t| Integer |] + , simpleField "idle" [t| Integer |] + , simpleField "iowait" [t| Integer |] + , simpleField "irq" [t| Integer |] + , simpleField "softirq" [t| Integer |] + , simpleField "steal" [t| Integer |] + , simpleField "guest" [t| Integer |] + , simpleField "guest_nice" [t| Integer |] ]) diff --git a/src/Ganeti/DataCollectors/CPUload.hs b/src/Ganeti/DataCollectors/CPUload.hs index 65ac423..42f4e88 100644 --- a/src/Ganeti/DataCollectors/CPUload.hs +++ b/src/Ganeti/DataCollectors/CPUload.hs @@ -5,7 +5,7 @@ {- -Copyright (C) 2013 Google Inc. +Copyright (C) 2013, 2016 Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -111,17 +111,17 @@ dcReport colData = in buildDCReport cpuLoadData -- | Data stored by the collector in mond's memory. -type Buffer = Seq.Seq (ClockTime, [Int]) +type Buffer = Seq.Seq (ClockTime, [Integer]) -- | Compute the load from a CPU. -computeLoad :: CPUstat -> Int +computeLoad :: CPUstat -> Integer computeLoad cpuData = csUser cpuData + csNice cpuData + csSystem cpuData + csIowait cpuData + csIrq cpuData + csSoftirq cpuData + csSteal cpuData + csGuest cpuData + csGuestNice cpuData -- | Reads and Computes the load for each CPU. -dcCollectFromFile :: FilePath -> IO (ClockTime, [Int]) +dcCollectFromFile :: FilePath -> IO (ClockTime, [Integer]) dcCollectFromFile inputFile = do contents <- ((E.try $ readFile inputFile) :: IO (Either IOError String)) >>= @@ -178,7 +178,7 @@ computeAverage s w ticks = (timestampR, listR) = rightmost workInWindow = zipWith (-) listL listR timediff = timestampL - timestampR - overall = fromInteger (timediff * ticks) / 1000000 :: Double + overall = fromIntegral (timediff * ticks) / 1000000 :: Double if overall > 0 then BT.Ok $ map (flip (/) overall . fromIntegral) workInWindow else BT.Bad $ "Time covered by data is not sufficient." diff --git a/src/Ganeti/DataCollectors/Types.hs b/src/Ganeti/DataCollectors/Types.hs index 3bd31b3..20386ce 100644 --- a/src/Ganeti/DataCollectors/Types.hs +++ b/src/Ganeti/DataCollectors/Types.hs @@ -145,7 +145,7 @@ instance JSON DCVersion where -- | Type for the value field of the `CollectorMap` below. data CollectorData = - CPULoadData (Seq.Seq (ClockTime, [Int])) + CPULoadData (Seq.Seq (ClockTime, [Integer])) | InstanceCpuLoad (Map.Map String (Seq.Seq (ClockTime, Double))) instance NFData ClockTime where -- 2.7.0.rc3.207.g0ac5344
