summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicolargo <nicolas@nicolargo.com>2021-05-23 18:54:42 +0200
committernicolargo <nicolas@nicolargo.com>2021-05-23 18:54:42 +0200
commitabb97d5286af5893b2ae69eb7c9c2f1ffc8bf61b (patch)
tree2affc48ce549204361bdbd008d6384d2414ad570
parent0c7e3bca5f2e3cf898f31ed2a0a129dd02159584 (diff)
First optimzation with a new dynamic way to compute the refresh rate. Good news, the CPU consumption seams to be lower than ~20% with a refresh rate more or less the same...
-rw-r--r--conf/glances.conf12
-rw-r--r--docs/config.rst11
-rw-r--r--glances/__init__.py6
-rw-r--r--glances/main.py19
-rw-r--r--glances/outputs/glances_curses.py12
-rw-r--r--glances/plugins/glances_connections.py5
-rw-r--r--glances/plugins/glances_core.py2
-rw-r--r--glances/plugins/glances_cpu.py3
-rw-r--r--glances/plugins/glances_folders.py4
-rw-r--r--glances/plugins/glances_mem.py1
-rw-r--r--glances/plugins/glances_plugin.py33
-rw-r--r--glances/plugins/glances_ports.py18
-rw-r--r--glances/plugins/glances_processcount.py1
-rw-r--r--glances/processes.py9
-rw-r--r--glances/standalone.py3
-rw-r--r--glances/stats.py5
16 files changed, 94 insertions, 50 deletions
diff --git a/conf/glances.conf b/conf/glances.conf
index 1c24b773..0b04fb34 100644
--- a/conf/glances.conf
+++ b/conf/glances.conf
@@ -3,6 +3,10 @@
##############################################################################
[global]
+# Refresh rate (default is a minimum of 2 seconds)
+# Can be overwrite by the -t <sec> option
+# It is also possible to overwrite it in each plugin sections
+refresh=2
# Does Glances should check if a newer version is available on PyPI ?
check_update=false
# History size (maximum number of values)
@@ -27,6 +31,8 @@ max_processes_display=30
# Set to true to disable a plugin
# Note: you can also disable it from the command line (see --disable-plugin <plugin_name>)
disable=False
+# Set a specific refresh rate for this plugin by overwriting the default/refresh value
+#refresh=3
# Graphical percentage char used in the terminal user interface (default is |)
percentage_char=|
# Define CPU, MEM and SWAP thresholds in %
@@ -45,7 +51,7 @@ disable=False
# See https://scoutapm.com/blog/slow_server_flow_chart
#
# I/O wait percentage should be lower than 1/# (# = Logical CPU cores)
-# Leave commented to just use the default config:
+# Leave commented to just use the default config:
# Careful=1/#*100-20% / Warning=1/#*100-10% / Critical=1/#*100
#iowait_careful=30
#iowait_warning=40
@@ -414,8 +420,8 @@ style=DarkStyle
[influxdb]
# !!!
-# Will be DEPRECATED in future release.
-# Please have a look on the new influxdb2 export module (compatible with InfluxDB 1.8.x and 2.x)
+# Will be DEPRECATED in future release.
+# Please have a look on the new influxdb2 export module (compatible with InfluxDB 1.8.x and 2.x)
# !!!
# Configuration for the --export influxdb option
# https://influxdb.com/
diff --git a/docs/config.rst b/docs/config.rst
index 07f0efd5..56accc1e 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -39,8 +39,15 @@ A first section (called global) is available:
.. code-block:: ini
[global]
- # Does Glances should check if a newer version is available on PyPI?
- check_update=true
+ # Refresh rate (default is a minimum of 3 seconds)
+ # Can be overwrite by the -t <sec> option
+ # It is also possible to overwrite it in each plugin sections
+ refresh=3
+ # Does Glances should check if a newer version is available on PyPI ?
+ check_update=false
+ # History size (maximum number of values)
+ # Default is 28800: 1 day with 1 point every 3 seconds
+ history_size=28800
Each plugin, export module and application monitoring process (AMP) can
have a section. Below an example for the CPU plugin:
diff --git a/glances/__init__.py b/glances/__init__.py
index 8236a33c..4ef033c5 100644
--- a/glances/__init__.py
+++ b/glances/__init__.py
@@ -141,9 +141,9 @@ def main():
global core
# Create the Glances main instance
+ # Glances options from the command line are readed first (in __init__)
+ # then the options from the config file (in parse_args)
core = GlancesMain()
- config = core.get_config()
- args = core.get_args()
# Glances can be ran in standalone, client or server mode
- start(config=config, args=args)
+ start(config=core.get_config(), args= core.get_args())
diff --git a/glances/main.py b/glances/main.py
index 11e68a3b..77c9471f 100644
--- a/glances/main.py
+++ b/glances/main.py
@@ -33,8 +33,8 @@ from glances.logger import logger, LOG_FILENAME
class GlancesMain(object):
"""Main class to manage Glances instance."""
- # Default stats' refresh time is 3 seconds
- refresh_time = 3
+ # Default stats' minimum refresh time is 2 seconds
+ DEFAULT_REFRESH_TIME = 2
# Set the default cache lifetime to 1 second (only for server)
cached_time = 1
# By default, Glances is ran in standalone mode (no client/server)
@@ -205,8 +205,8 @@ Examples of use:
help='SNMP authentication key (only for SNMPv3)')
parser.add_argument('--snmp-force', action='store_true', default=False,
dest='snmp_force', help='force SNMP mode')
- parser.add_argument('-t', '--time', default=self.refresh_time, type=float,
- dest='time', help='set refresh time in seconds [default: {} sec]'.format(self.refresh_time))
+ parser.add_argument('-t', '--time', default=self.DEFAULT_REFRESH_TIME, type=float,
+ dest='time', help='set refresh time in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME))
parser.add_argument('-w', '--webserver', action='store_true', default=False,
dest='webserver', help='run Glances in web server mode (bottle needed)')
parser.add_argument('--cached-time', default=self.cached_time, type=int,
@@ -258,6 +258,8 @@ Examples of use:
args = self.init_args().parse_args()
# Load the configuration file, if it exists
+ # This function should be called after the parse_args
+ # because the configration file path can be defined
self.config = Config(args.conf_file)
# Debug mode
@@ -268,6 +270,15 @@ Examples of use:
from warnings import simplefilter
simplefilter("ignore")
+ # Plugins refresh rate
+ if self.config.has_section('global'):
+ global_refresh = self.config.get_float_value('global',
+ 'refresh',
+ default=self.DEFAULT_REFRESH_TIME)
+ if args.time == self.DEFAULT_REFRESH_TIME:
+ args.time = global_refresh
+ logger.debug('Global refresh rate is set to {} seconds'.format(args.time))
+
# Plugins disable/enable
# Allow users to disable plugins from the glances.conf (issue #1378)
for s in self.config.sections():
diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py
index 2e4a535d..ce4a6e63 100644
--- a/glances/outputs/glances_curses.py
+++ b/glances/outputs/glances_curses.py
@@ -20,10 +20,9 @@
"""Curses interface class."""
from __future__ import unicode_literals
-import re
import sys
-from glances.compat import to_ascii, nativestr, b, u, itervalues, enable, disable
+from glances.compat import nativestr, u, itervalues, enable, disable
from glances.globals import MACOS, WINDOWS
from glances.logger import logger
from glances.events import glances_events
@@ -104,7 +103,7 @@ class _GlancesCurses(object):
# "<" (left arrow) navigation through process sort
# ">" (right arrow) navigation through process sort
# 'UP' > Up in the server list
- # 'DOWN' > Down in the server list
+ # 'DOWN' > Down in the server list
}
_sort_loop = ['cpu_percent', 'memory_percent', 'username',
@@ -666,9 +665,9 @@ class _GlancesCurses(object):
self.args.cursor_position]
confirm = self.display_popup(
'Kill process: {} (pid: {}) ?\n\nConfirm ([y]es/[n]o): '.format(
- selected_process_raw['name'],
- selected_process_raw['pid']),
- popup_type='yesno')
+ selected_process_raw['name'],
+ selected_process_raw['pid']),
+ popup_type='yesno')
if confirm.lower().startswith('y'):
try:
ret_kill = glances_processes.kill(selected_process_raw['pid'])
@@ -684,7 +683,6 @@ class _GlancesCurses(object):
'Kill process only available in standalone mode')
self.kill_process = False
-
# Display graph generation popup
if self.args.generate_graph:
self.display_popup('Generate graph in {}'.format(self.args.export_graph_path))
diff --git a/glances/plugins/glances_connections.py b/glances/plugins/glances_connections.py
index af727816..16b2239c 100644
--- a/glances/plugins/glances_connections.py
+++ b/glances/plugins/glances_connections.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
+# Copyright (C) 2021 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
@@ -21,9 +21,8 @@
from __future__ import unicode_literals
from glances.logger import logger
-from glances.timer import getTimeSinceLastUpdate
from glances.plugins.glances_plugin import GlancesPlugin
-from glances.compat import n, u, b, nativestr
+from glances.compat import nativestr
import psutil
diff --git a/glances/plugins/glances_core.py b/glances/plugins/glances_core.py
index bf1692e0..0e5a9cdc 100644
--- a/glances/plugins/glances_core.py
+++ b/glances/plugins/glances_core.py
@@ -40,6 +40,8 @@ class Plugin(GlancesPlugin):
# The core number is displayed by the load plugin
self.display_curse = False
+ @GlancesPlugin._check_decorator
+ @GlancesPlugin._log_result_decorator
def update(self):
"""Update core stats.
diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py
index 4ab2ad1a..08cc61e6 100644
--- a/glances/plugins/glances_cpu.py
+++ b/glances/plugins/glances_cpu.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
+# Copyright (C) 2021 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
@@ -79,7 +79,6 @@ class Plugin(GlancesPlugin):
@GlancesPlugin._log_result_decorator
def update(self):
"""Update CPU stats using the input method."""
-
# Grab stats into self.stats
if self.input_method == 'local':
stats = self.update_local()
diff --git a/glances/plugins/glances_folders.py b/glances/plugins/glances_folders.py
index 49f822dc..8efddadc 100644
--- a/glances/plugins/glances_folders.py
+++ b/glances/plugins/glances_folders.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
+# Copyright (C) 2021 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
@@ -22,7 +22,7 @@ from __future__ import unicode_literals
import numbers
-from glances.compat import nativestr, n
+from glances.compat import nativestr
from glances.folder_list import FolderList as glancesFolderList
from glances.plugins.glances_plugin import GlancesPlugin
from glances.logger import logger
diff --git a/glances/plugins/glances_mem.py b/glances/plugins/glances_mem.py
index 33237cc2..417483a3 100644
--- a/glances/plugins/glances_mem.py
+++ b/glances/plugins/glances_mem.py
@@ -19,6 +19,7 @@
"""Virtual memory plugin."""
+from glances.logger import logger
from glances.compat import iterkeys
from glances.plugins.glances_plugin import GlancesPlugin
diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py
index c6e57950..6e728a10 100644
--- a/glances/plugins/glances_plugin.py
+++ b/glances/plugins/glances_plugin.py
@@ -34,7 +34,7 @@ from glances.history import GlancesHistory
from glances.logger import logger
from glances.events import glances_events
from glances.thresholds import glances_thresholds
-from glances.timer import Counter
+from glances.timer import Counter, Timer
class GlancesPlugin(object):
@@ -104,6 +104,9 @@ class GlancesPlugin(object):
self.hide_zero = False
self.hide_zero_fields = []
+ # Set the initial refresh time to display stats the first time
+ self.refresh_timer = Timer(0)
+
# Init the stats
self.stats_init_value = stats_init_value
self.stats = None
@@ -584,6 +587,13 @@ class GlancesPlugin(object):
"""Set the limits to input_limits."""
self._limits = input_limits
+ def get_limits(self, item=None):
+ """Return the limits object."""
+ if item is None:
+ return self._limits
+ else:
+ return self._limits.get('{}_{}'.format(self.plugin_name, item), None)
+
def get_stats_action(self):
"""Return stats for the action.
@@ -989,12 +999,29 @@ class GlancesPlugin(object):
ret = '\\'
return ret
+ def get_refresh_time(self):
+ """Return the plugin refresh time"""
+ ret = self.get_limits(item='refresh')
+ if ret is None:
+ ret = self.args.time
+ return ret
+
def _check_decorator(fct):
- """Check if the plugin is enabled."""
+ """Check decorator for update method.
+ It checks:
+ - if the plugin is enabled.
+ - if the refresh_timer is finished
+ """
def wrapper(self, *args, **kw):
- if self.is_enable():
+ if self.is_enable() and self.refresh_timer.finished():
+ # Run the method
ret = fct(self, *args, **kw)
+ # Reset the timer
+ self.refresh_timer.set(self.get_refresh_time())
+ self.refresh_timer.reset()
else:
+ # No need to call the method
+ # Return the last result available
ret = self.stats
return ret
return wrapper
diff --git a/glances/plugins/glances_ports.py b/glances/plugins/glances_ports.py
index 479801af..cd36dc15 100644
--- a/glances/plugins/glances_ports.py
+++ b/glances/plugins/glances_ports.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
+# Copyright (C) 2021 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
@@ -60,9 +60,6 @@ class Plugin(GlancesPlugin):
self.stats = GlancesPortsList(config=config, args=args).get_ports_list() + \
GlancesWebList(config=config, args=args).get_web_list()
- # Init global Timer
- self.timer_ports = Timer(0)
-
# Global Thread running all the scans
self._thread = None
@@ -73,6 +70,7 @@ class Plugin(GlancesPlugin):
# Call the father class
super(Plugin, self).exit()
+ @GlancesPlugin._check_decorator
@GlancesPlugin._log_result_decorator
def update(self):
"""Update the ports list."""
@@ -84,15 +82,15 @@ class Plugin(GlancesPlugin):
thread_is_running = False
else:
thread_is_running = self._thread.is_alive()
- if self.timer_ports.finished() and not thread_is_running:
+ if not thread_is_running:
# Run ports scanner
self._thread = ThreadScanner(self.stats)
self._thread.start()
- # Restart timer
- if len(self.stats) > 0:
- self.timer_ports = Timer(self.stats[0]['refresh'])
- else:
- self.timer_ports = Timer(0)
+ # # Restart timer
+ # if len(self.stats) > 0:
+ # self.timer_ports = Timer(self.stats[0]['refresh'])
+ # else:
+ # self.timer_ports = Timer(0)
else:
# Not available in SNMP mode
pass
diff --git a/glances/plugins/glances_processcount.py b/glances/plugins/glances_processcount.py
index bcc3b219..862d9cd1 100644
--- a/glances/plugins/glances_processcount.py
+++ b/glances/plugins/glances_processcount.py
@@ -62,6 +62,7 @@ class Plugin(GlancesPlugin):
# Note: 'glances_processes' is already init in the glances_processes.py script
+ @GlancesPlugin._check_decorator
@GlancesPlugin._log_result_decorator
def update(self):
"""Update processes stats using the input method."""
diff --git a/glances/processes.py b/glances/processes.py
index b7dfe70d..fbecd8d1 100644
--- a/glances/processes.py
+++ b/glances/processes.py
@@ -2,7 +2,7 @@
#
# This file is part of Glances.
#
-# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
+# Copyright (C) 2021 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
@@ -17,11 +17,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import operator
import os
-from glances.compat import iteritems, itervalues, listitems, iterkeys
-from glances.globals import BSD, LINUX, MACOS, SUNOS, WINDOWS, WSL
+from glances.compat import iterkeys
+from glances.globals import BSD, LINUX, MACOS, WINDOWS
from glances.timer import Timer, getTimeSinceLastUpdate
from glances.filter import GlancesFilter
from glances.logger import logger
@@ -403,7 +402,7 @@ class GlancesProcesses(object):
else:
self.auto_sort = auto
self._sort_key = key
-
+
def kill(self, pid, timeout=3):
"""Kill process with pid"""
assert pid != os.getpid(), "Glances can kill itself..."
diff --git a/glances/standalone.py b/glances/standalone.py
index ef255bc4..1e7d070b 100644
--- a/glances/standalone.py
+++ b/glances/standalone.py
@@ -150,7 +150,8 @@ class GlancesStandalone(object):
if not self.quiet:
# The update function return True if an exit key 'q' or 'ESC'
# has been pressed.
- ret = not self.screen.update(self.stats, duration=adapted_refresh)
+ ret = not self.screen.update(self.stats,
+ duration=adapted_refresh)
else:
# Nothing is displayed
# Break should be done via a signal (CTRL-C)
diff --git a/glances/stats.py b/glances/stats.py
index 896eabad..62717005 100644
--- a/glances/stats.py
+++ b/glances/stats.py
@@ -229,29 +229,24 @@ class GlancesStats(object):
# If current plugin is disable
# then continue to next plugin
continue
- start_duration = Counter()
# Update the stats...
self._plugins[p].update()
# ... the history
self._plugins[p].update_stats_history()
# ... and the views
self._plugins[p].update_views()
- # logger.debug("Plugin {} update duration: {} seconds".format(p,
- # start_duration.get()))
def export(self, input_stats=None):
"""Export all the stats.
Each export module is ran in a dedicated thread.
"""
- # threads = []
input_stats = input_stats or {}
for e in self._exports:
logger.debug("Export stats using the %s module" % e)
thread = threading.Thread(target=self._exports[e].update,
args=(input_stats,))
- # threads.append(thread)
thread.start()
def getAll(self):