mirror of
https://github.com/nicolargo/glances.git
synced 2024-12-25 10:12:55 +03:00
Add alias feature and optimize history feature footprint
This commit is contained in:
parent
22ea5b1172
commit
257a90f718
@ -51,7 +51,9 @@ critical=90
|
||||
[network]
|
||||
# Define the list of hidden network interfaces (comma separeted)
|
||||
hide=lo
|
||||
# Default limits (in bits per second aka bps) for interface bitrate
|
||||
# WLAN0 alias name
|
||||
wlan0_alias=Wireless
|
||||
# WLAN0 Default limits (in bits per second aka bps) for interface bitrate
|
||||
wlan0_rx_careful=4000000
|
||||
wlan0_rx_warning=5000000
|
||||
wlan0_rx_critical=6000000
|
||||
@ -62,6 +64,8 @@ wlan0_tx_critical=1000000
|
||||
[diskio]
|
||||
# Define the list of hidden disks (comma separeted)
|
||||
hide=sda2,sda5
|
||||
# Alias for sda1
|
||||
#sda1_alias=IntDisk
|
||||
|
||||
[fs]
|
||||
# Default limits for free filesytem space in %
|
||||
@ -85,6 +89,12 @@ temperature_hdd_critical=60
|
||||
battery_careful=80
|
||||
battery_warning=90
|
||||
battery_critical=95
|
||||
# Sensors alias
|
||||
temp1_alias=Motherboard 0
|
||||
temp2_alias=Motherboard 1
|
||||
core 0_alias=CPU Core 0
|
||||
core 1_alias=CPU Core 1
|
||||
|
||||
|
||||
[processlist]
|
||||
# Limit values for CPU/MEM per process in %
|
||||
|
@ -51,7 +51,9 @@ critical=90
|
||||
#[network]
|
||||
# Define the list of hidden network interfaces (comma separeted)
|
||||
#hide=lo
|
||||
# Default limits (in bits per second aka bps) for interface bitrate
|
||||
# WLAN 0 alias
|
||||
#wlan0_alias=Wireless IF
|
||||
# WLAN 0 Default limits (in bits per second aka bps) for interface bitrate
|
||||
#wlan0_rx_careful=4000000
|
||||
#wlan0_rx_warning=5000000
|
||||
#wlan0_rx_critical=6000000
|
||||
@ -62,6 +64,8 @@ critical=90
|
||||
#[diskio]
|
||||
# Define the list of hidden disks (comma separeted)
|
||||
#hide=sda2,sda5
|
||||
# Alias for sda1
|
||||
#sda1_alias=IntDisk
|
||||
|
||||
[fs]
|
||||
# Default limits for free filesytem space in %
|
||||
@ -85,6 +89,11 @@ temperature_hdd_critical=60
|
||||
battery_careful=80
|
||||
battery_warning=90
|
||||
battery_critical=95
|
||||
# Sensors alias
|
||||
#temp1_alias=Motherboard 0
|
||||
#temp2_alias=Motherboard 1
|
||||
#core 0_alias=CPU Core 0
|
||||
#core 1_alias=CPU Core 1
|
||||
|
||||
[processlist]
|
||||
# Limit values for CPU/MEM per process in %
|
||||
|
@ -49,7 +49,7 @@ psutil_version = tuple([int(num) for num in __psutil_version.split('.')])
|
||||
|
||||
# First log with Glances and PSUtil version
|
||||
logger.info('Start Glances {0}'.format(__version__))
|
||||
logger.info('with {0} {1} and PSutil {2}'.format(platform.python_implementation(),
|
||||
logger.info('{0} {1} and PSutil {2} detected'.format(platform.python_implementation(),
|
||||
platform.python_version(),
|
||||
__psutil_version))
|
||||
|
||||
|
@ -73,3 +73,4 @@ glances_processes = GlancesProcesses()
|
||||
# The global instance for the logs
|
||||
from glances.core.glances_logs import GlancesLogs
|
||||
glances_logs = GlancesLogs()
|
||||
|
||||
|
@ -60,6 +60,8 @@ class GlancesMain(object):
|
||||
parser.add_argument('-C', '--config', dest='conf_file',
|
||||
help=_('path to the configuration file'))
|
||||
# Enable or disable option on startup
|
||||
parser.add_argument('--enable-history', action='store_true', default=False,
|
||||
dest='enable_history', help=_('enable the history mode'))
|
||||
parser.add_argument('--disable-bold', action='store_false', default=True,
|
||||
dest='disable_bold', help=_('disable bold mode in the terminal'))
|
||||
parser.add_argument('--disable-diskio', action='store_true', default=False,
|
||||
|
@ -30,7 +30,7 @@ class GlancesStandalone(object):
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
# Init stats
|
||||
self.stats = GlancesStats(config)
|
||||
self.stats = GlancesStats(config=config, args=args)
|
||||
|
||||
# Initial system informations update
|
||||
self.stats.update()
|
||||
|
@ -39,15 +39,18 @@ class GlancesStats(object):
|
||||
|
||||
"""This class stores, updates and gives stats."""
|
||||
|
||||
def __init__(self, config=None):
|
||||
def __init__(self, config=None, args=None):
|
||||
# Init the plugin list dict
|
||||
self._plugins = collections.defaultdict(dict)
|
||||
|
||||
# Set the argument instance
|
||||
self.args = args
|
||||
|
||||
# Set the config instance
|
||||
self.config = config
|
||||
|
||||
# Load the plugins
|
||||
self.load_plugins()
|
||||
self.load_plugins(args=args)
|
||||
|
||||
# Load the limits
|
||||
self.load_limits(config)
|
||||
|
@ -163,6 +163,17 @@ class GlancesCurses(object):
|
||||
self.term_window.nodelay(1)
|
||||
self.pressedkey = -1
|
||||
|
||||
# History tag
|
||||
self.reset_history_tag = False
|
||||
self.history_tag = False
|
||||
if args.enable_history:
|
||||
logger.info('Stats history enabled')
|
||||
from glances.outputs.glances_history import GlancesHistory
|
||||
self.glances_history = GlancesHistory()
|
||||
if not self.glances_history.graph_enabled():
|
||||
args.enable_history = False
|
||||
logger.error('Stats history disabled because graph lib is not available')
|
||||
|
||||
def __get_key(self, window):
|
||||
# Catch ESC key AND numlock key (issue #163)
|
||||
keycode = [0, 0]
|
||||
@ -205,6 +216,9 @@ class GlancesCurses(object):
|
||||
elif self.pressedkey == ord('f'):
|
||||
# 'f' > Show/hide fs stats
|
||||
self.args.disable_fs = not self.args.disable_fs
|
||||
elif self.pressedkey == ord('g'):
|
||||
# 'g' > History
|
||||
self.history_tag = not self.history_tag
|
||||
elif self.pressedkey == ord('h'):
|
||||
# 'h' > Show/hide help
|
||||
self.args.help_tag = not self.args.help_tag
|
||||
@ -223,6 +237,9 @@ class GlancesCurses(object):
|
||||
elif self.pressedkey == ord('p'):
|
||||
# 'p' > Sort processes by name
|
||||
self.args.process_sorted_by = 'name'
|
||||
elif self.pressedkey == ord('r'):
|
||||
# 'r' > Reset history
|
||||
self.reset_history_tag = not self.reset_history_tag
|
||||
elif self.pressedkey == ord('s'):
|
||||
# 's' > Show/hide sensors stats (Linux-only)
|
||||
self.args.disable_sensors = not self.args.disable_sensors
|
||||
@ -421,6 +438,58 @@ class GlancesCurses(object):
|
||||
self.new_line()
|
||||
self.display_plugin(stats_alert)
|
||||
|
||||
# History option
|
||||
# Generate history graph
|
||||
if self.history_tag and self.args.enable_history:
|
||||
self.display_popup(_("Graphs history generated in %s") % self.glances_history.get_output_folder())
|
||||
self.glances_history.generate_graph(stats)
|
||||
elif self.reset_history_tag and self.args.enable_history:
|
||||
self.display_popup(_("Reset history"))
|
||||
self.glances_history.reset(stats)
|
||||
elif (self.history_tag or self.reset_history_tag) and not self.args.enable_history:
|
||||
self.display_popup(_("History disabled\nEnable it using --enable-history"))
|
||||
self.history_tag = False
|
||||
self.reset_history_tag = False
|
||||
|
||||
return True
|
||||
|
||||
def display_popup(self, message, size_x=None, size_y=None, duration=3):
|
||||
"""
|
||||
Display a centered popup with the given message during duration seconds
|
||||
If size_x and size_y: set the popup size
|
||||
else set it automatically
|
||||
Return True if the popup could be displayed
|
||||
"""
|
||||
|
||||
# Center the popup
|
||||
if size_x is None:
|
||||
size_x = len(message) + 4
|
||||
if size_y is None:
|
||||
size_y = message.count('\n') + 1 + 4
|
||||
screen_x = self.screen.getmaxyx()[1]
|
||||
screen_y = self.screen.getmaxyx()[0]
|
||||
if size_x > screen_x or size_y > screen_y:
|
||||
# No size to display the popup => abord
|
||||
return False
|
||||
pos_x = (screen_x - size_x) / 2
|
||||
pos_y = (screen_y - size_y) / 2
|
||||
|
||||
# Create the popup
|
||||
popup = curses.newwin(size_y, size_x, pos_y, pos_x)
|
||||
|
||||
# Fill the popup
|
||||
popup.border()
|
||||
|
||||
# Add the message
|
||||
y = 0
|
||||
for m in message.split('\n'):
|
||||
popup.addnstr(2 + y, 2, m, len(m))
|
||||
y += 1
|
||||
|
||||
# Display the popup
|
||||
popup.refresh()
|
||||
curses.napms(duration * 1000)
|
||||
|
||||
return True
|
||||
|
||||
def display_plugin(self, plugin_stats,
|
||||
@ -532,7 +601,7 @@ class GlancesCurses(object):
|
||||
while not countdown.finished():
|
||||
# Getkey
|
||||
if self.__catch_key() > -1:
|
||||
# flush display
|
||||
# Redraw display
|
||||
self.flush(stats, cs_status=cs_status)
|
||||
# Wait 100ms...
|
||||
curses.napms(100)
|
||||
|
@ -33,6 +33,12 @@ snmp_oid = {'default': {'user': '1.3.6.1.4.1.2021.11.9.0',
|
||||
'windows': {'percent': '1.3.6.1.2.1.25.3.3.1.2'},
|
||||
'esxi': {'percent': '1.3.6.1.2.1.25.3.3.1.2'}}
|
||||
|
||||
# Define the history items list
|
||||
# 'color' define the graph color in #RGB format
|
||||
# All items in this list will be historised if the --enable-history tag is set
|
||||
items_history_list = [{'name': 'user', 'color': '#00FF00'},
|
||||
{'name': 'system', 'color': '#FF0000'}]
|
||||
|
||||
|
||||
class Plugin(GlancesPlugin):
|
||||
"""
|
||||
@ -43,7 +49,7 @@ class Plugin(GlancesPlugin):
|
||||
|
||||
def __init__(self, args=None):
|
||||
"""Init the CPU plugin."""
|
||||
GlancesPlugin.__init__(self, args=args)
|
||||
GlancesPlugin.__init__(self, args=args, items_history_list=items_history_list)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -123,6 +129,9 @@ class Plugin(GlancesPlugin):
|
||||
for key in list(self.stats.keys()):
|
||||
self.stats[key] = float(self.stats[key])
|
||||
|
||||
# Update the history list
|
||||
self.update_stats_history()
|
||||
|
||||
return self.stats
|
||||
|
||||
def msg_curse(self, args=None):
|
||||
|
@ -128,13 +128,15 @@ class Plugin(GlancesPlugin):
|
||||
# Do not display hidden interfaces
|
||||
if self.is_hide(i['disk_name']):
|
||||
continue
|
||||
# Is there an alias for the disk name ?
|
||||
disk_name = self.has_alias(i['disk_name'])
|
||||
if disk_name is None:
|
||||
disk_name = i['disk_name']
|
||||
# New line
|
||||
ret.append(self.curse_new_line())
|
||||
if len(i['disk_name']) > 9:
|
||||
if len(disk_name) > 9:
|
||||
# Cut disk name if it is too long
|
||||
disk_name = '_' + i['disk_name'][-8:]
|
||||
else:
|
||||
disk_name = i['disk_name']
|
||||
disk_name = '_' + disk_name[-8:]
|
||||
msg = '{0:9}'.format(disk_name)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
txps = self.auto_unit(int(i['read_bytes'] // i['time_since_update']))
|
||||
|
@ -116,7 +116,12 @@ class Plugin(GlancesPlugin):
|
||||
ret.append(self.curse_new_line())
|
||||
msg = msg_col.format(_("s"), _("Show/hide sensors stats"))
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = msg_col2.format(_("z"), _("Enable/disable processes stats"))
|
||||
msg = msg_col2.format(_("g"), _("Generate graphs for current history"))
|
||||
ret.append(self.curse_add_line(msg))
|
||||
ret.append(self.curse_new_line())
|
||||
msg = msg_col.format(_("z"), _("Enable/disable processes stats"))
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = msg_col2.format(_("r"), _("Reset history"))
|
||||
ret.append(self.curse_add_line(msg))
|
||||
ret.append(self.curse_new_line())
|
||||
msg = msg_col.format(_("q"), _("Quit (Esc and Ctrl-C also work)"))
|
||||
|
@ -35,6 +35,13 @@ snmp_oid = {'min1': '1.3.6.1.4.1.2021.10.1.3.1',
|
||||
'min5': '1.3.6.1.4.1.2021.10.1.3.2',
|
||||
'min15': '1.3.6.1.4.1.2021.10.1.3.3'}
|
||||
|
||||
# Define the history items list
|
||||
# All items in this list will be historised if the --enable-history tag is set
|
||||
# 'color' define the graph color in #RGB format
|
||||
items_history_list = [{'name': 'min1', 'color': '#0000FF'},
|
||||
{'name': 'min5', 'color': '#0000AA'},
|
||||
{'name': 'min15', 'color': '#000044'}]
|
||||
|
||||
|
||||
class Plugin(GlancesPlugin):
|
||||
|
||||
@ -45,7 +52,7 @@ class Plugin(GlancesPlugin):
|
||||
|
||||
def __init__(self, args=None):
|
||||
"""Init the plugin."""
|
||||
GlancesPlugin.__init__(self, args=args)
|
||||
GlancesPlugin.__init__(self, args=args, items_history_list=items_history_list)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -53,6 +60,12 @@ class Plugin(GlancesPlugin):
|
||||
# Init stats
|
||||
self.reset()
|
||||
|
||||
# Call CorePlugin in order to display the core number
|
||||
try:
|
||||
self.nb_log_core = CorePlugin(args=self.args).update()["log"]
|
||||
except Exception:
|
||||
self.nb_log_core = 0
|
||||
|
||||
def reset(self):
|
||||
"""Reset/init the stats."""
|
||||
self.stats = {}
|
||||
@ -62,12 +75,6 @@ class Plugin(GlancesPlugin):
|
||||
# Reset stats
|
||||
self.reset()
|
||||
|
||||
# Call CorePlugin in order to display the core number
|
||||
try:
|
||||
nb_log_core = CorePlugin().update()["log"]
|
||||
except Exception:
|
||||
nb_log_core = 0
|
||||
|
||||
if self.get_input() == 'local':
|
||||
# Update stats using the standard system lib
|
||||
|
||||
@ -80,7 +87,7 @@ class Plugin(GlancesPlugin):
|
||||
self.stats = {'min1': load[0],
|
||||
'min5': load[1],
|
||||
'min15': load[2],
|
||||
'cpucore': nb_log_core}
|
||||
'cpucore': self.nb_log_core}
|
||||
elif self.get_input() == 'snmp':
|
||||
# Update stats using SNMP
|
||||
self.stats = self.set_stats_snmp(snmp_oid=snmp_oid)
|
||||
@ -98,7 +105,10 @@ class Plugin(GlancesPlugin):
|
||||
for k, v in iteritems:
|
||||
self.stats[k] = float(v)
|
||||
|
||||
self.stats['cpucore'] = nb_log_core
|
||||
self.stats['cpucore'] = self.nb_log_core
|
||||
|
||||
# Update the history list
|
||||
self.update_stats_history()
|
||||
|
||||
return self.stats
|
||||
|
||||
|
@ -45,6 +45,11 @@ snmp_oid = {'default': {'total': '1.3.6.1.4.1.2021.4.5.0',
|
||||
'size': '1.3.6.1.2.1.25.2.3.1.5',
|
||||
'used': '1.3.6.1.2.1.25.2.3.1.6'}}
|
||||
|
||||
# Define the history items list
|
||||
# All items in this list will be historised if the --enable-history tag is set
|
||||
# 'color' define the graph color in #RGB format
|
||||
items_history_list = [{'name': 'percent', 'color': '#00FF00'}]
|
||||
|
||||
|
||||
class Plugin(GlancesPlugin):
|
||||
|
||||
@ -55,7 +60,7 @@ class Plugin(GlancesPlugin):
|
||||
|
||||
def __init__(self, args=None):
|
||||
"""Init the plugin."""
|
||||
GlancesPlugin.__init__(self, args=args)
|
||||
GlancesPlugin.__init__(self, args=args, items_history_list=items_history_list)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -146,6 +151,9 @@ class Plugin(GlancesPlugin):
|
||||
# percent: the percentage usage calculated as (total - available) / total * 100.
|
||||
self.stats['percent'] = float((self.stats['total'] - self.stats['free']) / self.stats['total'] * 100)
|
||||
|
||||
# Update the history list
|
||||
self.update_stats_history()
|
||||
|
||||
return self.stats
|
||||
|
||||
def msg_curse(self, args=None):
|
||||
|
@ -218,6 +218,9 @@ class Plugin(GlancesPlugin):
|
||||
if self.is_hide(i['interface_name']):
|
||||
continue
|
||||
# Format stats
|
||||
# Is there an alias for the interface name ?
|
||||
ifname = self.has_alias(i['interface_name'])
|
||||
if ifname is None:
|
||||
ifname = i['interface_name'].split(':')[0]
|
||||
if len(ifname) > ifname_max_width:
|
||||
# Cut interface name if it is too long
|
||||
|
@ -24,6 +24,7 @@ I am your father...
|
||||
"""
|
||||
|
||||
# Import system libs
|
||||
from datetime import datetime
|
||||
import json
|
||||
from operator import itemgetter
|
||||
|
||||
@ -35,10 +36,11 @@ class GlancesPlugin(object):
|
||||
|
||||
"""Main class for Glances' plugin."""
|
||||
|
||||
def __init__(self, args=None):
|
||||
def __init__(self, args=None, items_history_list=None):
|
||||
"""Init the plugin of plugins class."""
|
||||
# Plugin name (= module name without glances_)
|
||||
self.plugin_name = self.__class__.__module__[len('glances_'):]
|
||||
logger.debug(_("Init plugin %s") % self.plugin_name)
|
||||
|
||||
# Init the args
|
||||
self.args = args
|
||||
@ -53,6 +55,10 @@ class GlancesPlugin(object):
|
||||
# Init the stats list
|
||||
self.stats = None
|
||||
|
||||
# Init the history list
|
||||
self.items_history_list = items_history_list
|
||||
self.stats_history = self.init_stats_history()
|
||||
|
||||
# Init the limits dictionnary
|
||||
self.limits = dict()
|
||||
|
||||
@ -64,6 +70,49 @@ class GlancesPlugin(object):
|
||||
"""Return the human-readable stats."""
|
||||
return str(self.stats)
|
||||
|
||||
def init_stats_history(self):
|
||||
"""Init the stats history (dict of list)"""
|
||||
ret = None
|
||||
if self.args is not None and self.args.enable_history and self.get_items_history_list() is not None:
|
||||
iList = [i['name'] for i in self.get_items_history_list()]
|
||||
logger.debug(_("Stats history activated for plugin %s (items: %s)") % (self.plugin_name, iList))
|
||||
ret = {}
|
||||
# First column for the date
|
||||
ret['date'] = []
|
||||
for i in self.get_items_history_list():
|
||||
# One column per item
|
||||
ret[i['name']] = []
|
||||
return ret
|
||||
|
||||
def reset_stats_history(self):
|
||||
"""Reset the stats history (dict of list)"""
|
||||
if self.args is not None and self.args.enable_history and self.get_items_history_list() is not None:
|
||||
iList = [i['name'] for i in self.get_items_history_list()]
|
||||
logger.debug(_("Reset history for plugin %s (items: %s)") % (self.plugin_name, iList))
|
||||
self.stats_history = {}
|
||||
# First column for the date
|
||||
self.stats_history['date'] = []
|
||||
for i in self.get_items_history_list():
|
||||
# One column per item
|
||||
self.stats_history[i['name']] = []
|
||||
return self.stats_history
|
||||
|
||||
def update_stats_history(self):
|
||||
"""Update stats history"""
|
||||
if self.args is not None and self.args.enable_history and self.get_items_history_list() is not None:
|
||||
self.stats_history['date'].append(datetime.now())
|
||||
for i in self.get_items_history_list():
|
||||
self.stats_history[i['name']].append(self.stats[i['name']])
|
||||
return self.stats_history
|
||||
|
||||
def get_stats_history(self):
|
||||
"""Return the stats history"""
|
||||
return self.stats_history
|
||||
|
||||
def get_items_history_list(self):
|
||||
"""Return the items history list"""
|
||||
return self.items_history_list
|
||||
|
||||
def set_input(self, input_method, short_system_name=None):
|
||||
"""Set the input method.
|
||||
|
||||
@ -283,7 +332,7 @@ class GlancesPlugin(object):
|
||||
else:
|
||||
return self.limits[self.plugin_name + '_' + header + '_' + 'careful']
|
||||
|
||||
def get_hide(self, header=""):
|
||||
def __get_hide(self, header=""):
|
||||
"""Return the hide configuration list key for the current plugin."""
|
||||
if header == "":
|
||||
try:
|
||||
@ -298,7 +347,14 @@ class GlancesPlugin(object):
|
||||
|
||||
def is_hide(self, value, header=""):
|
||||
"""Return True if the value is in the hide configuration list."""
|
||||
return value in self.get_hide(header=header)
|
||||
return value in self.__get_hide(header=header)
|
||||
|
||||
def has_alias(self, header):
|
||||
"""Return the alias name for the relative header or None if nonexist"""
|
||||
try:
|
||||
return self.limits[self.plugin_name + '_' + header + '_' + 'alias'][0]
|
||||
except (KeyError, IndexError):
|
||||
return None
|
||||
|
||||
def msg_curse(self, args=None, max_width=None):
|
||||
"""Return default string to display in the curse interface."""
|
||||
|
@ -50,10 +50,10 @@ class Plugin(GlancesPlugin):
|
||||
self.glancesgrabsensors = GlancesGrabSensors()
|
||||
|
||||
# Instance for the HDDTemp Plugin in order to display the hard disks temperatures
|
||||
self.hddtemp_plugin = HddTempPlugin()
|
||||
self.hddtemp_plugin = HddTempPlugin(args=args)
|
||||
|
||||
# Instance for the BatPercent in order to display the batteries capacities
|
||||
self.batpercent_plugin = BatPercentPlugin()
|
||||
self.batpercent_plugin = BatPercentPlugin(args=args)
|
||||
|
||||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
@ -136,7 +136,12 @@ class Plugin(GlancesPlugin):
|
||||
for item in self.stats:
|
||||
# New line
|
||||
ret.append(self.curse_new_line())
|
||||
msg = '{0:18}'.format(item['label'][:18])
|
||||
# Alias for the lable name ?
|
||||
label = self.has_alias(item['label'].lower())
|
||||
if label is None:
|
||||
label = item['label']
|
||||
label = label[:18]
|
||||
msg = '{0:18}'.format(label)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{0:>5}'.format(item['value'])
|
||||
if item['type'] == 'battery':
|
||||
|
Loading…
Reference in New Issue
Block a user