From 5092475d7f0414726abae26cfafff0d55d61d230 Mon Sep 17 00:00:00 2001 From: nicolargo Date: Sat, 27 Jan 2024 11:20:44 +0100 Subject: Make the Quicklook stats list configurable (TODO on the WebUI) --- conf/glances.conf | 8 +++-- glances/outputs/glances_bars.py | 20 ++++++++--- glances/outputs/glances_sparklines.py | 10 ++++-- glances/plugins/quicklook/__init__.py | 63 ++++++++++++++++++++--------------- 4 files changed, 64 insertions(+), 37 deletions(-) diff --git a/conf/glances.conf b/conf/glances.conf index 75512743..1a489815 100644 --- a/conf/glances.conf +++ b/conf/glances.conf @@ -45,8 +45,11 @@ max_processes_display=25 # Set to true to disable a plugin # Note: you can also disable it from the command line (see --disable-plugin ) disable=False -# Graphical percentage char used in the terminal user interface (default is |) -percentage_char=| +# Stats list (default is cpu,mem,load) +# Available stats are: cpu,mem,load,swap +list=cpu,mem,load +# Graphical bar char used in the terminal user interface (default is |) +bar_char=| # Define CPU, MEM and SWAP thresholds in % cpu_careful=50 cpu_warning=70 @@ -58,6 +61,7 @@ swap_careful=50 swap_warning=70 swap_critical=90 # Source: http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages +# With 1 CPU core, the load should be lower than 1.00 (100%) load_careful=70 load_warning=100 load_critical=500 diff --git a/glances/outputs/glances_bars.py b/glances/outputs/glances_bars.py index f6466a9b..171099bf 100644 --- a/glances/outputs/glances_bars.py +++ b/glances/outputs/glances_bars.py @@ -28,10 +28,14 @@ class Bar(object): """ def __init__(self, size, - percentage_char='|', empty_char=' ', pre_char='[', post_char=']', - display_value=True, min_value=0, max_value=100): + bar_char='|', + empty_char=' ', + pre_char='[', post_char=']', + unit_char='%', + display_value=True, + min_value=0, max_value=100): # Build curses_bars - self.__curses_bars = [empty_char] * 5 + [percentage_char] * 5 + self.__curses_bars = [empty_char] * 5 + [bar_char] * 5 # Bar size self.__size = size # Bar current percent @@ -43,6 +47,8 @@ class Bar(object): self.__pre_char = pre_char self.__post_char = post_char self.__empty_char = empty_char + self.__unit_char = unit_char + # Value should be displayed ? self.__display_value = display_value @property @@ -82,9 +88,13 @@ class Bar(object): ret += self.__empty_char * int(self.size - whole) if self.__display_value: if self.percent > self.max_value: - ret = '{}>{:4.0f}%'.format(ret, self.max_value) + ret = '{}>{:4.0f}{}'.format(ret, + self.max_value, + self.__unit_char) else: - ret = '{}{:5.1f}%'.format(ret, self.percent) + ret = '{}{:5.1f}{}'.format(ret, + self.percent, + self.__unit_char) if overwrite and len(overwrite) < len(ret) - 6: ret = overwrite + ret[len(overwrite):] return ret diff --git a/glances/outputs/glances_sparklines.py b/glances/outputs/glances_sparklines.py index 29c0fbf0..3a5dabf8 100644 --- a/glances/outputs/glances_sparklines.py +++ b/glances/outputs/glances_sparklines.py @@ -35,7 +35,8 @@ class Sparkline(object): """Manage sparklines (see https://pypi.org/project/sparklines/).""" def __init__(self, size, - pre_char='[', post_char=']', empty_char=' ', + pre_char='[', post_char=']', + unit_char='%', display_value=True): # If the sparklines python module available ? self.__available = sparklines_module @@ -46,7 +47,8 @@ class Sparkline(object): # Char used for the decoration self.__pre_char = pre_char self.__post_char = post_char - self.__empty_char = empty_char + self.__unit_char = unit_char + # Value should be displayed ? self.__display_value = display_value @property @@ -83,7 +85,9 @@ class Sparkline(object): if self.__display_value: percents_without_none = [x for x in self.percents if x is not None] if len(percents_without_none) > 0: - ret = '{}{:5.1f}%'.format(ret, percents_without_none[-1]) + ret = '{}{:5.1f}{}'.format(ret, + percents_without_none[-1], + self.__unit_char) ret = nativestr(ret) if overwrite and len(overwrite) < len(ret) - 6: ret = overwrite + ret[len(overwrite):] diff --git a/glances/plugins/quicklook/__init__.py b/glances/plugins/quicklook/__init__.py index 1cfd5682..b1e53bda 100644 --- a/glances/plugins/quicklook/__init__.py +++ b/glances/plugins/quicklook/__init__.py @@ -71,6 +71,9 @@ class PluginModel(GlancesPluginModel): 'stats' is a dictionary. """ + AVAILABLE_STATS_LIST = ['cpu', 'mem', 'swap', 'load'] + DEFAULT_STATS_LIST = ['cpu', 'mem', 'load'] + def __init__(self, args=None, config=None): """Init the quicklook plugin.""" super(PluginModel, self).__init__( @@ -81,6 +84,12 @@ class PluginModel(GlancesPluginModel): # We want to display the stat in the curse interface self.display_curse = True + # Define the stats list + self.stats_list = self.get_conf_value('list', default=self.DEFAULT_STATS_LIST) + if not set(self.stats_list).issubset(self.AVAILABLE_STATS_LIST): + logger.warning('Quicklook plugin: Invalid stats list: {}'.format(self.stats_list)) + self.stats_list = self.AVAILABLE_STATS_LIST + @GlancesPluginModel._check_decorator @GlancesPluginModel._log_result_decorator def update(self): @@ -115,7 +124,7 @@ class PluginModel(GlancesPluginModel): stats['cpucore'] = get_nb_log_core() try: # Load average is a tuple (1 min, 5 min, 15 min) - # Process only the 15 min value + # Process only the 15 min value (index 2) stats['load'] = get_load_average(percent=True)[2] except (TypeError, IndexError): stats['load'] = None @@ -135,7 +144,7 @@ class PluginModel(GlancesPluginModel): super(PluginModel, self).update_views() # Alert for CPU, MEM and SWAP - for key in ['cpu', 'mem', 'swap']: + for key in self.stats_list: if key in self.stats: self.views[key]['decoration'] = self.get_alert(self.stats[key], header=key) @@ -159,14 +168,14 @@ class PluginModel(GlancesPluginModel): return ret # Define the data: Bar (default behavior) or Sparkline - sparkline_tag = False - if self.args.sparkline and self.history_enable() and not self.args.client: - data = Sparkline(max_width) - sparkline_tag = data.available - if not sparkline_tag: - # Fallback to bar if Sparkline module is not installed - data = Bar(max_width, - percentage_char=self.get_conf_value('percentage_char', default=['|'])[0]) + data = dict() + for key in self.stats_list: + if self.args.sparkline and self.history_enable() and not self.args.client: + data[key] = Sparkline(max_width) + else: + # Fallback to bar if Sparkline module is not installed + data[key] = Bar(max_width, + bar_char=self.get_conf_value('bar_char', default=['|'])[0]) # Build the string message ########################## @@ -186,36 +195,36 @@ class PluginModel(GlancesPluginModel): ret.append(self.curse_new_line()) # Loop over CPU, MEM and LOAD - for key in ['cpu', 'mem', 'load']: + for key in self.stats_list: if key == 'cpu' and args.percpu: - if sparkline_tag: - raw_cpu = self.get_raw_history(item='percpu', nb=data.size) + if type(data[key]).__name__ == 'Sparkline': + raw_cpu = self.get_raw_history(item='percpu', nb=data[key].size) for cpu_index, cpu in enumerate(self.stats['percpu']): - if sparkline_tag: + if type(data[key]).__name__ == 'Sparkline': # Sparkline display an history - data.percents = [i[1][cpu_index]['total'] for i in raw_cpu] + data[key].percents = [i[1][cpu_index]['total'] for i in raw_cpu] # A simple padding in order to align metrics to the right - data.percents += [None] * (data.size - len(data.percents)) + data[key].percents += [None] * (data[key].size - len(data[key].percents)) else: # Bar only the last value - data.percent = cpu['total'] + data[key].percent = cpu['total'] if cpu[cpu['key']] < 10: msg = '{:3}{} '.format(key.upper(), cpu['cpu_number']) else: msg = '{:4} '.format(cpu['cpu_number']) - ret.extend(self._msg_create_line(msg, data, key)) + ret.extend(self._msg_create_line(msg, data[key], key)) ret.append(self.curse_new_line()) else: - if sparkline_tag: + if type(data[key]).__name__ == 'Sparkline': # Sparkline display an history - data.percents = [i[1] for i in self.get_raw_history(item=key, nb=data.size)] + data[key].percents = [i[1] for i in self.get_raw_history(item=key, nb=data[key].size)] # A simple padding in order to align metrics to the right - data.percents += [None] * (data.size - len(data.percents)) + data[key].percents += [None] * (data[key].size - len(data[key].percents)) else: # Bar only the last value - data.percent = self.stats[key] + data[key].percent = self.stats[key] msg = '{:4} '.format(key.upper()) - ret.extend(self._msg_create_line(msg, data, key)) + ret.extend(self._msg_create_line(msg, data[key], key)) ret.append(self.curse_new_line()) # Remove the last new line @@ -226,10 +235,10 @@ class PluginModel(GlancesPluginModel): def _msg_create_line(self, msg, data, key): """Create a new line to the Quick view.""" - if key == 'mem' and self.get_alert(self.stats['swap'], header='swap') != 'DEFAULT': - overwrite = 'SWAP' - else: - overwrite = '' + # if key == 'mem' and self.get_alert(self.stats['swap'], header='swap') != 'DEFAULT': + # overwrite = 'SWAP' + # else: + overwrite = '' return [ self.curse_add_line(msg), self.curse_add_line(data.pre_char, decoration='BOLD'), -- cgit v1.2.3