summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS29
-rw-r--r--README.rst5
-rw-r--r--conf/glances.conf23
-rw-r--r--docs/_static/cpu-wide.pngbin30307 -> 8563 bytes
-rw-r--r--docs/_static/cpu.pngbin7519 -> 4504 bytes
-rw-r--r--docs/_static/mem-wide.pngbin23457 -> 9404 bytes
-rw-r--r--docs/_static/mem.pngbin13587 -> 5994 bytes
-rw-r--r--docs/_static/ports.pngbin10291 -> 11041 bytes
-rw-r--r--docs/_static/trend.pngbin0 -> 23021 bytes
-rw-r--r--docs/aoa/actions.rst10
-rw-r--r--docs/aoa/cpu.rst17
-rw-r--r--docs/aoa/memory.rst11
-rw-r--r--docs/aoa/ports.rst19
-rw-r--r--docs/man/glances.12
-rw-r--r--glances/__init__.py2
-rw-r--r--glances/actions.py9
-rw-r--r--glances/attribute.py4
-rw-r--r--glances/compat.py9
-rw-r--r--glances/exports/glances_export.py8
-rw-r--r--glances/exports/glances_statsd.py18
-rw-r--r--glances/history.py4
-rw-r--r--glances/outputs/glances_curses.py33
-rw-r--r--glances/outputs/static/html/plugins/cpu.html2
-rw-r--r--glances/outputs/static/html/plugins/mem_more.html4
-rw-r--r--glances/outputs/static/js/services/plugins/processlist.js4
-rw-r--r--glances/outputs/static/public/js/main.min.js4
-rw-r--r--glances/outputs/static/public/js/templates.min.js4
-rw-r--r--glances/plugins/glances_alert.py76
-rw-r--r--glances/plugins/glances_cpu.py13
-rw-r--r--glances/plugins/glances_fs.py3
-rw-r--r--glances/plugins/glances_gpu.py70
-rw-r--r--glances/plugins/glances_mem.py4
-rw-r--r--glances/plugins/glances_memswap.py4
-rw-r--r--glances/plugins/glances_plugin.py131
-rw-r--r--glances/plugins/glances_ports.py134
-rw-r--r--glances/plugins/glances_uptime.py4
-rw-r--r--glances/server.py1
-rw-r--r--glances/stats.py14
-rw-r--r--glances/stats_client.py19
-rw-r--r--glances/thresholds.py116
-rw-r--r--glances/web_list.py113
-rwxr-xr-xsetup.py4
-rwxr-xr-xunitest-xmlrpc.py9
-rwxr-xr-xunitest.py25
44 files changed, 801 insertions, 160 deletions
diff --git a/NEWS b/NEWS
index e794b711..0b268a49 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,33 @@
Glances Version 2
==============================================================================
+Version 2.10
+============
+
+Enhancements and new features:
+
+ * New plugin to scan remote Web sites (URL) (issue #981)
+ * Add trends in the Curses interface (issue #1077)
+ * Add new repeat function to the action (issue #952)
+ * Use -> and <- arrows keys to switch between processing sort (issue #1075)
+ * Refactor __init__ and main scripts (issue #1050)
+ * [WebUI] Improve WebUI for Windows 10 (issue #1052)
+
+Bugs corrected:
+
+ * StatsD export prefix option is ignored (issue #1074)
+ * Some FS and LAN metrics fail to export correctly to StatsD (issue #1068)
+ * Problem with non breaking space in file system name (issue #1065)
+ * TypeError: string indices must be integers (Network plugin) (issue #1054)
+ * No Offline status for timeouted ports? (issue #1084)
+ * When exporting, uptime values loop after 1 day (issue #1092)
+
+Installation:
+
+ * Create a package.sh script to generate .DEB, .RPM and others... (issue #722)
+ ==> https://github.com/nicolargo/glancesautopkg
+ * OSX: can't python setup.py install due to python 3.5 constraint (issue #1064)
+
Version 2.9.1
=============
@@ -9,7 +36,7 @@ Bugs corrected:
* Glances PerCPU issues with Curses UI on Android (issue #1071)
* Remove extra } in format string (issue #1073)
-
+
Version 2.9.0
=============
diff --git a/README.rst b/README.rst
index 14e015d2..a2d05505 100644
--- a/README.rst
+++ b/README.rst
@@ -265,6 +265,7 @@ Start Termux on your device and enter:
$ apt update
$ apt upgrade
$ apt install clang python python-dev
+ $ pip install bottle
$ pip install glances
And start Glances:
@@ -273,6 +274,9 @@ And start Glances:
$ glances
+You can also run Glances in server mode (-s or -w) in order to remotely
+monitor your Android device.
+
Source
------
@@ -374,7 +378,6 @@ LGPLv3. See ``COPYING`` for more details.
.. _psutil: https://github.com/giampaolo/psutil
.. _glancesautoinstall: https://github.com/nicolargo/glancesautoinstall
.. _@nicolargo: https://twitter.com/nicolargo
-.. _@glances_system: https://twitter.com/glances_system
.. _Python: https://www.python.org/getit/
.. _Termux: https://play.google.com/store/apps/details?id=com.termux
.. _readthedocs: https://glances.readthedocs.io/
diff --git a/conf/glances.conf b/conf/glances.conf
index 013b8067..a7dc1cb4 100644
--- a/conf/glances.conf
+++ b/conf/glances.conf
@@ -87,6 +87,7 @@ mem_critical=90
# Define RAM thresholds in %
# Default values if not defined: 50/70/90
careful=50
+#careful_action_repeat=echo {{percent}} >> /tmp/memory.alert
warning=70
critical=90
@@ -141,9 +142,10 @@ careful=-65
warning=-75
critical=-85
-#[diskio]
+[diskio]
# Define the list of hidden disks (comma-separated regexp)
#hide=sda2,sda5,loop.*
+hide=loop.*
# Alias for sda1
#sda1_alias=IntDisk
@@ -217,12 +219,14 @@ refresh=30
timeout=3
# If port_default_gateway is True, add the default gateway on top of the scan list
port_default_gateway=True
+#
# Define the scan list (1 < x < 255)
# port_x_host (name or IP) is mandatory
# port_x_port (TCP port number) is optional (if not set, use ICMP)
# port_x_description is optional (if not set, define to host:port)
# port_x_timeout is optional and overwrite the default timeout value
# port_x_rtt_warning is optional and defines the warning threshold in ms
+#
#port_1_host=192.168.0.1
#port_1_port=80
#port_1_description=Home Box
@@ -232,10 +236,25 @@ port_default_gateway=True
#port_3_host=www.google.com
#port_3_description=Internet ICMP
#port_3_rtt_warning=1000
-#port_4_host=www.google.com
#port_4_description=Internet Web
+#port_4_host=www.google.com
#port_4_port=80
#port_4_rtt_warning=1000
+#
+# Define Web (URL) monitoring list (1 < x < 255)
+# web_x_url is the URL to monitor (example: http://my.site.com/folder)
+# web_x_description is optional (if not set, define to URL)
+# web_x_timeout is optional and overwrite the default timeout value
+# web_x_rtt_warning is optional and defines the warning respond time in ms (approximatively)
+#
+#web_1_url=https://blog.nicolargo.com
+#web_1_description=My Blog
+#web_1_rtt_warning=3000
+#web_2_url=https://github.com
+#web_3_url=http://www.google.fr
+#web_3_description=Google Fr
+#web_4_url=https://blog.nicolargo.com/nonexist
+#web_4_description=Intranet
[docker]
# Thresholds for CPU and MEM (in %)
diff --git a/docs/_static/cpu-wide.png b/docs/_static/cpu-wide.png
index 1046b7d8..53c2a95b 100644
--- a/docs/_static/cpu-wide.png
+++ b/docs/_static/cpu-wide.png
Binary files differ
diff --git a/docs/_static/cpu.png b/docs/_static/cpu.png
index 7fa618a1..d034c180 100644
--- a/docs/_static/cpu.png
+++ b/docs/_static/cpu.png
Binary files differ
diff --git a/docs/_static/mem-wide.png b/docs/_static/mem-wide.png
index 838b959d..60a6bece 100644
--- a/docs/_static/mem-wide.png
+++ b/docs/_static/mem-wide.png
Binary files differ
diff --git a/docs/_static/mem.png b/docs/_static/mem.png
index aaf90ac4..df79d0da 100644
--- a/docs/_static/mem.png
+++ b/docs/_static/mem.png
Binary files differ
diff --git a/docs/_static/ports.png b/docs/_static/ports.png
index 03edf63d..f65c8453 100644
--- a/docs/_static/ports.png
+++ b/docs/_static/ports.png
Binary files differ
diff --git a/docs/_static/trend.png b/docs/_static/trend.png
new file mode 100644
index 00000000..7cf0cff4
--- /dev/null
+++ b/docs/_static/trend.png
Binary files differ
diff --git a/docs/aoa/actions.rst b/docs/aoa/actions.rst
index 5ce40bcd..b83f1737 100644
--- a/docs/aoa/actions.rst
+++ b/docs/aoa/actions.rst
@@ -31,4 +31,14 @@ reached:
https://github.com/nicolargo/glances/wiki/The-Glances-2.x-API-How-to
for the stats list.
+It is also possible to repeat action until the end of the alert.
+Keep in mind that the command line is executed every refresh time so
+use with caution:
+
+.. code-block:: ini
+
+ [load]
+ critical=5.0
+ critical_action_repeat=/home/myhome/bin/bipper.sh
+
.. _{{mustache}}: https://mustache.github.io/
diff --git a/docs/aoa/cpu.rst b/docs/aoa/cpu.rst
index ead6a0df..d112d795 100644
--- a/docs/aoa/cpu.rst
+++ b/docs/aoa/cpu.rst
@@ -3,8 +3,10 @@
CPU
===
-The CPU stats are shown as a percentage or value and for the configured
-refresh time. The total CPU usage is displayed on the first line.
+The CPU stats are shown as a percentage or values and for the configured
+refresh time.
+
+The total CPU usage is displayed on the first line.
.. image:: ../_static/cpu.png
@@ -13,6 +15,17 @@ displayed.
.. image:: ../_static/cpu-wide.png
+A character is also displayed just after the CPU header and shows the
+trend value:
+
+======== ==============================================================
+Trend Status
+======== ==============================================================
+``-`` CPU value is equal to the mean of the six latests refreshes
+``\`` CPU value is lower than the mean of the six latests refreshes
+``/`` CPU value is higher than the mean of the six latests refreshes
+======== ==============================================================
+
CPU stats description:
- **user**: percent time spent in user space. User CPU time is the time
diff --git a/docs/aoa/memory.rst b/docs/aoa/memory.rst
index 0cd6afc8..05b3df87 100644
--- a/docs/aoa/memory.rst
+++ b/docs/aoa/memory.rst
@@ -12,6 +12,17 @@ the ``RAM``:
.. image:: ../_static/mem-wide.png
+A character is also displayed just after the MEM header and shows the
+trend value:
+
+======== ==============================================================
+Trend Status
+======== ==============================================================
+``-`` MEM value is equal to the mean of the six latests refreshes
+``\`` MEM value is lower than the mean of the six latests refreshes
+``/`` MEM value is higher than the mean of the six latests refreshes
+======== ==============================================================
+
Alerts are only set for used memory and used swap.
Legend:
diff --git a/docs/aoa/ports.rst b/docs/aoa/ports.rst
index 4534dfa9..54353891 100644
--- a/docs/aoa/ports.rst
+++ b/docs/aoa/ports.rst
@@ -7,9 +7,9 @@ Ports
.. image:: ../_static/ports.png
-This plugin aims at providing a list of hosts/port to scan.
+This plugin aims at providing a list of hosts/port and URL to scan.
-You can define ``ICMP`` or ``TCP`` ports scan.
+You can define ``ICMP`` or ``TCP`` ports scans and URL (head only) check.
The list should be defined in the ``[ports]`` section of the Glances
configuration file.
@@ -24,12 +24,14 @@ configuration file.
timeout=3
# If port_default_gateway is True, add the default gateway on top of the scan list
port_default_gateway=True
+ #
# Define the scan list (1 < x < 255)
# port_x_host (name or IP) is mandatory
# port_x_port (TCP port number) is optional (if not set, use ICMP)
# port_x_description is optional (if not set, define to host:port)
# port_x_timeout is optional and overwrite the default timeout value
# port_x_rtt_warning is optional and defines the warning threshold in ms
+ #
port_1_host=192.168.0.1
port_1_port=80
port_1_description=Home Box
@@ -43,3 +45,16 @@ configuration file.
port_4_description=Internet Web
port_4_port=80
port_4_rtt_warning=1000
+ #
+ # Define Web (URL) monitoring list (1 < x < 255)
+ # web_x_url is the URL to monitor (example: http://my.site.com/folder)
+ # web_x_description is optional (if not set, define to URL)
+ # web_x_timeout is optional and overwrite the default timeout value
+ # web_x_rtt_warning is optional and defines the warning respond time in ms (approximatively)
+ #
+ web_1_url=https://blog.nicolargo.com
+ web_1_description=My Blog
+ web_1_rtt_warning=3000
+ web_2_url=https://github.com
+ web_3_url=http://www.google.fr
+ web_3_description=Google Fr
diff --git a/docs/man/glances.1 b/docs/man/glances.1
index 1f0b9fb2..8e4bf72f 100644
--- a/docs/man/glances.1
+++ b/docs/man/glances.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "GLANCES" "1" "Mar 29, 2017" "2.9.1" "Glances"
+.TH "GLANCES" "1" "May 26, 2017" "2.10" "Glances"
.SH NAME
glances \- An eye on your system
.
diff --git a/glances/__init__.py b/glances/__init__.py
index 8a1d1c79..85942d5f 100644
--- a/glances/__init__.py
+++ b/glances/__init__.py
@@ -27,7 +27,7 @@ import signal
import sys
# Global name
-__version__ = '2.9.1'
+__version__ = '2.10'
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
__license__ = 'LGPLv3'
diff --git a/glances/actions.py b/glances/actions.py
index e50376d0..89c9e326 100644
--- a/glances/actions.py
+++ b/glances/actions.py
@@ -63,21 +63,24 @@ class GlancesActions(object):
"""Set the stat_name to criticity."""
self.status[stat_name] = criticity
- def run(self, stat_name, criticity, commands, mustache_dict=None):
+ def run(self, stat_name, criticity, commands, repeat, mustache_dict=None):
"""Run the commands (in background).
- stats_name: plugin_name (+ header)
- criticity: criticity of the trigger
- commands: a list of command line with optional {{mustache}}
+ - If True, then repeat the action
- mustache_dict: Plugin stats (can be use within {{mustache}})
Return True if the commands have been ran.
"""
- if self.get(stat_name) == criticity or not self.start_timer.finished():
+ if (self.get(stat_name) == criticity and not repeat) or \
+ not self.start_timer.finished():
# Action already executed => Exit
return False
- logger.debug("Run action {} for {} ({}) with stats {}".format(
+ logger.debug("{} action {} for {} ({}) with stats {}".format(
+ "Repeat" if repeat else "Run",
commands, stat_name, criticity, mustache_dict))
# Run all actions in background
diff --git a/glances/attribute.py b/glances/attribute.py
index 5f008650..41b9c8b0 100644
--- a/glances/attribute.py
+++ b/glances/attribute.py
@@ -126,6 +126,10 @@ class GlancesAttribute(object):
"""
return self._history[-pos]
+ def history_raw(self, nb=0):
+ """Return the history of last nb items (0 for all) In ISO JSON format"""
+ return self._history[-nb:]
+
def history_json(self, nb=0):
"""Return the history of last nb items (0 for all) In ISO JSON format"""
return [(i[0].isoformat(), i[1]) for i in self._history[-nb:]]
diff --git a/glances/compat.py b/glances/compat.py
index bfec1433..f11ce3ca 100644
--- a/glances/compat.py
+++ b/glances/compat.py
@@ -28,6 +28,13 @@ import types
PY3 = sys.version_info[0] == 3
+try:
+ from statistics import mean
+except ImportError:
+ # Statistics is only available for Python 3.4 or higher
+ def mean(numbers):
+ return float(sum(numbers)) / max(len(numbers), 1)
+
if PY3:
import queue
from configparser import ConfigParser, NoOptionError, NoSectionError
@@ -35,6 +42,7 @@ if PY3:
from xmlrpc.server import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from urllib.request import urlopen
from urllib.error import HTTPError, URLError
+ from urllib.parse import urlparse
input = input
range = range
@@ -90,6 +98,7 @@ else:
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from xmlrpclib import Fault, ProtocolError, ServerProxy, Transport, Server
from urllib2 import urlopen, HTTPError, URLError
+ from urlparse import urlparse
input = raw_input
range = xrange
diff --git a/glances/exports/glances_export.py b/glances/exports/glances_export.py
index e47f773b..b402ea2e 100644
--- a/glances/exports/glances_export.py
+++ b/glances/exports/glances_export.py
@@ -122,9 +122,9 @@ class GlancesExport(object):
def parse_tags(self, tags):
"""Parse tags into a dict.
- tags: a comma separated list of 'key:value' pairs.
+ input tags: a comma separated list of 'key:value' pairs.
Example: foo:bar,spam:eggs
- dtags: a dict of tags.
+ output dtags: a dict of tags.
Example: {'foo': 'bar', 'spam': 'eggs'}
"""
dtags = {}
@@ -158,7 +158,9 @@ class GlancesExport(object):
if isinstance(all_stats[plugin], dict):
all_stats[plugin].update(all_limits[plugin])
elif isinstance(all_stats[plugin], list):
- all_stats[plugin] += all_limits[plugin]
+ # TypeError: string indices must be integers (Network plugin) #1054
+ for i in all_stats[plugin]:
+ i.update(all_limits[plugin])
else:
continue
export_names, export_values = self.__build_export(all_stats[plugin])
diff --git a/glances/exports/glances_statsd.py b/glances/exports/glances_statsd.py
index db7628a0..4ab88e9c 100644
--- a/glances/exports/glances_statsd.py
+++ b/glances/exports/glances_statsd.py
@@ -57,7 +57,7 @@ class Export(GlancesExport):
# Init the Statsd client
self.client = self.init()
- def init(self, prefix='glances'):
+ def init(self):
"""Init the connection to the Statsd server."""
if not self.export_enable:
return None
@@ -66,7 +66,7 @@ class Export(GlancesExport):
self.port))
return StatsClient(self.host,
int(self.port),
- prefix=prefix)
+ prefix=self.prefix)
def export(self, name, columns, points):
"""Export the stats to the Statsd server."""
@@ -76,7 +76,19 @@ class Export(GlancesExport):
stat_name = '{}.{}'.format(name, columns[i])
stat_value = points[i]
try:
- self.client.gauge(stat_name, stat_value)
+ self.client.gauge(normalize(stat_name),
+ stat_value)
except Exception as e:
logger.error("Can not export stats to Statsd (%s)" % e)
logger.debug("Export {} stats to Statsd".format(name))
+
+
+def normalize(name):
+ """Normalize name for the Statsd convention"""
+
+ # Name should not contain some specials chars (issue #1068)
+ ret = name.replace(':', '')
+ ret = ret.replace('%', '')
+ ret = ret.replace(' ', '_')
+
+ return ret
diff --git a/glances/history.py b/glances/history.py
index ff222328..433f15df 100644
--- a/glances/history.py
+++ b/glances/history.py
@@ -49,9 +49,9 @@ class GlancesHistory(object):
for a in self.stats_history:
self.stats_history[a].history_reset()
- def get(self):
+ def get(self, nb=0):
"""Get the history as a dict of list"""
- return {i: self.stats_history[i].history for i in self.stats_history}
+ return {i: self.stats_history[i].history_raw(nb=nb) for i in self.stats_history}
def get_json(self, nb=0):
"""Get the history as a dict of list (with list JSON compliant)"""
diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py
index 3234775a..5416e5be 100644
--- a/glances/outputs/glances_curses.py
+++ b/glances/outputs/glances_curses.py
@@ -82,9 +82,11 @@ class _GlancesCurses(object):
'm': {'auto_sort': False, 'sort_key': 'memory_percent'},
'p': {'auto_sort': False, 'sort_key': 'name'},
't': {'auto_sort': False, 'sort_key': 'cpu_times'},
- 'u': {'auto_sort': False, 'sort_key': 'username'}
+ 'u': {'auto_sort': False, 'sort_key': 'username'},
}
+ _sort_loop = ['cpu_percent', 'memory_percent', 'username', 'cpu_times', 'io_counters', 'name']
+
def __init__(self, config=None, args=None):
# Init
self.config = config
@@ -130,7 +132,7 @@ class _GlancesCurses(object):
self.args.reset_minmax_tag = False
# Catch key pressed with non blocking mode
- self.no_flash_cursor()
+ self.term_window.keypad(1)
self.term_window.nodelay(1)
self.pressedkey = -1
@@ -284,12 +286,6 @@ class _GlancesCurses(object):
'PASSWORD': curses.A_PROTECT
}
- def flash_cursor(self):
- self.term_window.keypad(1)
-
- def no_flash_cursor(self):
- self.term_window.keypad(0)
-
def set_cursor(self, value):
"""Configure the curse cursor apparence.
@@ -395,10 +391,27 @@ class _GlancesCurses(object):
glances_processes.disable()
else:
glances_processes.enable()
+ elif self.pressedkey == curses.KEY_LEFT:
+ # "<" (left arrow) navigation through process sort
+ setattr(glances_processes, 'auto_sort', False)
+ next_sort = (self.loop_position() - 1) % len(self._sort_loop)
+ glances_processes.sort_key = self._sort_loop[next_sort]
+ elif self.pressedkey == curses.KEY_RIGHT:
+ # ">" (right arrow) navigation through process sort
+ setattr(glances_processes, 'auto_sort', False)
+ next_sort = (self.loop_position() + 1) % len(self._sort_loop)
+ glances_processes.sort_key = self._sort_loop[next_sort]
# Return the key code
return self.pressedkey
+ def loop_position(self):
+ """Return the current sort in the loop"""
+ for i, v in enumerate(self._sort_loop):
+ if v == glances_processes.sort_key:
+ return i
+ return 0
+
def disable_top(self):
"""Disable the top panel"""
for p in ['quicklook', 'cpu', 'gpu', 'mem', 'memswap', 'load']:
@@ -816,11 +829,11 @@ class _GlancesCurses(object):
subpop.refresh()
# Create the textbox inside the subwindows
self.set_cursor(2)
- self.flash_cursor()
+ self.term_window.keypad(1)
textbox = GlancesTextbox(subpop, insert_mode=False)
textbox.edit()
self.set_cursor(0)
- self.no_flash_cursor()
+ self.term_window.keypad(0)
if textbox.gather() != '':
logger.debug(
"User enters the following string: %s" % textbox.gather())
diff --git a/glances/outputs/static/html/plugins/cpu.html b/glances/outputs/static/html/plugins/cpu.html
index 82315ff9..53175592 100644
--- a/glances/outputs/static/html/plugins/cpu.html
+++ b/glances/outputs/static/html/plugins/cpu.html
@@ -25,7 +25,7 @@
</div>
<div class="hidden-xs hidden-sm col-md-12 col-lg-8">
<div class="table">
- <div class="table-row">
+ <div class="table-row" ng-show="statsCpu.nice != undefined">
<div class="table-cell text-left">nice:</div>
<div class="table-cell">
{{ statsCpu.nice }}%
diff --git a/glances/outputs/static/html/plugins/mem_more.html b/glances/outputs/static/html/plugins/mem_more.html
index 080060ae..49d831dd 100644
--- a/glances/outputs/static/html/plugins/mem_more.html
+++ b/glances/outputs/static/html/plugins/mem_more.html
@@ -1,9 +1,9 @@
<div class="table">
- <div class="table-row">
+ <div class="table-row" ng-show="statsMem.active != undefined">
<div class="table-cell text-left">active:</div>
<div class="table-cell">{{ statsMem.active | bytes }}</div>
</div>
- <div class="table-row">
+ <div class="table-row" ng-show="statsMem.inactive != undefined">
<div class="table-cell text-left">inactive:<