From 34a500e3ed2f65bc5bf9b105427bb98f544b7b32 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Thu, 31 Mar 2016 12:30:14 +0200 Subject: [PATCH] CPU additionnal stats monitoring: Context switch, Interrupts... (issue #810) --- NEWS | 1 + conf/glances.conf | 5 + docs/_static/cpu-wide.png | Bin 15160 -> 30307 bytes docs/aoa/cpu.rst | 18 ++- docs/man/glances.1 | 2 +- glances/plugins/glances_cpu.py | 192 +++++++++++++++++++-------- glances/plugins/glances_diskio.py | 2 +- glances/plugins/glances_load.py | 2 +- glances/plugins/glances_plugin.py | 4 + glances/plugins/glances_quicklook.py | 15 ++- 10 files changed, 175 insertions(+), 66 deletions(-) diff --git a/NEWS b/NEWS index 04d1be6a..aa2b8dd0 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ Version 2.7 Enhancements and new features: + * CPU additionnal stats monitoring: Context switch, Interrupts... (issue #810) * [Folders] Differentiate permission issue and non-existence of a directory (issue #828) * [Web UI] add cpu name in quicklook plugin (issue #825) diff --git a/conf/glances.conf b/conf/glances.conf index d836cb66..594d0138 100644 --- a/conf/glances.conf +++ b/conf/glances.conf @@ -28,6 +28,11 @@ steal_careful=50 steal_warning=70 steal_critical=90 #steal_log=True +# Context switch limit per core / second +# For example, if you have 2 Core, critical limit will be 28000/sec +ctx_switches_careful=10000 +ctx_switches_warning=12000 +ctx_switches_critical=14000 [percpu] # Define CPU thresholds in % diff --git a/docs/_static/cpu-wide.png b/docs/_static/cpu-wide.png index 6d2cc697282b3a2ea54201e0e5679ec97dcbeb3a..1046b7d82d0993a91b513673a67ba461aca6be3d 100644 GIT binary patch literal 30307 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 0: - self.stats['idle'] = self.stats[ - 'idle'] / self.stats['nb_log_core'] - self.stats['idle'] = 100 - self.stats['idle'] - self.stats['total'] = 100 - self.stats['idle'] - - else: - # Default behavor - try: - self.stats = self.get_stats_snmp( - snmp_oid=snmp_oid[self.short_system_name]) - except KeyError: - self.stats = self.get_stats_snmp( - snmp_oid=snmp_oid['default']) - - if self.stats['idle'] == '': - self.reset() - return self.stats - - # Convert SNMP stats to float - for key in iterkeys(self.stats): - self.stats[key] = float(self.stats[key]) - self.stats['total'] = 100 - self.stats['idle'] + self.update_snmp() # Update the history list self.update_stats_history() @@ -139,6 +98,96 @@ class Plugin(GlancesPlugin): return self.stats + def update_local(self): + """Update CPU stats using PSUtil.""" + # Grab CPU stats using psutil's cpu_percent and cpu_times_percent + # Get all possible values for CPU stats: user, system, idle, + # nice (UNIX), iowait (Linux), irq (Linux, FreeBSD), steal (Linux 2.6.11+) + # The following stats are returned by the API but not displayed in the UI: + # softirq (Linux), guest (Linux 2.6.24+), guest_nice (Linux 3.2.0+) + self.stats['total'] = cpu_percent.get() + cpu_times_percent = psutil.cpu_times_percent(interval=0.0) + for stat in ['user', 'system', 'idle', 'nice', 'iowait', + 'irq', 'softirq', 'steal', 'guest', 'guest_nice']: + if hasattr(cpu_times_percent, stat): + self.stats[stat] = getattr(cpu_times_percent, stat) + + # Additionnal CPU stats (number of events / not as a %) + # ctx_switches: number of context switches (voluntary + involuntary) per second + # interrupts: number of interrupts per second + # soft_interrupts: number of software interrupts per second. Always set to 0 on Windows and SunOS. + # syscalls: number of system calls since boot. Always set to 0 on Linux. + try: + cpu_stats = psutil.cpu_stats() + except AttributeError: + # cpu_stats only available with PSUtil 4.1 or + + pass + else: + # By storing time data we enable Rx/s and Tx/s calculations in the + # XML/RPC API, which would otherwise be overly difficult work + # for users of the API + time_since_update = getTimeSinceLastUpdate('cpu') + + # Previous CPU stats are stored in the cpu_stats_old variable + if not hasattr(self, 'cpu_stats_old'): + # First call, we init the cpu_stats_old var + self.cpu_stats_old = cpu_stats + else: + for stat in cpu_stats._fields: + self.stats[stat] = getattr(cpu_stats, stat) - getattr(self.cpu_stats_old, stat) + + self.stats['time_since_update'] = time_since_update + + # Core number is needed to compute the CTX switch limit + self.stats['cpucore'] = self.nb_log_core + + # Save stats to compute next step + self.cpu_stats_old = cpu_stats + + def update_snmp(self): + """Update CPU stats using SNMP.""" + # Update stats using SNMP + if self.short_system_name in ('windows', 'esxi'): + # Windows or VMWare ESXi + # You can find the CPU utilization of windows system by querying the oid + # Give also the number of core (number of element in the table) + try: + cpu_stats = self.get_stats_snmp(snmp_oid=snmp_oid[self.short_system_name], + bulk=True) + except KeyError: + self.reset() + + # Iter through CPU and compute the idle CPU stats + self.stats['nb_log_core'] = 0 + self.stats['idle'] = 0 + for c in cpu_stats: + if c.startswith('percent'): + self.stats['idle'] += float(cpu_stats['percent.3']) + self.stats['nb_log_core'] += 1 + if self.stats['nb_log_core'] > 0: + self.stats['idle'] = self.stats[ + 'idle'] / self.stats['nb_log_core'] + self.stats['idle'] = 100 - self.stats['idle'] + self.stats['total'] = 100 - self.stats['idle'] + + else: + # Default behavor + try: + self.stats = self.get_stats_snmp( + snmp_oid=snmp_oid[self.short_system_name]) + except KeyError: + self.stats = self.get_stats_snmp( + snmp_oid=snmp_oid['default']) + + if self.stats['idle'] == '': + self.reset() + return self.stats + + # Convert SNMP stats to float + for key in iterkeys(self.stats): + self.stats[key] = float(self.stats[key]) + self.stats['total'] = 100 - self.stats['idle'] + def update_views(self): """Update stats views.""" # Call the father's method @@ -153,8 +202,12 @@ class Plugin(GlancesPlugin): for key in ['steal', 'total']: if key in self.stats: self.views[key]['decoration'] = self.get_alert(self.stats[key], header=key) + # Alert only but depend on Core number + for key in ['ctx_switches']: + if key in self.stats: + self.views[key]['decoration'] = self.get_alert(self.stats[key], maximum=100 * self.stats['cpucore'], header=key) # Optional - for key in ['nice', 'irq', 'iowait', 'steal']: + for key in ['nice', 'irq', 'iowait', 'steal', 'ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls']: if key in self.stats: self.views[key]['optional'] = True @@ -171,6 +224,7 @@ class Plugin(GlancesPlugin): # If user stat is not here, display only idle / total CPU usage (for # exemple on Windows OS) idle_tag = 'user' not in self.stats + # Header msg = '{0:8}'.format('CPU') ret.append(self.curse_add_line(msg, "TITLE")) @@ -187,6 +241,15 @@ class Plugin(GlancesPlugin): ret.append(self.curse_add_line(msg, optional=self.get_views(key='nice', option='optional'))) msg = '{0:>5}%'.format(self.stats['nice']) ret.append(self.curse_add_line(msg, optional=self.get_views(key='nice', option='optional'))) + # ctx_switches + if 'ctx_switches' in self.stats: + msg = ' {0:8}'.format('ctx_sw:') + ret.append(self.curse_add_line(msg, optional=self.get_views(key='ctx_switches', option='optional'))) + msg = '{0:>5}'.format(int(self.stats['ctx_switches'] // self.stats['time_since_update'])) + ret.append(self.curse_add_line( + msg, self.get_views(key='ctx_switches', option='decoration'), + optional=self.get_views(key='ctx_switches', option='optional'))) + # New line ret.append(self.curse_new_line()) # User CPU @@ -207,6 +270,13 @@ class Plugin(GlancesPlugin): ret.append(self.curse_add_line(msg, optional=self.get_views(key='irq', option='optional'))) msg = '{0:>5}%'.format(self.stats['irq']) ret.append(self.curse_add_line(msg, optional=self.get_views(key='irq', option='optional'))) + # interrupts + if 'interrupts' in self.stats: + msg = ' {0:8}'.format('inter:') + ret.append(self.curse_add_line(msg, optional=self.get_views(key='interrupts', option='optional'))) + msg = '{0:>5}'.format(int(self.stats['interrupts'] // self.stats['time_since_update'])) + ret.append(self.curse_add_line(msg, optional=self.get_views(key='interrupts', option='optional'))) + # New line ret.append(self.curse_new_line()) # System CPU @@ -229,6 +299,13 @@ class Plugin(GlancesPlugin): ret.append(self.curse_add_line( msg, self.get_views(key='iowait', option='decoration'), optional=self.get_views(key='iowait', option='optional'))) + # soft_interrupts + if 'soft_interrupts' in self.stats: + msg = ' {0:8}'.format('sw_int:') + ret.append(self.curse_add_line(msg, optional=self.get_views(key='soft_interrupts', option='optional'))) + msg = '{0:>5}'.format(int(self.stats['soft_interrupts'] // self.stats['time_since_update'])) + ret.append(self.curse_add_line(msg, optional=self.get_views(key='soft_interrupts', option='optional'))) + # New line ret.append(self.curse_new_line()) # Idle CPU @@ -245,6 +322,13 @@ class Plugin(GlancesPlugin): ret.append(self.curse_add_line( msg, self.get_views(key='steal', option='decoration'), optional=self.get_views(key='steal', option='optional'))) + # syscalls + # syscalls: number of system calls since boot. Always set to 0 on Linux. (do not display) + if 'syscalls' in self.stats and not LINUX: + msg = ' {0:8}'.format('syscal:') + ret.append(self.curse_add_line(msg, optional=self.get_views(key='syscalls', option='optional'))) + msg = '{0:>5}'.format(int(self.stats['syscalls'] // self.stats['time_since_update'])) + ret.append(self.curse_add_line(msg, optional=self.get_views(key='syscalls', option='optional'))) # Return the message with decoration return ret diff --git a/glances/plugins/glances_diskio.py b/glances/plugins/glances_diskio.py index 1439bfa4..ffb346f7 100644 --- a/glances/plugins/glances_diskio.py +++ b/glances/plugins/glances_diskio.py @@ -81,7 +81,7 @@ class Plugin(GlancesPlugin): # Previous disk IO stats are stored in the diskio_old variable if not hasattr(self, 'diskio_old'): - # First call, we init the network_old var + # First call, we init the diskio_old var try: self.diskio_old = diskiocounters except (IOError, UnboundLocalError): diff --git a/glances/plugins/glances_load.py b/glances/plugins/glances_load.py index 38a2fad8..b0388338 100644 --- a/glances/plugins/glances_load.py +++ b/glances/plugins/glances_load.py @@ -62,7 +62,7 @@ class Plugin(GlancesPlugin): try: self.nb_log_core = CorePlugin(args=self.args).update()["log"] except Exception: - self.nb_log_core = 0 + self.nb_log_core = 1 def reset(self): """Reset/init the stats.""" diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index b38c4892..bda8c8a5 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -403,6 +403,8 @@ class GlancesPlugin(object): except KeyError: return 'DEFAULT' + logger.debug("{0} => ret = {1}".format(stat_name, ret)) + # Manage log log_str = "" if self.__get_limit_log(stat_name=stat_name, default_action=log): @@ -455,6 +457,8 @@ class GlancesPlugin(object): # Exemple: network_careful limit = self._limits[self.plugin_name + '_' + criticity] + # logger.debug("{0} {1} value is {2}".format(stat_name, criticity, limit)) + # Return the limit return limit diff --git a/glances/plugins/glances_quicklook.py b/glances/plugins/glances_quicklook.py index 5c9feca0..d0c25839 100644 --- a/glances/plugins/glances_quicklook.py +++ b/glances/plugins/glances_quicklook.py @@ -113,13 +113,14 @@ class Plugin(GlancesPlugin): bar = Bar(max_width) # Build the string message - if 'cpu_name' in self.stats: - msg = '{0} - {1:.2f}/{2:.2f}GHz'.format(self.stats['cpu_name'], - self._hz_to_ghz(self.stats['cpu_hz_current']), - self._hz_to_ghz(self.stats['cpu_hz'])) - if len(msg) - 6 <= max_width: - ret.append(self.curse_add_line(msg)) - ret.append(self.curse_new_line()) + if 'cpu_name' in self.stats and 'cpu_hz_current' in self.stats and 'cpu_hz' in self.stats: + msg_name = '{0} - '.format(self.stats['cpu_name']) + msg_freq = '{0:.2f}/{1:.2f}GHz'.format(self._hz_to_ghz(self.stats['cpu_hz_current']), + self._hz_to_ghz(self.stats['cpu_hz'])) + if len(msg_name + msg_freq) - 6 <= max_width: + ret.append(self.curse_add_line(msg_name)) + ret.append(self.curse_add_line(msg_freq)) + ret.append(self.curse_new_line()) for key in ['cpu', 'mem', 'swap']: if key == 'cpu' and args.percpu: for cpu in self.stats['percpu']: -- GitLab