diff options
author | nicolargo <nicolas@nicolargo.com> | 2018-04-29 22:15:12 +0200 |
---|---|---|
committer | nicolargo <nicolas@nicolargo.com> | 2018-04-29 22:15:12 +0200 |
commit | 4d32e070870f9dce972d6b0d9b2c7357ad49b345 (patch) | |
tree | 5d57788004a0f8d60a6a78b9a6667c53fc771e60 | |
parent | e3e1aaf303872ec1f4447900a56d1e54c744260d (diff) |
Stats updated during export (thread issue) #1250
31 files changed, 373 insertions, 435 deletions
@@ -51,6 +51,7 @@ Bugs corrected: * [WEB UI] Minor issue on the Web UI #1240 * [Glances 3.0 RC1] Client/Server is broken #1244 * Fixing horizontal scrolling #1248 + * Stats updated during export (thread issue) #1250 Backward-incompatible changes: diff --git a/glances/__init__.py b/glances/__init__.py index b97d62a8..bf0bbe2d 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -27,7 +27,7 @@ import signal import sys # Global name -__version__ = '3.0.rc2' +__version__ = '3.0.rc3' __author__ = 'Nicolas Hennion <nicolas@nicolargo.com>' __license__ = 'LGPLv3' diff --git a/glances/plugins/glances_alert.py b/glances/plugins/glances_alert.py index e1c4ec62..159254c7 100644 --- a/glances/plugins/glances_alert.py +++ b/glances/plugins/glances_alert.py @@ -85,7 +85,8 @@ class Plugin(GlancesPlugin): def __init__(self, args=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args) + super(Plugin, self).__init__(args=args, + stats_init_value=[]) # We want to display the stat in the curse interface self.display_curse = True @@ -93,13 +94,6 @@ class Plugin(GlancesPlugin): # Set the message position self.align = 'bottom' - # Init the stats - self.reset() - - def reset(self): - """Reset/init the stats.""" - self.stats = [] - def update(self): """Nothing to do here. Just return the global glances_log.""" # Set the stats to the glances_logs diff --git a/glances/plugins/glances_amps.py b/glances/plugins/glances_amps.py index 9b85fe88..797556a0 100644 --- a/glances/plugins/glances_amps.py +++ b/glances/plugins/glances_amps.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2017 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2018 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -29,7 +29,8 @@ class Plugin(GlancesPlugin): def __init__(self, args=None, config=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args) + super(Plugin, self).__init__(args=args, + stats_init_value=[]) self.args = args self.config = config @@ -39,35 +40,30 @@ class Plugin(GlancesPlugin): # Init the list of AMP (classe define in the glances/amps_list.py script) self.glances_amps = glancesAmpsList(self.args, self.config) - # Init stats - self.reset() - - def reset(self): - """Reset/init the stats.""" - self.stats = [] - @GlancesPlugin._check_decorator @GlancesPlugin._log_result_decorator def update(self): """Update the AMP list.""" - # Reset stats - self.reset() + # Init new stats + stats = self.get_init_value() if self.input_method == 'local': for k, v in iteritems(self.glances_amps.update()): - # self.stats.append({k: v.result()}) - self.stats.append({'key': k, - 'name': v.NAME, - 'result': v.result(), - 'refresh': v.refresh(), - 'timer': v.time_until_refresh(), - 'count': v.count(), - 'countmin': v.count_min(), - 'countmax': v.count_max()}) + stats.append({'key': k, + 'name': v.NAME, + 'result': v.result(), + 'refresh': v.refresh(), + 'timer': v.time_until_refresh(), + 'count': v.count(), + 'countmin': v.count_min(), + 'countmax': v.count_max()}) else: # Not available in SNMP mode pass + # Update the stats + self.stats = stats + return self.stats def get_alert(self, nbprocess=0, countmin=None, countmax=None, header="", log=False): diff --git a/glances/plugins/glances_batpercent.py b/glances/plugins/glances_batpercent.py index c8aa5944..df7d9a77 100644 --- a/glances/plugins/glances_batpercent.py +++ b/glances/plugins/glances_batpercent.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2017 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2018 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -51,7 +51,8 @@ class Plugin(GlancesPlugin): def __init__(self, args=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args) + super(Plugin, self).__init__(args=args, + stats_init_value=[]) # Init the sensor class self.glancesgrabbat = GlancesGrabBat() @@ -60,30 +61,26 @@ class Plugin(GlancesPlugin): # The HDD temp is displayed within the sensors plugin self.display_curse = False - # Init stats - self.reset() - - def reset(self): - """Reset/init the stats.""" - self.stats = [] - @GlancesPlugin._check_decorator @GlancesPlugin._log_result_decorator def update(self): """Update battery capacity stats using the input method.""" - # Reset stats - self.reset() + # Init new stats + stats = self.get_init_value() if self.input_method == 'local': # Update stats self.glancesgrabbat.update() - self.stats = self.glancesgrabbat.get() + stats = self.glancesgrabbat.get() elif self.input_method == 'snmp': # Update stats using SNMP # Not avalaible pass + # Update the stats + self.stats = stats + return self.stats diff --git a/glances/plugins/glances_cloud.py b/glances/plugins/glances_cloud.py index 9ef29970..6f512e8c 100644 --- a/glances/plugins/glances_cloud.py +++ b/glances/plugins/glances_cloud.py @@ -67,10 +67,6 @@ class Plugin(GlancesPlugin): # Run the thread self.aws_ec2. start() - def reset(self): - """Reset/init the stats.""" - self.stats = {} - def exit(self): """Overwrite the exit method to close threads.""" self.aws_ec2.stop() @@ -84,21 +80,24 @@ class Plugin(GlancesPlugin): Return the stats (dict) """ - # Reset stats - self.reset() + # Init new stats + stats = self.get_init_value() # Requests lib is needed to get stats from the Cloud API if import_error_tag: - return self.stats + return stats # Update the stats if self.input_method == 'local': # Example: - # self.stats = {'ami-id': 'ami-id', - # 'instance-id': 'instance-id', - # 'instance-type': 'instance-type', - # 'region': 'placement/availability-zone'} - self.stats = self.aws_ec2.stats + # stats = {'ami-id': 'ami-id', + # 'instance-id': 'instance-id', + # 'instance-type': 'instance-type', + # 'region': 'placement/availability-zone'} + stats = self.aws_ec2.stats + + # Update the stats + self.stats = stats return self.stats diff --git a/glances/plugins/glances_core.py b/glances/plugins/glances_core.py index cfdf16a6..15d8025c 100644 --- a/glances/plugins/glances_core.py +++ b/glances/plugins/glances_core.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2017 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2018 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -40,20 +40,13 @@ class Plugin(GlancesPlugin): # The core number is displayed by the load plugin self.display_curse = False - # Init the stat - self.reset() - - def reset(self): - """Reset/init the stat using the input method.""" - self.stats = {} - def update(self): """Update core stats. Stats is a dict (with both physical and log cpu number) instead of a integer. """ - # Reset the stats - self.reset() + # Init new stats + stats = self.get_init_value() if self.input_method == 'local': # Update stats using the standard system lib @@ -64,8 +57,8 @@ class Plugin(GlancesPlugin): # - log: logical CPUs in the system # Return None if undefine try: - self.stats["phys"] = psutil.cpu_count(logical=False) - self.stats["log"] = psutil.cpu_count() + stats["phys"] = psutil.cpu_count(logical=False) + stats["log"] = psutil.cpu_count() except NameError: self.reset() @@ -74,4 +67,7 @@ class Plugin(GlancesPlugin): # http://stackoverflow.com/questions/5662467/how-to-find-out-the-number-of-cpus-using-snmp pass + # Update the stats + self.stats = stats + return self.stats diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index cc824470..32a913ef 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -66,31 +66,27 @@ class Plugin(GlancesPlugin): # We want to display the stat in the curse interface self.display_curse = True - # Init stats - self.reset() - # Call CorePlugin in order to display the core number try: self.nb_log_core = CorePlugin(args=self.args).update()["log"] except Exception: self.nb_log_core = 1 - def reset(self): - """Reset/init the stats.""" - self.stats = {} - @GlancesPlugin._check_decorator @GlancesPlugin._log_result_decorator def update(self): """Update CPU stats using the input method.""" - # Reset stats - self.reset() # Grab stats into self.stats if self.input_method == 'local': - self.update_local() + stats = self.update_local() elif self.input_method == 'snmp': - self.update_snmp() + stats = self.update_snmp() + else: + stats = self.get_init_value() + + # Update the stats + self.stats = stats return self.stats @@ -101,12 +97,16 @@ class Plugin(GlancesPlugin): # 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() + + # Init new stats + stats = self.get_init_value() + + 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) + stats[stat] = getattr(cpu_times_percent, stat) # Additional CPU stats (number of events not as a %; psutil>=4.1.0) # ctx_switches: number of context switches (voluntary + involuntary) per second @@ -126,18 +126,24 @@ class Plugin(GlancesPlugin): else: for stat in cpu_stats._fields: if getattr(cpu_stats, stat) is not None: - self.stats[stat] = getattr(cpu_stats, stat) - getattr(self.cpu_stats_old, stat) + stats[stat] = getattr(cpu_stats, stat) - getattr(self.cpu_stats_old, stat) - self.stats['time_since_update'] = time_since_update + stats['time_since_update'] = time_since_update # Core number is needed to compute the CTX switch limit - self.stats['cpucore'] = self.nb_log_core + stats['cpucore'] = self.nb_log_core # Save stats to compute next step self.cpu_stats_old = cpu_stats + return stats + def update_snmp(self): """Update CPU stats using SNMP.""" + + # Init new stats + stats = self.get_init_value() + # Update stats using SNMP if self.short_system_name in ('windows', 'esxi'): # Windows or VMWare ESXi @@ -150,35 +156,36 @@ class Plugin(GlancesPlugin): self.reset() # Iter through CPU and compute the idle CPU stats - self.stats['nb_log_core'] = 0 - self.stats['idle'] = 0 + stats['nb_log_core'] = 0 + 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'] + stats['idle'] += float(cpu_stats['percent.3']) + stats['nb_log_core'] += 1 + if stats['nb_log_core'] > 0: + stats['idle'] = stats['idle'] / stats['nb_log_core'] + stats['idle'] = 100 - stats['idle'] + stats['total'] = 100 - stats['idle'] else: # Default behavor try: - self.stats = self.get_stats_snmp( + stats = self.get_stats_snmp( snmp_oid=snmp_oid[self.short_system_name]) except KeyError: - self.stats = self.get_stats_snmp( + stats = self.get_stats_snmp( snmp_oid=snmp_oid['default']) - if self.stats['idle'] == '': + if 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'] + for key in iterkeys(stats): + stats[key] = float(stats[key]) + stats['total'] = 100 - stats['idle'] + + return stats def update_views(self): """Update stats views.""" diff --git a/glances/plugins/glances_diskio.py b/glances/plugins/glances_diskio.py index 8ec3e312..535c8f5c 100644 --- a/glances/plugins/glances_diskio.py +++ b/glances/plugins/glances_diskio.py @@ -43,28 +43,23 @@ class Plugin(GlancesPlugin): def __init__(self, args=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args, items_history_list=items_history_list) + super(Plugin, self).__init__(args=args, + items_history_list=items_history_list, + stats_init_value=[]) # We want to display the stat in the curse interface self.display_curse = True - # Init the stats - self.reset() - def get_key(self): """Return the key of the list.""" return 'disk_name' - def reset(self): - """Reset/init the stats.""" - self.stats = [] - @GlancesPlugin._check_decorator @GlancesPlugin._log_result_decorator def update(self): """Update disk I/O stats using the input method.""" - # Reset stats - self.reset() + # Init new stats + stats = self.get_init_value() if self.input_method == 'local': # Update stats using the standard system lib @@ -78,7 +73,7 @@ class Plugin(GlancesPlugin): try: diskiocounters = psutil.disk_io_counters(perdisk=True) except Exception: - return self.stats + return stats # Previous disk IO stats are stored in the diskio_old variable if not hasattr(self, 'diskio_old'): @@ -127,7 +122,7 @@ class Plugin(GlancesPlugin): continue else: diskstat['key'] = self.get_key() - self.stats.append(diskstat) + stats.append(diskstat) # Save stats to compute next bitrate self.diskio_old = diskio_new @@ -136,6 +131,9 @@ class Plugin(GlancesPlugin): # No standard way for the moment... pass + # Update the stats + self.stats = stats + return self.stats def update_views(self): diff --git a/glances/plugins/glances_docker.py b/glances/plugins/glances_docker.py index 08a875ff..fc396a3f 100644 --- a/glances/plugins/glances_docker.py +++ b/glances/plugins/glances_docker.py @@ -90,9 +90,6 @@ class Plugin(GlancesPlugin): # value: instance of ThreadDockerGrabber self.thread_list = {} - # Init the stats - self.reset() - def exit(self): """Overwrite the exit method to close threads.""" for t in itervalues(self.thread_list): @@ -127,10 +124,6 @@ class Plugin(GlancesPlugin): return ret - def reset(self): - """Reset/init the stats.""" - self.stats = {} - def _all_tag(self): """Return the all tag of the Glances/Docker configuration file. @@ -148,8 +141,8 @@ class Plugin(GlancesPlugin): @GlancesPlugin._log_result_decorator def update(self): """Update Docker stats using the input method.""" - # Reset stats - self.reset() + # Init new stats + stats = self.get_init_value() # The Docker-py lib is mandatory if import_error_tag: @@ -169,7 +162,7 @@ class Plugin(GlancesPlugin): # "GoVersion": "go1.3.3" # } try: - self.stats['version'] = self.docker_client.version() + stats['version'] = self.docker_client.version() except Exception as e: # Correct issue#649 logger.error("{} plugin - Cannot get Docker version ({})".format(self.plugin_name, e)) @@ -204,7 +197,7 @@ class Plugin(GlancesPlugin): del self.thread_list[container_id] # Get stats for all containers - self.stats['containers'] = [] + stats['containers'] = [] for container in containers: # Init the stats for the current container container_stats = {} @@ -245,13 +238,16 @@ class Plugin(GlancesPlugin): container_stats['network_rx'] = None container_stats['network_tx'] = None # Add current container stats to the stats list - self.stats['containers'].append(container_stats) + stats['containers'].append(container_stats) elif self.input_method == 'snmp': # Update stats using SNMP # Not available pass + # Update the stats + self.stats = stats + return self.stats def get_docker_cpu(self, container_id, all_stats): diff --git a/glances/plugins/glances_folders.py b/glances/plugins/glances_folders.py index f9bee535..f5275482 100644 --- a/glances/plugins/glances_folders.py +++ b/glances/plugins/glances_folders.py @@ -31,23 +31,19 @@ class Plugin(GlancesPlugin): def __init__(self, args=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args) + super(Plugin, self).__init__(args=args, + stats_init_value=[]) # We want to display the stat in the curse interface self.display_curse = True # Init stats self.glances_folders = None - self.reset() def get_key(self): """Return the key of the list.""" return 'path' - def reset(self): - """Reset/init the stats.""" - self.stats = [] - def load_limits(self, config): """Load the foldered list from the config file, if it exists.""" self.glances_folders = glancesFolderList(config) @@ -56,8 +52,8 @@ class Plugin(GlancesPlugin): @GlancesPlugin._log_result_decorator def update(self): """Update the foldered list.""" - # Reset the list - self.reset() + # Init new stats + stats = self.get_init_value() if self.input_method == 'local': # Folder list only available in a full Glances environment @@ -69,10 +65,13 @@ class Plugin(GlancesPlugin): self.glances_folders.update() # Put it on the stats var - self.stats = self.glances_folders.get() + stats = self.glances_folders.get() else: pass + # Update the stats + self.stats = stats + return self.stats def get_alert(self, stat): diff --git a/glances/plugins/glances_fs.py b/glances/plugins/glances_fs.py index 6dfef0c1..5e229b3d 100644 --- a/glances/plugins/glances_fs.py +++ b/glances/plugins/glances_fs.py @@ -71,28 +71,23 @@ class Plugin(GlancesPlugin): def __init__(self, args=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args, items_history_list=items_history_list) + super(Plugin, self).__init__(args=args, + items_history_list=items_history_list, + stats_init_value=[]) # We want to display the stat in the curse interface self.display_curse = True - # Init the stats - self.reset() - def get_key(self): """Return the key of the list.""" return 'mnt_point' - def reset(self): - """Reset/init the stats.""" - self.stats = [] - @GlancesPlugin._check_decorator @GlancesPlugin._log_result_decorator def update(self): """Update the FS stats using the input method.""" - # Reset the list - self.reset() + # Init new stats + stats = self.get_init_value() if self.input_method == 'local': # Update stats using the standard system lib @@ -136,7 +131,7 @@ class Plugin(GlancesPlugin): 'free': fs_usage.free, 'percent': fs_usage.percent, 'key': self.get_key()} - self.stats.append(fs_current) + stats.append(fs_current) elif self.input_method == 'snmp': # Update stats using SNMP @@ -166,7 +161,7 @@ class Plugin(GlancesPlugin): 'used': used, 'percent': percent, 'key': self.get_key()} - self.stats.append(fs_current) + stats.append(fs_current) else: # Default behavior for fs in fs_stat: @@ -177,7 +172,10 @@ class Plugin(GlancesPlugin): 'used': int(fs_stat[fs]['used']) * 1024, 'percent': float(fs_stat[fs]['percent']), 'key': self.get_key()} - self.stats.append(fs_current) + stats.append(fs_current) + + # Update the stats + self.stats = stats return self.stats diff --git a/glances/plugins/glances_gpu.py b/glances/plugins/glances_gpu.py index fc6c2367..19826811 100644 --- a/glances/plugins/glances_gpu.py +++ b/glances/plugins/glances_gpu.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2017 Kirby Banman <kirby.banman@gmail.com> +# Copyright (C) 2018 Kirby Banman <kirby.banman@gmail.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -41,7 +41,8 @@ class Plugin(GlancesPlugin): def __init__(self, args=None): """Init the plugin.""" - super(Plugin, self).__init__(args=args) + super(Plugin, self).__init__(args=args, + stats_init_value=[]) # Init the NVidia API self.init_nvidia() @@ -49,13 +50,6 @@ class Plugin(GlancesPlugin): # We want to display the stat in the curse interface self.display_curse = True - # Init the stats - self.reset() - - def reset(self): - """Reset/init the stats.""" |