4
from landscape.accumulate import Accumulator
5
from landscape.lib.monitor import CoverageMonitor
6
from landscape.monitor.plugin import MonitorPlugin
8
LAST_MESURE_KEY = "last-cpu-usage-measure"
9
ACCUMULATOR_KEY = "cpu-usage-accumulator"
12
class CPUUsage(MonitorPlugin):
14
Plugin that captures CPU usage information.
16
persist_name = "cpu-usage"
18
# Prevent the Plugin base-class from scheduling looping calls.
21
def __init__(self, interval=30, monitor_interval=60 * 60,
22
create_time=time.time):
23
self._interval = interval
24
self._monitor_interval = monitor_interval
25
self._cpu_usage_points = []
26
self._create_time = create_time
27
self._stat_file = "/proc/stat"
29
def register(self, registry):
30
super(CPUUsage, self).register(registry)
31
self._accumulate = Accumulator(self._persist, registry.step_size)
33
self.registry.reactor.call_every(self._interval, self.run)
35
self._monitor = CoverageMonitor(self._interval, 0.8,
37
create_time=self._create_time)
38
self.registry.reactor.call_every(self._monitor_interval,
40
self.registry.reactor.call_on("stop", self._monitor.log, priority=2000)
41
self.call_on_accepted("cpu-usage", self.send_message, True)
43
def create_message(self):
44
cpu_points = self._cpu_usage_points
45
self._cpu_usage_points = []
46
return {"type": "cpu-usage", "cpu-usages": cpu_points}
48
def send_message(self, urgent=False):
49
message = self.create_message()
50
if len(message["cpu-usages"]):
51
self.registry.broker.send_message(message, self._session_id,
54
def exchange(self, urgent=False):
55
self.registry.broker.call_if_accepted("cpu-usage",
56
self.send_message, urgent)
60
new_timestamp = int(self._create_time())
61
new_cpu_usage = self._get_cpu_usage(self._stat_file)
64
if new_cpu_usage is not None:
65
step_data = self._accumulate(new_timestamp, new_cpu_usage,
67
if step_data is not None:
68
self._cpu_usage_points.append(step_data)
70
def _get_cpu_usage(self, stat_file):
72
This method computes the CPU usage from C{stat_file}.
76
with open(stat_file, "r") as f:
77
# The first line of the file is the CPU information aggregated
81
logging.error("Could not open %s for reading, "
82
"CPU usage cannot be computed.", stat_file)
85
# The cpu line is composed of:
86
# ["cpu", user, nice, system, idle, iowait, irq, softirq, steal, guest,
88
# The fields are a sum of USER_HZ quantums since boot spent in each
89
# "category". We need to keep track of what the previous measure was,
90
# since the current CPU usage will be calculated on the delta between
91
# the previous measure and the current measure.
92
# Remove the trailing "\n"
93
fields = stat.split()[1:]
95
value = sum(int(i) for i in fields)
97
previous = self._persist.get(LAST_MESURE_KEY)
98
if previous is not None and value != previous[0]:
99
delta = value - previous[0]
101
result = (delta - idle + previous[1]) / float(delta)
103
self._persist.set(LAST_MESURE_KEY, (value, idle))