提交 abb97d52 编写于 作者: N nicolargo

First optimzation with a new dynamic way to compute the refresh rate. Good...

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...
上级 0c7e3bca
......@@ -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):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册