mirror of https://github.com/nicolargo/glances.git
First version of the #2662 - Need to study how to display the swap
This commit is contained in:
parent
5841d588c8
commit
ef9694cd6a
|
|
@ -57,6 +57,10 @@ mem_critical=90
|
|||
swap_careful=50
|
||||
swap_warning=70
|
||||
swap_critical=90
|
||||
# Source: http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages
|
||||
load_careful=70
|
||||
load_warning=100
|
||||
load_critical=500
|
||||
|
||||
[system]
|
||||
# This plugin display the first line in the Glances UI with:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,12 @@ class Bar(object):
|
|||
sys.stdout.flush()
|
||||
"""
|
||||
|
||||
def __init__(self, size, percentage_char='|', empty_char=' ', pre_char='[', post_char=']', with_text=True):
|
||||
def __init__(self, size,
|
||||
percentage_char='|',
|
||||
empty_char=' ',
|
||||
pre_char='[', post_char=']',
|
||||
display_value=True,
|
||||
min_value=0, max_value=100):
|
||||
# Build curses_bars
|
||||
self.__curses_bars = [empty_char] * 5 + [percentage_char] * 5
|
||||
# Bar size
|
||||
|
|
@ -36,20 +41,20 @@ class Bar(object):
|
|||
# Bar current percent
|
||||
self.__percent = 0
|
||||
# Min and max value
|
||||
self.min_value = 0
|
||||
self.max_value = 100
|
||||
self.min_value = min_value
|
||||
self.max_value = max_value
|
||||
# Char used for the decoration
|
||||
self.__pre_char = pre_char
|
||||
self.__post_char = post_char
|
||||
self.__empty_char = empty_char
|
||||
self.__with_text = with_text
|
||||
self.__display_value = display_value
|
||||
|
||||
@property
|
||||
def size(self, with_decoration=False):
|
||||
# Return the bar size, with or without decoration
|
||||
if with_decoration:
|
||||
return self.__size
|
||||
if self.__with_text:
|
||||
if self.__display_value:
|
||||
return self.__size - 6
|
||||
|
||||
@property
|
||||
|
|
@ -58,10 +63,8 @@ class Bar(object):
|
|||
|
||||
@percent.setter
|
||||
def percent(self, value):
|
||||
if value <= self.min_value:
|
||||
if value < self.min_value:
|
||||
value = self.min_value
|
||||
if value >= self.max_value:
|
||||
value = self.max_value
|
||||
self.__percent = value
|
||||
|
||||
@property
|
||||
|
|
@ -74,14 +77,20 @@ class Bar(object):
|
|||
|
||||
def get(self):
|
||||
"""Return the bars."""
|
||||
frac, whole = modf(self.size * self.percent / 100.0)
|
||||
value = self.percent
|
||||
if value > self.max_value:
|
||||
value = self.max_value
|
||||
frac, whole = modf(self.size * value / 100.0)
|
||||
ret = self.__curses_bars[8] * int(whole)
|
||||
if frac > 0:
|
||||
ret += self.__curses_bars[int(frac * 8)]
|
||||
whole += 1
|
||||
ret += self.__empty_char * int(self.size - whole)
|
||||
if self.__with_text:
|
||||
ret = '{}{:5.1f}%'.format(ret, self.percent)
|
||||
if self.__display_value:
|
||||
if self.percent > self.max_value:
|
||||
ret = '{}>{:4.0f}%'.format(ret, self.max_value)
|
||||
else:
|
||||
ret = '{}{:5.1f}%'.format(ret, self.percent)
|
||||
return ret
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
|||
|
|
@ -58,6 +58,14 @@ items_history_list = [
|
|||
{'name': 'min15', 'description': '15 minutes load'},
|
||||
]
|
||||
|
||||
# Get the number of logical CPU core only once
|
||||
# the variable is also shared with the QuickLook plugin
|
||||
try:
|
||||
nb_log_core = CorePluginModel().update()["log"]
|
||||
except Exception as e:
|
||||
logger.warning('Error: Can not retrieve the CPU core number (set it to 1) ({})'.format(e))
|
||||
nb_log_core = 1
|
||||
|
||||
|
||||
class PluginModel(GlancesPluginModel):
|
||||
"""Glances load plugin.
|
||||
|
|
@ -74,24 +82,6 @@ class PluginModel(GlancesPluginModel):
|
|||
# We want to display the stat in the curse interface
|
||||
self.display_curse = True
|
||||
|
||||
# Call CorePluginModel in order to display the core number
|
||||
try:
|
||||
self.nb_log_core = CorePluginModel(args=self.args).update()["log"]
|
||||
except Exception as e:
|
||||
logger.warning('Error: Can not retrieve the CPU core number (set it to 1) ({})'.format(e))
|
||||
self.nb_log_core = 1
|
||||
|
||||
def _getloadavg(self):
|
||||
"""Get load average. On both Linux and Windows thanks to PsUtil"""
|
||||
try:
|
||||
return psutil.getloadavg()
|
||||
except (AttributeError, OSError):
|
||||
pass
|
||||
try:
|
||||
return os.getloadavg()
|
||||
except (AttributeError, OSError):
|
||||
return None
|
||||
|
||||
@GlancesPluginModel._check_decorator
|
||||
@GlancesPluginModel._log_result_decorator
|
||||
def update(self):
|
||||
|
|
@ -103,11 +93,16 @@ class PluginModel(GlancesPluginModel):
|
|||
# Update stats using the standard system lib
|
||||
|
||||
# Get the load using the os standard lib
|
||||
load = self._getloadavg()
|
||||
load = get_load_average()
|
||||
if load is None:
|
||||
stats = self.get_init_value()
|
||||
else:
|
||||
stats = {'min1': load[0], 'min5': load[1], 'min15': load[2], 'cpucore': self.nb_log_core}
|
||||
stats = {
|
||||
'min1': load[0],
|
||||
'min5': load[1],
|
||||
'min15': load[2],
|
||||
'cpucore': get_nb_log_core()
|
||||
}
|
||||
|
||||
elif self.input_method == 'snmp':
|
||||
# Update stats using SNMP
|
||||
|
|
@ -122,7 +117,7 @@ class PluginModel(GlancesPluginModel):
|
|||
for k, v in iteritems(stats):
|
||||
stats[k] = float(v)
|
||||
|
||||
stats['cpucore'] = self.nb_log_core
|
||||
stats['cpucore'] = get_nb_log_core()
|
||||
|
||||
# Update the stats
|
||||
self.stats = stats
|
||||
|
|
@ -170,9 +165,9 @@ class PluginModel(GlancesPluginModel):
|
|||
ret.append(self.curse_new_line())
|
||||
msg = '{:7}'.format('{} min'.format(load_time))
|
||||
ret.append(self.curse_add_line(msg))
|
||||
if args.disable_irix and self.nb_log_core != 0:
|
||||
if args.disable_irix and get_nb_log_core() != 0:
|
||||
# Enable Irix mode for load (see issue #1554)
|
||||
load_stat = self.stats['min{}'.format(load_time)] / self.nb_log_core * 100
|
||||
load_stat = self.stats['min{}'.format(load_time)] / get_nb_log_core() * 100
|
||||
msg = '{:>5.1f}%'.format(load_stat)
|
||||
else:
|
||||
# Default mode for load
|
||||
|
|
@ -181,3 +176,28 @@ class PluginModel(GlancesPluginModel):
|
|||
ret.append(self.curse_add_line(msg, self.get_views(key='min{}'.format(load_time), option='decoration')))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def get_nb_log_core():
|
||||
"""Get the number of logical CPU core."""
|
||||
return nb_log_core
|
||||
|
||||
|
||||
def get_load_average(percent: bool = False):
|
||||
"""Get load average. On both Linux and Windows thanks to PsUtil
|
||||
|
||||
if percent is True, return the load average in percent
|
||||
Ex: if you only have one CPU core and the load average is 1.0, then return 100%"""
|
||||
load_average = None
|
||||
try:
|
||||
load_average = psutil.getloadavg()
|
||||
except (AttributeError, OSError):
|
||||
try:
|
||||
load_average = os.getloadavg()
|
||||
except (AttributeError, OSError):
|
||||
pass
|
||||
|
||||
if load_average and percent:
|
||||
return tuple([i / get_nb_log_core() * 100 for i in load_average])
|
||||
else:
|
||||
return load_average
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <nicolas@nicolargo.com>
|
||||
# SPDX-FileCopyrightText: 2024 Nicolas Hennion <nicolas@nicolargo.com>
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-only
|
||||
#
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
from glances.logger import logger
|
||||
from glances.cpu_percent import cpu_percent
|
||||
from glances.plugins.load import get_load_average, get_nb_log_core
|
||||
from glances.outputs.glances_bars import Bar
|
||||
from glances.outputs.glances_sparklines import Sparkline
|
||||
from glances.plugins.plugin.model import GlancesPluginModel
|
||||
|
|
@ -84,11 +85,20 @@ class PluginModel(GlancesPluginModel):
|
|||
|
||||
# Grab quicklook stats: CPU, MEM and SWAP
|
||||
if self.input_method == 'local':
|
||||
# Get the latest CPU percent value
|
||||
# Get system information
|
||||
cpu_info = cpu_percent.get_info()
|
||||
stats['cpu_name'] = cpu_info['cpu_name']
|
||||
stats['cpu_hz_current'] = (
|
||||
self._mhz_to_hz(cpu_info['cpu_hz_current']) if cpu_info['cpu_hz_current'] is not None else None
|
||||
)
|
||||
stats['cpu_hz'] = self._mhz_to_hz(cpu_info['cpu_hz']) if cpu_info['cpu_hz'] is not None else None
|
||||
|
||||
# Get the CPU percent value (global and per core)
|
||||
# Stats is shared across all plugins
|
||||
stats['cpu'] = cpu_percent.get()
|
||||
stats['percpu'] = cpu_percent.get(percpu=True)
|
||||
|
||||
# Use the psutil lib for the memory (virtual and swap)
|
||||
# Get the virtual and swap memory
|
||||
stats['mem'] = psutil.virtual_memory().percent
|
||||
try:
|
||||
stats['swap'] = psutil.swap_memory().percent
|
||||
|
|
@ -96,13 +106,14 @@ class PluginModel(GlancesPluginModel):
|
|||
# Correct issue in Illumos OS (see #1767)
|
||||
stats['swap'] = None
|
||||
|
||||
# Get additional information
|
||||
cpu_info = cpu_percent.get_info()
|
||||
stats['cpu_name'] = cpu_info['cpu_name']
|
||||
stats['cpu_hz_current'] = (
|
||||
self._mhz_to_hz(cpu_info['cpu_hz_current']) if cpu_info['cpu_hz_current'] is not None else None
|
||||
)
|
||||
stats['cpu_hz'] = self._mhz_to_hz(cpu_info['cpu_hz']) if cpu_info['cpu_hz'] is not None else None
|
||||
# Get load
|
||||
stats['cpucore'] = get_nb_log_core()
|
||||
try:
|
||||
# Load average is a tuple (1 min, 5 min, 15 min)
|
||||
# Process only the 15 min value
|
||||
stats['load'] = get_load_average(percent=True)[2]
|
||||
except (TypeError, IndexError):
|
||||
stats['load'] = None
|
||||
|
||||
elif self.input_method == 'snmp':
|
||||
# Not available
|
||||
|
|
@ -118,12 +129,16 @@ class PluginModel(GlancesPluginModel):
|
|||
# Call the father's method
|
||||
super(PluginModel, self).update_views()
|
||||
|
||||
# Add specifics information
|
||||
# Alert only
|
||||
# Alert for CPU, MEM and SWAP
|
||||
for key in ['cpu', 'mem', 'swap']:
|
||||
if key in self.stats:
|
||||
self.views[key]['decoration'] = self.get_alert(self.stats[key], header=key)
|
||||
|
||||
# Alert for LOAD
|
||||
self.views['load']['decoration'] = self.get_alert(
|
||||
self.stats['load'], header='load'
|
||||
)
|
||||
|
||||
def msg_curse(self, args=None, max_width=10):
|
||||
"""Return the list to display in the UI."""
|
||||
# Init the return message
|
||||
|
|
@ -145,9 +160,13 @@ class PluginModel(GlancesPluginModel):
|
|||
sparkline_tag = data.available
|
||||
if not sparkline_tag:
|
||||
# Fallback to bar if Sparkline module is not installed
|
||||
data = Bar(max_width, percentage_char=self.get_conf_value('percentage_char', default=['|'])[0])
|
||||
data = Bar(max_width,
|
||||
percentage_char=self.get_conf_value('percentage_char', default=['|'])[0])
|
||||
|
||||
# Build the string message
|
||||
##########################
|
||||
|
||||
# System information
|
||||
if 'cpu_name' in self.stats and 'cpu_hz_current' in self.stats and 'cpu_hz' in self.stats:
|
||||
msg_name = self.stats['cpu_name']
|
||||
if self.stats['cpu_hz_current'] and self.stats['cpu_hz']:
|
||||
|
|
@ -160,7 +179,9 @@ class PluginModel(GlancesPluginModel):
|
|||
ret.append(self.curse_add_line(msg_name))
|
||||
ret.append(self.curse_add_line(msg_freq))
|
||||
ret.append(self.curse_new_line())
|
||||
for key in ['cpu', 'mem', 'swap']:
|
||||
|
||||
# Loop over CPU, MEM and LOAD
|
||||
for key in ['cpu', 'mem', 'load']:
|
||||
if key == 'cpu' and args.percpu:
|
||||
if sparkline_tag:
|
||||
raw_cpu = self.get_raw_history(item='percpu', nb=data.size)
|
||||
|
|
|
|||
Loading…
Reference in New Issue