Skip to content

Commit f40862e

Browse files
ivasicbasepi
authored andcommitted
Handle exceptions when cpu_total is zero (#611)
* Handle exceptions when `cpu_total` is zero * Make sure zero `cpu_total` is handled correctly * Ensure `system.process.cpu.total.norm.pct` is `0` as well * Add newline to satisfy the linter
1 parent bddb81d commit f40862e

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

elasticapm/metrics/sets/cpu_linux.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ def before_collect(self):
6969
with self._read_data_lock:
7070
prev = self.previous
7171
delta = {k: new[k] - prev[k] for k in new.keys()}
72-
cpu_usage_ratio = delta["cpu_usage"] / delta["cpu_total"]
72+
try:
73+
cpu_usage_ratio = delta["cpu_usage"] / delta["cpu_total"]
74+
except ZeroDivisionError:
75+
cpu_usage_ratio = 0
7376
self.gauge("system.cpu.total.norm.pct").val = cpu_usage_ratio
7477
# MemAvailable not present in linux before kernel 3.14
7578
# fallback to MemFree + Buffers + Cache if not present - see #500
@@ -80,7 +83,10 @@ def before_collect(self):
8083
self.gauge("system.memory.actual.free").val = mem_free
8184
self.gauge("system.memory.total").val = new["MemTotal"]
8285

83-
cpu_process_percent = delta["proc_total_time"] / delta["cpu_total"]
86+
try:
87+
cpu_process_percent = delta["proc_total_time"] / delta["cpu_total"]
88+
except ZeroDivisionError:
89+
cpu_process_percent = 0
8490

8591
self.gauge("system.process.cpu.total.norm.pct").val = cpu_process_percent
8692
self.gauge("system.process.memory.size").val = new["vsize"]

tests/metrics/cpu_linux_tests.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,28 @@ def test_mem_free_from_memfree_when_memavailable_not_mentioned(tmpdir):
155155

156156
mem_free_expected = sum([359184, 891296, 6416340]) * 1024 # MemFree + Buffers + Cached, in bytes
157157
assert data["samples"]["system.memory.actual.free"]["value"] == mem_free_expected
158+
159+
160+
def test_cpu_usage_when_cpu_total_is_zero(tmpdir):
161+
proc_stat_self = os.path.join(tmpdir.strpath, "self-stat")
162+
proc_stat = os.path.join(tmpdir.strpath, "stat")
163+
proc_meminfo = os.path.join(tmpdir.strpath, "meminfo")
164+
165+
for path, content in (
166+
(proc_stat, TEMPLATE_PROC_STAT_DEBIAN.format(user=0, idle=0)),
167+
(proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)),
168+
(proc_meminfo, TEMPLATE_PROC_MEMINFO_NO_MEMAVAILABLE),
169+
):
170+
with open(path, mode="w") as f:
171+
f.write(content)
172+
metricset = CPUMetricSet(
173+
MetricsRegistry(0, lambda x: None),
174+
sys_stats_file=proc_stat,
175+
process_stats_file=proc_stat_self,
176+
memory_stats_file=proc_meminfo,
177+
)
178+
data = next(metricset.collect())
179+
180+
cpu_total_expected = 0
181+
assert data["samples"]["system.cpu.total.norm.pct"]["value"] == cpu_total_expected
182+
assert data["samples"]["system.process.cpu.total.norm.pct"]["value"] == cpu_total_expected

0 commit comments

Comments
 (0)