]> git.ipfire.org Git - oddments/collecty.git/blobdiff - src/collecty/plugins/psi.py
plugins: Read Pressure Stall Information from the kernel
[oddments/collecty.git] / src / collecty / plugins / psi.py
diff --git a/src/collecty/plugins/psi.py b/src/collecty/plugins/psi.py
new file mode 100644 (file)
index 0000000..f9fe0b1
--- /dev/null
@@ -0,0 +1,99 @@
+#!/usr/bin/python3
+###############################################################################
+#                                                                             #
+# collecty - A system statistics collection daemon for IPFire                 #
+# Copyright (C) 2021 IPFire development team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import os
+
+from . import base
+
+class PSIObject(base.Object):
+       rrd_schema = [
+               # some
+               "DS:some_avg10:GAUGE:0:100",
+               "DS:some_avg60:GAUGE:0:100",
+               "DS:some_avg300:GAUGE:0:100",
+               "DS:some_total:DERIVE:0:U",
+
+               # full
+               "DS:full_avg10:GAUGE:0:100",
+               "DS:full_avg60:GAUGE:0:100",
+               "DS:full_avg300:GAUGE:0:100",
+               "DS:full_total:DERIVE:0:U",
+       ]
+
+       def __repr__(self):
+               return "<%s %s>" % (self.__class__.__name__, self.item)
+
+       def init(self, item):
+               self.item = item
+
+               self.path = os.path.join("/proc/pressure", self.item)
+
+       @property
+       def id(self):
+               return self.item
+
+       def collect(self):
+               lines = self.read_file("/proc/pressure", self.item)
+
+               # Do nothing if nothing could be read
+               if not lines:
+                       return
+
+               # Parse all input lines
+               values = {}
+               for line in lines.splitlines():
+                       values.update(self._parse_psi(line))
+
+               # Return all values in order
+               for share in ("some", "full"):
+                       for value in ("avg10", "avg60", "avg300", "total"):
+                               yield values.get("%s-%s" % (share, value), None)
+
+       def _parse_psi(self, line):
+               words = line.split(" ")
+
+               share = None
+               values = {}
+
+               for i, word in enumerate(words):
+                       # Store the share of time
+                       if i == 0:
+                               share = word
+                               continue
+
+                       # Split word
+                       key, delim, value = word.partition("=")
+
+                       # Store it in the values array
+                       values["%s-%s" % (share, key)] = value
+
+               # Return everything
+               return values
+
+
+class PSIPlugin(base.Plugin):
+       name = "psi"
+       description = "Pressure Stall Information Plugin"
+
+       @property
+       def objects(self):
+               for item in os.listdir("/proc/pressure"):
+                       yield PSIObject(self, item)