def test_cpu_usage_when_cpu_total_is_zero(elasticapm_client, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") for path, content in ( (proc_stat, TEMPLATE_PROC_STAT_DEBIAN.format(user=0, idle=0)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)), (proc_meminfo, TEMPLATE_PROC_MEMINFO_NO_MEMAVAILABLE), ): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, ) data = next(metricset.collect()) cpu_total_expected = 0 assert data["samples"]["system.cpu.total.norm.pct"][ "value"] == cpu_total_expected assert data["samples"]["system.process.cpu.total.norm.pct"][ "value"] == cpu_total_expected
def test_cpu_mem_from_proc(proc_stat_template, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") for path, content in ( (proc_stat, proc_stat_template.format(user=0, idle=0)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)), (proc_meminfo, TEMPLATE_PROC_MEMINFO), ): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet(sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo) for path, content in ( (proc_stat, proc_stat_template.format(user=400000, idle=600000)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=100000, stime=100000)), (proc_meminfo, TEMPLATE_PROC_MEMINFO), ): with open(path, mode="w") as f: f.write(content) data = metricset.collect() assert data["samples"]["system.cpu.total.norm.pct"]["value"] == 0.4 assert data["samples"]["system.process.cpu.total.norm.pct"]["value"] == 0.2 assert data["samples"]["system.memory.total"]["value"] == 16552841216 assert data["samples"]["system.memory.actual.free"]["value"] == 6670774272 assert data["samples"]["system.process.memory.rss.bytes"][ "value"] == 47738880 assert data["samples"]["system.process.memory.size"]["value"] == 3686981632
def test_mem_free_from_memfree_when_memavailable_not_mentioned( elasticapm_client, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") for path, content in ( (proc_stat, TEMPLATE_PROC_STAT_DEBIAN.format(user=0, idle=0)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)), (proc_meminfo, TEMPLATE_PROC_MEMINFO_NO_MEMAVAILABLE), ): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, ) for path, content in ( (proc_stat, TEMPLATE_PROC_STAT_DEBIAN.format(user=400000, idle=600000)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=100000, stime=100000)), (proc_meminfo, TEMPLATE_PROC_MEMINFO_NO_MEMAVAILABLE), ): with open(path, mode="w") as f: f.write(content) data = next(metricset.collect()) mem_free_expected = sum([359184, 891296, 6416340 ]) * 1024 # MemFree + Buffers + Cached, in bytes assert data["samples"]["system.memory.actual.free"][ "value"] == mem_free_expected
def test_cpu_mem_from_proc(elasticapm_client, proc_stat_template, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") cgroup_memory_limit = os.path.join(tmpdir.strpath, "memory", "memory.limit_in_bytes") cgroup_memory_usage = os.path.join(tmpdir.strpath, "memory", "memory.usage_in_bytes") proc_self_cgroup = os.path.join(tmpdir.strpath, "cgroup") os.mkdir(os.path.join(tmpdir.strpath, "memory")) proc_self_mount = os.path.join(tmpdir.strpath, "mountinfo") for path, content in ( (proc_stat, proc_stat_template.format(user=0, idle=0)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)), (proc_meminfo, TEMPLATE_PROC_MEMINFO), (cgroup_memory_limit, TEMPLATE_CGROUP_MEM_LIMIT_IN_BYTES), (cgroup_memory_usage, TEMPLATE_CGROUP_MEM_USAGE_IN_BYTES), (proc_self_cgroup, "9:memory:/slice"), ( proc_self_mount, "39 30 0:35 / " + tmpdir.strpath + "/memory rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,memory\n", ), ): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, proc_self_cgroup=proc_self_cgroup, mount_info=proc_self_mount, ) for path, content in ( (proc_stat, proc_stat_template.format(user=400000, idle=600000)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=100000, stime=100000)), (proc_meminfo, TEMPLATE_PROC_MEMINFO), ): with open(path, mode="w") as f: f.write(content) data = next(metricset.collect()) assert data["samples"]["system.cpu.total.norm.pct"]["value"] == 0.4 assert data["samples"]["system.process.cpu.total.norm.pct"]["value"] == 0.2 assert data["samples"]["system.memory.total"]["value"] == 16552841216 assert data["samples"]["system.memory.actual.free"]["value"] == 6670774272 assert data["samples"]["system.process.memory.rss.bytes"][ "value"] == 47738880 assert data["samples"]["system.process.memory.size"]["value"] == 3686981632
def test_mem_from_cgroup2(elasticapm_client, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") cgroup2_memory_limit = os.path.join(tmpdir.strpath, "slice", "memory.max") cgroup2_memory_usage = os.path.join(tmpdir.strpath, "slice", "memory.current") cgroup2_memory_stat = os.path.join(tmpdir.strpath, "slice", "memory.stat") cgroup2_self_cgroup = os.path.join(tmpdir.strpath, "cgroup") proc_self_cgroup = os.path.join(tmpdir.strpath, "cgroup") os.mkdir(os.path.join(tmpdir.strpath, "slice")) proc_self_mount = os.path.join(tmpdir.strpath, "mountinfo") for path, content in ( (proc_stat, TEMPLATE_PROC_STAT_DEBIAN.format(user=0, idle=0)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)), (proc_meminfo, TEMPLATE_PROC_MEMINFO), (cgroup2_memory_limit, TEMPLATE_CGROUP_MEM_LIMIT_IN_BYTES_LIMITED), (cgroup2_memory_usage, TEMPLATE_CGROUP_MEM_USAGE_IN_BYTES), (cgroup2_memory_stat, TEMPLATE_CGROUP_MEM_STAT), (cgroup2_self_cgroup, "9:memory:/slice"), ( proc_self_mount, "30 23 0:26 / " + tmpdir.strpath + " rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 cgroup rw,seclabel\n", ), ): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, proc_self_cgroup=proc_self_cgroup, mount_info=proc_self_mount, ) data = next(metricset.collect()) assert data["samples"]["system.memory.total"]["value"] == 16552841216 assert data["samples"]["system.memory.actual.free"]["value"] == 6670774272 assert data["samples"]["system.process.memory.rss.bytes"][ "value"] == 47738880 assert data["samples"]["system.process.memory.size"]["value"] == 3686981632 assert data["samples"]["system.process.cgroup.memory.mem.limit.bytes"][ "value"] == 7964778496 assert data["samples"]["system.process.cgroup.memory.mem.usage.bytes"][ "value"] == 954370560 assert data["samples"][ "system.process.cgroup.memory.stats.inactive_file.bytes"][ "value"] == 10407936
def test_mem_from_cgroup_files_dont_exist(elasticapm_client, tmpdir): # it appears that on Google App engine, there is a possibility of # memory.limit_in_bytes existing while memory.usage_in_bytes does not. # See https://github.com/elastic/apm-agent-python/issues/985 proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") cgroup_memory_limit = os.path.join(tmpdir.strpath, "memory", "memory.limit_in_bytes") # intentionally commented out # cgroup_memory_usage = os.path.join(tmpdir.strpath, "memory", "memory.usage_in_bytes") cgroup_memory_stat = os.path.join(tmpdir.strpath, "memory", "memory.stat") proc_self_cgroup = os.path.join(tmpdir.strpath, "cgroup") os.mkdir(os.path.join(tmpdir.strpath, "memory")) proc_self_mount = os.path.join(tmpdir.strpath, "mountinfo") for path, content in ( (proc_stat, TEMPLATE_PROC_STAT_DEBIAN.format(user=0, idle=0)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)), (proc_meminfo, TEMPLATE_PROC_MEMINFO), (cgroup_memory_limit, TEMPLATE_CGROUP_MEM_LIMIT_IN_BYTES_LIMITED), # intentionally commented out # (cgroup_memory_usage, TEMPLATE_CGROUP_MEM_USAGE_IN_BYTES), (cgroup_memory_stat, TEMPLATE_CGROUP_MEM_STAT), (proc_self_cgroup, "9:memory:/slice"), ( proc_self_mount, "39 30 0:35 / " + tmpdir.strpath + "/memory rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,memory\n", ), ): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, proc_self_cgroup=proc_self_cgroup, mount_info=proc_self_mount, ) assert metricset.cgroup_files.limit is not None assert metricset.cgroup_files.usage is None data = next(metricset.collect()) assert "system.process.cgroup.memory.mem.limit.bytes" in data["samples"] assert "system.process.cgroup.memory.mem.usage.bytes" not in data[ "samples"]
def test_mem_from_cgroup2_max_handling(elasticapm_client, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") cgroup2_memory_limit = os.path.join(tmpdir.strpath, "slice", "memory.max") cgroup2_memory_usage = os.path.join(tmpdir.strpath, "slice", "memory.current") cgroup2_memory_stat = os.path.join(tmpdir.strpath, "slice", "memory.stat") cgroup2_self_cgroup = os.path.join(tmpdir.strpath, "cgroup") proc_self_cgroup = os.path.join(tmpdir.strpath, "cgroup") os.mkdir(os.path.join(tmpdir.strpath, "slice")) proc_self_mount = os.path.join(tmpdir.strpath, "mountinfo") for path, content in ( (proc_stat, TEMPLATE_PROC_STAT_DEBIAN.format(user=0, idle=0)), (proc_stat_self, TEMPLATE_PROC_STAT_SELF.format(utime=0, stime=0)), (proc_meminfo, TEMPLATE_PROC_MEMINFO), (cgroup2_memory_limit, "max"), (cgroup2_memory_usage, TEMPLATE_CGROUP_MEM_USAGE_IN_BYTES), (cgroup2_memory_stat, TEMPLATE_CGROUP_MEM_STAT), (cgroup2_self_cgroup, "9:memory:/slice"), ( proc_self_mount, "30 23 0:26 / " + tmpdir.strpath + " rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 cgroup rw,seclabel\n", ), ): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, proc_self_cgroup=proc_self_cgroup, mount_info=proc_self_mount, ) data = next(metricset.collect()) assert "system.process.cgroup.memory.mem.limit.bytes" not in data[ "samples"] assert "system.process.cgroup.memory.mem.usage.bytes" not in data[ "samples"] assert "system.process.cgroup.memory.stats.inactive_file.bytes" not in data[ "samples"]