From 1621832567ff096b7407626b27f52b6563de3c1c Mon Sep 17 00:00:00 2001 From: nicolargo Date: Sun, 1 May 2016 21:00:47 +0200 Subject: [PATCH] Almost finished. Just had to correct an issue on the WebUI displaying AMP with empty result --- conf/glances.conf | 40 ++-- glances/client.py | 1 - glances/main.py | 2 - glances/monitor_list.py | 200 ------------------ glances/outputs/glances_curses.py | 14 +- glances/outputs/static/css/style.css | 2 +- glances/outputs/static/html/index.html | 2 +- glances/outputs/static/html/plugins/amps.html | 7 + .../outputs/static/html/plugins/monitor.html | 8 - glances/outputs/static/html/stats.html | 2 +- .../static/js/services/core/glances_stats.js | 2 +- .../{glances_monitor.js => glances_amps.js} | 4 +- glances/outputs/static/js/stats_controller.js | 2 +- glances/plugins/glances_monitor.py | 118 ----------- glances/processes.py | 2 +- glances/server.py | 5 - unitest-restful.py | 4 +- 17 files changed, 34 insertions(+), 381 deletions(-) delete mode 100644 glances/monitor_list.py create mode 100644 glances/outputs/static/html/plugins/amps.html delete mode 100644 glances/outputs/static/html/plugins/monitor.html rename glances/outputs/static/js/services/plugins/{glances_monitor.js => glances_amps.js} (88%) delete mode 100644 glances/plugins/glances_monitor.py diff --git a/conf/glances.conf b/conf/glances.conf index 1726f8e4..9fa40ce3 100644 --- a/conf/glances.conf +++ b/conf/glances.conf @@ -1,3 +1,7 @@ +############################################################################## +# plugins +############################################################################## + [quicklook] # Define CPU, MEM and SWAP thresholds in % cpu_careful=50 @@ -156,31 +160,9 @@ mem_careful=50 mem_warning=70 mem_critical=90 -[monitor] -# Define the list of processes to monitor -# *** This section is optional *** -# The list is composed of items (list_#nb <= 10) -# An item is defined: -# * description: Description of the processes (max 16 chars) -# * regex: regular expression of the processes to monitor -# * command: (optional) full path to shell command/script for extended stat -# Use with caution. Should return a single line string. -# Only execute when at least one process is running -# By default display CPU and MEM % -# Limitation: Do not use in client / server mode -# * countmin: (optional) minimal number of processes -# A warning will be displayed if number of process < count -# * countmax: (optional) maximum number of processes -# A warning will be displayed if number of process > count -list_1_description=Dropbox -list_1_regex=.*dropbox.* -list_1_countmin=1 -list_1_command=dropbox status | head -1 -list_2_description=Python programs -list_2_regex=.*python.* -list_3_description=Famous Xeyes -list_3_regex=.*xeyes.* -list_3_countmin=1 +############################################################################## +# Client/server +############################################################################## [serverlist] # Define the static servers list @@ -204,6 +186,10 @@ list_3_countmin=1 #xps=abc #default=defaultpassword +############################################################################## +# Exports +############################################################################## + [influxdb] # Configuration for the --export-influxdb option # https://influxdb.com/ @@ -251,7 +237,7 @@ user=guest password=guest queue=glances_queue -###### +############################################################################## # AMPS # * enable: Enable (true) or disable (false) the AMP # * regex: Regular expression to filter the process(es) @@ -263,7 +249,7 @@ queue=glances_queue # * countmax: (optional) maximum number of processes # A warning will be displayed if number of process > count # * : Others variables can be defined and used in the AMP script -###### +############################################################################## [amp_dropbox] # Use the default AMP (no dedicated AMP Python script) diff --git a/glances/client.py b/glances/client.py index e93ec4ee..7525af59 100644 --- a/glances/client.py +++ b/glances/client.py @@ -181,7 +181,6 @@ class GlancesClient(object): # Update the stats try: server_stats = json.loads(self.client.getAll()) - server_stats['monitor'] = json.loads(self.client.getAllMonitored()) except socket.error: # Client cannot get server stats return "Disconnected" diff --git a/glances/main.py b/glances/main.py index 4f2baece..e68e443f 100644 --- a/glances/main.py +++ b/glances/main.py @@ -138,8 +138,6 @@ Start the client browser (browser mode):\n\ help='disable network, disk I/O, FS and sensors modules') parser.add_argument('--disable-process', action='store_true', default=False, dest='disable_process', help='disable process module') - parser.add_argument('--disable-monitoring', action='store_true', default=False, - dest='disable_monitor', help='disable monitoring list module') parser.add_argument('--disable-amp', action='store_true', default=False, dest='disable_amp', help='disable applications monitoring process (AMP) module') parser.add_argument('--disable-log', action='store_true', default=False, diff --git a/glances/monitor_list.py b/glances/monitor_list.py deleted file mode 100644 index ad8e3c43..00000000 --- a/glances/monitor_list.py +++ /dev/null @@ -1,200 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of Glances. -# -# Copyright (C) 2015 Nicolargo -# -# 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 -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Glances 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . - -"""Manage the monitor list.""" - -import re -import subprocess - -from glances.compat import range, u -from glances.logger import logger -from glances.processes import glances_processes - - -class MonitorList(object): - - """This class describes the optional monitored processes list. - - The monitored list is a list of 'important' processes to monitor. - - The list (Python list) is composed of items (Python dict). - An item is defined (dict keys): - * description: Description of the processes (max 16 chars) - * regex: regular expression of the processes to monitor - * command: (optional) shell command for extended stat - * countmin: (optional) minimal number of processes - * countmax: (optional) maximum number of processes - """ - - # Maximum number of items in the list - __monitor_list_max_size = 10 - # The list - __monitor_list = [] - - def __init__(self, config): - """Init the monitoring list from the configuration file, if it exists.""" - self.config = config - - if self.config is not None and self.config.has_section('monitor'): - # Process monitoring list - logger.debug("Monitor list configuration detected") - self.__set_monitor_list('monitor', 'list') - else: - self.__monitor_list = [] - - def __set_monitor_list(self, section, key): - """Init the monitored processes list. - - The list is defined in the Glances configuration file. - """ - for l in range(1, self.__monitor_list_max_size + 1): - value = {} - key = "list_" + str(l) + "_" - try: - description = self.config.get_value(section, key + 'description') - regex = self.config.get_value(section, key + 'regex') - command = self.config.get_value(section, key + 'command') - countmin = self.config.get_value(section, key + 'countmin') - countmax = self.config.get_value(section, key + 'countmax') - except Exception as e: - logger.error("Cannot read monitored list: {0}".format(e)) - else: - if description is not None and regex is not None: - # Build the new item - value["description"] = description - try: - re.compile(regex) - except Exception: - continue - else: - value["regex"] = regex - value["command"] = command - value["countmin"] = countmin - value["countmax"] = countmax - value["count"] = None - value["result"] = None - # Add the item to the list - self.__monitor_list.append(value) - - def __str__(self): - return str(self.__monitor_list) - - def __repr__(self): - return self.__monitor_list - - def __getitem__(self, item): - return self.__monitor_list[item] - - def __len__(self): - return len(self.__monitor_list) - - def __get__(self, item, key): - """Meta function to return key value of item. - - Return None if not defined or item > len(list) - """ - if item < len(self.__monitor_list): - try: - return self.__monitor_list[item][key] - except Exception: - return None - else: - return None - - def update(self): - """Update the command result attributed.""" - # Only continue if monitor list is not empty - if len(self.__monitor_list) == 0: - return self.__monitor_list - - # Search monitored processes by a regular expression - processlist = glances_processes.getalllist() - - # Iter upon the monitored list - for i in range(len(self.get())): - monitoredlist = [p for p in processlist for c in p['cmdline'] if re.search(self.regex(i), c) is not None] - self.__monitor_list[i]['count'] = len(monitoredlist) - - # Always get processes CPU and MEM - self.__monitor_list[i]['default_result'] = 'CPU: {0:.1f}% | MEM: {1:.1f}%'.format( - sum([p['cpu_percent'] for p in monitoredlist]), - sum([p['memory_percent'] for p in monitoredlist])) - - if self.command(i) is not None: - # Execute the user command line - try: - self.__monitor_list[i]['result'] = subprocess.check_output(self.command(i), - shell=True) - except subprocess.CalledProcessError: - self.__monitor_list[i]['result'] = 'Error: ' + self.command(i) - except Exception: - self.__monitor_list[i]['result'] = 'Cannot execute command' - - # Only save the first line - try: - self.__monitor_list[i]['result'] = u(self.__monitor_list[i]['result']).split('\n')[0] - except: - self.__monitor_list[i]['result'] = '' - - if self.command(i) is None or self.__monitor_list[i]['result'] == '': - # If there is no command specified in the conf file - # then display CPU and MEM % - self.__monitor_list[i]['result'] = self.__monitor_list[i]['default_result'] - - return self.__monitor_list - - def get(self): - """Return the monitored list (list of dict).""" - return self.__monitor_list - - def set(self, newlist): - """Set the monitored list (list of dict).""" - self.__monitor_list = newlist - - def getAll(self): - # Deprecated: use get() - return self.get() - - def setAll(self, newlist): - # Deprecated: use set() - self.set(newlist) - - def description(self, item): - """Return the description of the item number (item).""" - return self.__get__(item, "description") - - def regex(self, item): - """Return the regular expression of the item number (item).""" - return self.__get__(item, "regex") - - def command(self, item): - """Return the stat command of the item number (item).""" - return self.__get__(item, "command") - - def result(self, item): - """Return the reult command of the item number (item).""" - return self.__get__(item, "result") - - def countmin(self, item): - """Return the minimum number of processes of the item number (item).""" - return self.__get__(item, "countmin") - - def countmax(self, item): - """Return the maximum number of processes of the item number (item).""" - return self.__get__(item, "countmax") diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index 77c94511..a38eb176 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -425,7 +425,7 @@ class _GlancesCurses(object): # 'x' > Delete finished warning and critical logs glances_logs.clean(critical=True) elif self.pressedkey == ord('z'): - # 'z' > Enable/Disable processes stats (count + list + monitor) + # 'z' > Enable/Disable processes stats (count + list + AMPs) # Enable/Disable display self.args.disable_process = not self.args.disable_process # Enable/Disable update @@ -536,8 +536,6 @@ class _GlancesCurses(object): args=self.args) stats_processcount = stats.get_plugin( 'processcount').get_stats_display(args=self.args) - stats_monitor = stats.get_plugin( - 'monitor').get_stats_display(args=self.args) stats_amps = stats.get_plugin( 'amps').get_stats_display(args=self.args) stats_alert = stats.get_plugin( @@ -722,19 +720,15 @@ class _GlancesCurses(object): self.next_line = self.saved_line # Display right sidebar - # ((DOCKER)+PROCESS_COUNT+(MONITORED)+(AMPS)+PROCESS_LIST+ALERT) + # DOCKER+PROCESS_COUNT+AMPS+PROCESS_LIST+ALERT self.new_column() self.new_line() self.display_plugin(stats_docker) - if glances_processes.process_filter is None: - # Do not display stats monitor list if a filter exist - self.new_line() - self.display_plugin(stats_monitor) - self.new_line() - self.display_plugin(stats_amps) self.new_line() self.display_plugin(stats_processcount) self.new_line() + self.display_plugin(stats_amps) + self.new_line() self.display_plugin(stats_processlist, display_optional=(screen_x > 102), display_additional=(not OSX), diff --git a/glances/outputs/static/css/style.css b/glances/outputs/static/css/style.css index 9eb3c6b9..99372d7b 100644 --- a/glances/outputs/static/css/style.css +++ b/glances/outputs/static/css/style.css @@ -133,7 +133,7 @@ body { width: 100%; text-overflow: ellipsis; } -#monitor .process-result { +#amps .process-result { max-width: 300px; overflow: hidden; white-space: nowrap; diff --git a/glances/outputs/static/html/index.html b/glances/outputs/static/html/index.html index fb90052f..0b93ad2d 100644 --- a/glances/outputs/static/html/index.html +++ b/glances/outputs/static/html/index.html @@ -31,7 +31,7 @@ - + diff --git a/glances/outputs/static/html/plugins/amps.html b/glances/outputs/static/html/plugins/amps.html new file mode 100644 index 00000000..a103a366 --- /dev/null +++ b/glances/outputs/static/html/plugins/amps.html @@ -0,0 +1,7 @@ +
+
+
{{ process.name }}
+
{{ process.count }}
+
{{ process.result }}
+
+
diff --git a/glances/outputs/static/html/plugins/monitor.html b/glances/outputs/static/html/plugins/monitor.html deleted file mode 100644 index 40909cee..00000000 --- a/glances/outputs/static/html/plugins/monitor.html +++ /dev/null @@ -1,8 +0,0 @@ -
-
-
{{ process.description }}
-
{{ process.count > 1 ? process.count : '' }}
-
{{ process.count > 0 ? 'RUNNING' : 'NOT RUNNING' }}
-
{{ process.result }}
-
-
diff --git a/glances/outputs/static/html/stats.html b/glances/outputs/static/html/stats.html index 5ea160f1..34912321 100644 --- a/glances/outputs/static/html/stats.html +++ b/glances/outputs/static/html/stats.html @@ -61,7 +61,7 @@
-
+
diff --git a/glances/outputs/static/js/services/core/glances_stats.js b/glances/outputs/static/js/services/core/glances_stats.js index d29dd6e1..313499f1 100644 --- a/glances/outputs/static/js/services/core/glances_stats.js +++ b/glances/outputs/static/js/services/core/glances_stats.js @@ -12,7 +12,7 @@ glancesApp.service('GlancesStats', function($http, $injector, $q, GlancesPlugin) 'load': 'GlancesPluginLoad', 'mem': 'GlancesPluginMem', 'memswap': 'GlancesPluginMemSwap', - 'monitor': 'GlancesPluginMonitor', + 'amps': 'GlancesPluginAmps', 'network': 'GlancesPluginNetwork', 'percpu': 'GlancesPluginPerCpu', 'processcount': 'GlancesPluginProcessCount', diff --git a/glances/outputs/static/js/services/plugins/glances_monitor.js b/glances/outputs/static/js/services/plugins/glances_amps.js similarity index 88% rename from glances/outputs/static/js/services/plugins/glances_monitor.js rename to glances/outputs/static/js/services/plugins/glances_amps.js index f0d8bc93..1a7be44d 100644 --- a/glances/outputs/static/js/services/plugins/glances_monitor.js +++ b/glances/outputs/static/js/services/plugins/glances_amps.js @@ -1,5 +1,5 @@ -glancesApp.service('GlancesPluginMonitor', function() { - var _pluginName = "monitor"; +glancesApp.service('GlancesPluginAmps', function() { + var _pluginName = "amps"; this.processes = []; this.setData = function(data, views) { diff --git a/glances/outputs/static/js/stats_controller.js b/glances/outputs/static/js/stats_controller.js index f75f870a..810c749b 100644 --- a/glances/outputs/static/js/stats_controller.js +++ b/glances/outputs/static/js/stats_controller.js @@ -31,7 +31,7 @@ glancesApp.controller('statsController', function ($scope, $rootScope, $interval $scope.statsLoad = GlancesStats.getPlugin('load'); $scope.statsMem = GlancesStats.getPlugin('mem'); $scope.statsMemSwap = GlancesStats.getPlugin('memswap'); - $scope.statsMonitor = GlancesStats.getPlugin('monitor'); + $scope.statsAmps = GlancesStats.getPlugin('amps'); $scope.statsNetwork = GlancesStats.getPlugin('network'); $scope.statsPerCpu = GlancesStats.getPlugin('percpu'); $scope.statsProcessCount = GlancesStats.getPlugin('processcount'); diff --git a/glances/plugins/glances_monitor.py b/glances/plugins/glances_monitor.py deleted file mode 100644 index 763e1796..00000000 --- a/glances/plugins/glances_monitor.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of Glances. -# -# Copyright (C) 2015 Nicolargo -# -# 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 -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Glances 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . - -"""Monitor plugin.""" - -from glances.compat import u -from glances.monitor_list import MonitorList as glancesMonitorList -from glances.logger import logger -from glances.plugins.glances_plugin import GlancesPlugin - - -class Plugin(GlancesPlugin): - - """Glances monitor plugin.""" - - def __init__(self, args=None): - """Init the plugin.""" - super(Plugin, self).__init__(args=args) - - # We want to display the stat in the curse interface - self.display_curse = True - - # Init stats - self.glances_monitors = None - self.stats = [] - - def load_limits(self, config): - """Load the monitored list from the config file, if it exists.""" - self.glances_monitors = glancesMonitorList(config) - - @GlancesPlugin._log_result_decorator - def update(self): - """Update the monitored list.""" - if self.input_method == 'local': - # Monitor list only available in a full Glances environment - # Check if the glances_monitor instance is init - if self.glances_monitors is None: - return self.stats - - # Update the monitored list (result of command) - self.glances_monitors.update() - - # Put it on the stats var - self.stats = self.glances_monitors.get() - else: - pass - - return self.stats - - def get_alert(self, nbprocess=0, countmin=None, countmax=None, header="", log=False): - """Return the alert status relative to the process number.""" - if nbprocess is None: - return 'OK' - if countmin is None: - countmin = nbprocess - if countmax is None: - countmax = nbprocess - if nbprocess > 0: - if int(countmin) <= int(nbprocess) <= int(countmax): - return 'OK' - else: - return 'WARNING' - else: - if int(countmin) == 0: - return 'OK' - else: - return 'CRITICAL' - - def msg_curse(self, args=None): - """Return the dict to display in the curse interface.""" - # Init the return message - ret = [] - - # Only process if stats exist and display plugin enable... - if not self.stats or args.disable_process or args.disable_monitor: - return ret - - # Build the string message - for m in self.stats: - msg = '{0:<16} '.format(m['description']) - ret.append(self.curse_add_line( - msg, self.get_alert(m['count'], m['countmin'], m['countmax']))) - msg = '{0:<3} '.format(m['count'] if m['count'] > 1 else '') - ret.append(self.curse_add_line(msg)) - msg = '{0:13} '.format('RUNNING' if m['count'] >= 1 else 'NOT RUNNING') - ret.append(self.curse_add_line(msg)) - # Decode to UTF-8 (for Python 2) - try: - msg = u(m['result']) if m['count'] >= 1 else '' - except UnicodeEncodeError: - # Hack if return message contains non UTF-8 compliant char - msg = u(m['default_result']) if m['count'] >= 1 else '' - ret.append(self.curse_add_line(msg, optional=True, splittable=True)) - ret.append(self.curse_new_line()) - - # Delete the last empty line - try: - ret.pop() - except IndexError: - pass - - return ret diff --git a/glances/processes.py b/glances/processes.py index 843e848f..93ba0b71 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -510,7 +510,7 @@ class GlancesProcesses(object): # Next... first = False - # Build the all processes list used by the monitored list + # Build the all processes list used by the AMPs self.allprocesslist = [p for p in itervalues(processdict)] # Clean internals caches if timeout is reached diff --git a/glances/server.py b/glances/server.py index 361599cc..a9bd258b 100644 --- a/glances/server.py +++ b/glances/server.py @@ -156,11 +156,6 @@ class GlancesInstance(object): # Return all the plugins views return json.dumps(self.stats.getAllViewsAsDict()) - def getAllMonitored(self): - # Return the processes monitored list - # return json.dumps(self.monitors.getAll()) - return json.dumps(self.stats.getAll()['monitor']) - def __getattr__(self, item): """Overwrite the getattr method in case of attribute is not found. diff --git a/unitest-restful.py b/unitest-restful.py index b4b17e38..86598563 100755 --- a/unitest-restful.py +++ b/unitest-restful.py @@ -93,8 +93,8 @@ class TestGlances(unittest.TestCase): self.assertTrue(req.ok) if p in ('uptime', 'now'): self.assertIsInstance(req.json(), text_type) - elif p in ('fs', 'monitor', 'percpu', 'sensors', 'alert', 'processlist', - 'diskio', 'hddtemp', 'batpercent', 'network', 'folders', 'amps'): + elif p in ('fs', 'percpu', 'sensors', 'alert', 'processlist', 'diskio', + 'hddtemp', 'batpercent', 'network', 'folders', 'amps'): self.assertIsInstance(req.json(), list) elif p in ('psutilversion', 'help'): pass