From: Michael Tremer Date: Tue, 26 May 2015 23:14:00 +0000 (+0000) Subject: Add cpufreq plugin X-Git-Tag: 003~15 X-Git-Url: http://git.ipfire.org/?p=collecty.git;a=commitdiff_plain;h=81b24bab60a154c7528b57803a707f4031807bfa Add cpufreq plugin --- diff --git a/Makefile.am b/Makefile.am index ac7e794..80c1946 100644 --- a/Makefile.am +++ b/Makefile.am @@ -87,6 +87,7 @@ collectyplugins_PYTHON = \ src/collecty/plugins/base.py \ src/collecty/plugins/conntrack.py \ src/collecty/plugins/cpu.py \ + src/collecty/plugins/cpufreq.py \ src/collecty/plugins/disk.py \ src/collecty/plugins/entropy.py \ src/collecty/plugins/__init__.py \ diff --git a/po/POTFILES.in b/po/POTFILES.in index d8d9ea0..f6aebb3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -9,6 +9,7 @@ src/collecty/ping.py src/collecty/plugins/base.py src/collecty/plugins/conntrack.py src/collecty/plugins/cpu.py +src/collecty/plugins/cpufreq.py src/collecty/plugins/disk.py src/collecty/plugins/entropy.py src/collecty/plugins/__init__.py diff --git a/src/collecty/plugins/__init__.py b/src/collecty/plugins/__init__.py index faa9348..b68acc9 100644 --- a/src/collecty/plugins/__init__.py +++ b/src/collecty/plugins/__init__.py @@ -24,6 +24,7 @@ from base import Timer, get import base import conntrack import cpu +import cpufreq import disk import entropy import interface diff --git a/src/collecty/plugins/cpufreq.py b/src/collecty/plugins/cpufreq.py new file mode 100644 index 0000000..7deeae6 --- /dev/null +++ b/src/collecty/plugins/cpufreq.py @@ -0,0 +1,161 @@ +#!/usr/bin/python +############################################################################### +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2015 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 . # +# # +############################################################################### + +import os +import re + +import base + +from ..i18n import _ + +class GraphTemplateCPUFreq(base.GraphTemplate): + name = "cpufreq" + + lower_limit = 0 + + @property + def graph_title(self): + return _("CPU usage") + + @property + def graph_vertical_label(self): + return "%s [%s]" % (_("Frequency"), _("Hz")) + + def get_object_table(self): + objects_table = {} + + for processor in self.plugin.objects: + objects_table[processor.id] = processor + + return objects_table + + core_colours = { + "cpu0" : "#ff000066", + "cpu1" : "#00ff0066", + "cpu2" : "#0000ff66", + "cpu3" : "#ffff0066", + } + + @property + def rrd_graph(self): + rrd_graph = [] + + for core, processor in sorted(self.object_table.items()): + i = { + "core" : core, + "colour" : self.core_colours.get(core, "#000000"), + "name" : processor.name, + } + + core_graph = [ + "DEF:current_%(core)s=%%(%(core)s)s:current:AVERAGE", + "DEF:minimum_%(core)s=%%(%(core)s)s:minimum:AVERAGE", + "DEF:maximum_%(core)s=%%(%(core)s)s:maximum:AVERAGE", + + "VDEF:avg_%(core)s=current_%(core)s,AVERAGE", + + "LINE2:current_%(core)s%(colour)s:%(name)-10s", + "GPRINT:avg_%(core)s:%%6.2lf %%sHz\l", + ] + + rrd_graph += [line % i for line in core_graph] + + return rrd_graph + + rrd_graph_args = [ + "--base", "1000", # Hz + ] + + +class CPUFreqObject(base.Object): + rrd_schema = [ + "DS:current:GAUGE:0:U", + "DS:minimum:GAUGE:0:U", + "DS:maximum:GAUGE:0:U", + ] + + def __repr__(self): + return "<%s %s>" % (self.__class__.__name__, self.cpuid) + + def init(self, cpuid): + self.cpuid = cpuid + + self.sys_path = os.path.join("/sys/devices/system/cpu", self.cpuid) + + @property + def name(self): + return "Core %s" % self.core_id + + @property + def id(self): + return self.cpuid + + @property + def core_id(self): + return self.read_file("topology/core_id") + + def collect(self): + return ( + self.read_frequency("cpufreq/cpuinfo_cur_freq"), + self.read_frequency("cpufreq/cpuinfo_min_freq"), + self.read_frequency("cpufreq/cpuinfo_max_freq"), + ) + + def read_file(self, filename): + file = os.path.join(self.sys_path, filename) + + with open(file, "r") as f: + return f.read().strip() + + def read_frequency(self, filename): + val = self.read_file(filename) + + # Convert from kHz to Hz + return int(val) * 1000 + + +class CPUFreqPlugin(base.Plugin): + name = "cpufreq" + description = "cpufreq Plugin" + + templates = [GraphTemplateCPUFreq] + + cpuid_pattern = re.compile(r"cpu[0-9]+") + + @property + def objects(self): + core_ids = [] + + for cpuid in os.listdir("/sys/devices/system/cpu"): + if not self.cpuid_pattern.match(cpuid): + continue + + o = CPUFreqObject(self, cpuid) + + # If we have already seen a virtual core of the processor, + # we will skip any others. + if o.core_id in core_ids: + continue + + # Save the ID of the added core + core_ids.append(o.core_id) + + yield o