Changeset

4554:025cf93acfe9

mod_measure_process: Provide metrics about the process itself
author Jonas Schäfer <jonas@wielicki.name>
date Wed, 28 Apr 2021 08:21:54 +0200
parents 4553:7e5c8186f121
children 4555:1e70538e4641
files mod_measure_process/README.markdown mod_measure_process/mod_measure_process.lua
diffstat 2 files changed, 101 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_measure_process/README.markdown	Wed Apr 28 08:21:54 2021 +0200
@@ -0,0 +1,27 @@
+---
+labels:
+- Statistics
+summary: Measure process resource use metrics (cpu, memory, file descriptors)
+---
+
+Description
+===========
+
+This module exposes process resource use metrics similar to those exposed by
+default when using a Prometheus client library. Specifically, the following
+metrics are exposed:
+
+- CPU use
+- Resident set and virtual memory size
+- Number of open file descriptors and their limit
+
+This module uses the new OpenMetrics API and thus requires a recent version
+of Prosody trunk (0.12+).
+
+Compatibility
+=============
+
+  ------- -------------
+  trunk   Works
+  0.11    Does not work
+  ------- -------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_measure_process/mod_measure_process.lua	Wed Apr 28 08:21:54 2021 +0200
@@ -0,0 +1,74 @@
+module:set_global()
+
+local get_cpu_time = os.clock
+
+local custom_metric = require "core.statsmanager".metric
+local cpu_time = custom_metric(
+	"counter", "process_cpu", "seconds",
+	"CPU time used by Prosody as reported by clock(3)."
+):with_labels()
+
+local lfs = require "lfs"
+
+module:hook("stats-update", function ()
+	cpu_time:set(get_cpu_time())
+end);
+
+if lfs.attributes("/proc/self/statm", "mode") == "file" then
+	local pagesize = module:get_option_number("memory_pagesize", 4096); -- getconf PAGESIZE
+
+	local vsz = custom_metric(
+		"gauge", "process_virtual_memory", "bytes",
+		"Virtual memory size in bytes."
+	):with_labels()
+	local rss = custom_metric(
+		"gauge", "process_resident_memory", "bytes",
+		"Resident memory size in bytes."
+	):with_labels()
+
+	module:hook("stats-update", function ()
+		local statm, err = io.open("/proc/self/statm");
+		if not statm then
+			module:log("error", tostring(err));
+			return;
+		end
+		-- virtual memory (caches, opened librarys, everything)
+		vsz:set(statm:read("*n") * pagesize);
+		-- resident set size (actually used memory)
+		rss:set(statm:read("*n") * pagesize);
+		statm:close();
+	end);
+end
+
+if lfs.attributes("/proc/self/fd", "mode") == "directory" then
+	local open_fds = custom_metric(
+		"gauge", "process_open_fds", "",
+		"Number of open file descriptors."
+	):with_labels()
+
+	local has_posix, posix = pcall(require, "util.pposix")
+	local max_fds
+	if has_posix then
+		max_fds = custom_metric(
+			"gauge", "process_max_fds", "",
+			"Maximum number of open file descriptors"
+		):with_labels()
+	else
+		module:log("warn", "not reporting maximum number of file descriptors because mod_posix is not available")
+	end
+
+	module:hook("stats-update", function ()
+		local count = 0
+		for _ in lfs.dir("/proc/self/fd") do
+			count = count + 1
+		end
+		open_fds:set(count)
+
+		if has_posix then
+			local ok, soft, hard = posix.getrlimit("NOFILE")
+			if ok then
+				max_fds:set(hard)
+			end
+		end
+	end);
+end