mirror of https://github.com/nicolargo/glances
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...
parent
0c7e3bca5f
commit
abb97d5286
|
@ -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/
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
"""Virtual memory plugin."""
|
||||
|
||||
from glances.logger import logger
|
||||
from glances.compat import iterkeys
|
||||
from glances.plugins.glances_plugin import GlancesPlugin
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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..."
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue