]> git.ipfire.org Git - oddments/collecty.git/commitdiff
plugins: Read Pressure Stall Information from the kernel
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Dec 2021 23:24:16 +0000 (23:24 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Dec 2021 23:24:16 +0000 (23:24 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/collecty/daemon.py
src/collecty/plugins/__init__.py
src/collecty/plugins/psi.py [new file with mode: 0644]

index d86a0deb659321947906d37952e514480df0a9ff..dcc7a9eb389c715b89bd02ccbb017d0368e59e8c 100644 (file)
@@ -105,6 +105,7 @@ collectyplugins_PYTHON = \
        src/collecty/plugins/latency.py \
        src/collecty/plugins/loadavg.py \
        src/collecty/plugins/memory.py \
+       src/collecty/plugins/psi.py \
        src/collecty/plugins/processor.py \
        src/collecty/plugins/sensors.py
 
index 22af2b0d103bb43ca88904721fc0db9b78ea9648..cac236c93dd106ae5a7326395a82f6c77afaf6d7 100644 (file)
@@ -357,9 +357,6 @@ class QueueObject(object):
 
        @staticmethod
        def _format_data(data):
-               if not isinstance(data, tuple) and not isinstance(data, list):
-                       return data
-
                # Replace all Nones by UNKNOWN
                s = []
 
index 147a1b6ee977042f7f0a5edaf37a4bb0d266a710..41b47f5421fe6cc53d8f5cd906d5a9edb6746b24 100644 (file)
@@ -33,5 +33,6 @@ from . import ipfrag
 from . import latency
 from . import loadavg
 from . import processor
+from . import psi
 from . import memory
 from . import sensors
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)