1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
--
-- (C) 2014-22 - ntop.org
--
local dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
local cpu_utils = {}
local alert_utils = require "alert_utils"
-- #################################
local CPU_STATES_PREV_KEY = "ntopng.cache.system_utils.cpu_states.prev"
local CPU_STATES_DELTA = "ntopng.cache.system_utils.cpu_states.delta"
-- #################################
-- Save cpu_states (either a delta or an absolute value) in a redis key.
-- The format used is the same as the one used by /proc/stat
local function save_cpu_states(cpu_states, key)
-- To serialize CPU states use the same format as the one used in /proc/stat
-- This allows us to re-use the parse function both to read serialized values as well as to read the line directly from /proc/stat
local cpu_line = string.format("cpu %u %u %u %u %u %u %u %u %u %u",
cpu_states["user"] or 0, cpu_states["nice"] or 0, cpu_states["system"] or 0,
cpu_states["idle"] or 0, cpu_states["iowait"] or 0, cpu_states["irq"] or 0,
cpu_states["softirq"] or 0, cpu_states["steal"] or 0, cpu_states["guest"] or 0,
cpu_states["guest_nice"] or 0)
ntop.setCache(key, cpu_line, 120 --[[ 2 minutes --]])
end
-- #################################
-- Reads a line with the format of /proc/stat and parses the various state values into a table
local function parse_proc_stat_cpu_line(cpu_line)
-- Parse the cpu string using an sscanf-like pattern
local user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice = cpu_line:match("cpu%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")
local states = {
user = user or 0, nice = nice or 0, system = system or 0,
idle = idle or 0, iowait = iowait or 0, irq = irq or 0,
softirq = softirq or 0, steal = steal or 0, guest = guest or 0,
guest_nice = guest_nice or 0
}
return states
end
-- #################################
-- Computes the delta of the current cpu states submitted in cur_states
-- with their previous values
local function compute_cpu_states_delta(cur_states)
-- Read the previously saved line so it can be compared with the cur_states
-- to compute the variation
local prev_cpu_line = ntop.getCache(CPU_STATES_PREV_KEY)
local states_delta = {}
-- It there was a previous line...
if prev_cpu_line and prev_cpu_line ~= "" then
-- Parse the previous line in its corresponding previous states
local prev_states = parse_proc_stat_cpu_line(prev_cpu_line)
-- Now iterate the current states and compute their deltas with reference
-- to their previous value
for cur_state, cur_val in pairs(cur_states) do
local cur_delta = 0
if prev_states[cur_state] then
cur_delta = cur_val - prev_states[cur_state]
-- Safety check
if cur_delta < 0 then
cur_delta = 0
end
end
states_delta[cur_state] = math.floor(cur_delta) -- make sure it's an integer
end
-- Save the deltas
save_cpu_states(states_delta, CPU_STATES_DELTA)
end
-- Save the current cpu states in the prev key so they will automatically
-- become previous during the next call
save_cpu_states(cur_states, CPU_STATES_PREV_KEY)
return states_delta
end
-- #################################
function cpu_utils.compute_cpu_states()
if not ntop.isWindows() then
local f = io.open("/proc/stat", "r")
if f then
-- The first line of the file contains cpu time_spent
-- See http://man7.org/linux/man-pages/man5/proc.5.html for the meaning of each column
local cpu_line = f:read("*line")
if cpu_line and cpu_line ~= "" then
local cur_states = parse_proc_stat_cpu_line(cpu_line)
local states_delta = compute_cpu_states_delta(cur_states)
end
f:close()
end
end
end
-- #################################
-- Returns all the available cpu states in %
function cpu_utils.get_cpu_states()
local states_delta_line = ntop.getCache(CPU_STATES_DELTA)
if states_delta_line and states_delta_line ~= "" then
-- Parse the delta in its corresponding states
local delta_states = parse_proc_stat_cpu_line(states_delta_line)
local total = 0
for _, delta_val in pairs(delta_states) do
total = total + delta_val
end
-- Express in percentage
for state in pairs(delta_states) do
if total > 0 then
delta_states[state] = delta_states[state] / total * 100
else
delta_states[state] = 0
end
end
return delta_states
end
end
-- #################################
function cpu_utils.systemHostStats()
local system_host_stats = ntop.systemHostStat()
system_host_stats["cpu_states"] = cpu_utils.get_cpu_states()
return system_host_stats
end
-- #################################
function cpu_utils.processTimeseriesEnabled()
return(ntop.getPref("ntopng.prefs.system_probes_timeseries") ~= "0")
end
-- #################################
return cpu_utils
|