Raise an (Alert) Event for a group of sensors #2692

This commit is contained in:
nicolargo 2024-12-21 15:19:34 +01:00
parent d9725d623f
commit 890b5d5dd2
8 changed files with 487 additions and 334 deletions

View File

@ -385,19 +385,26 @@ hide=unknown.*
# Show only the following sensors (comma separated list of regexp)
#show=CPU.*
# Sensors core thresholds (in Celsius...)
# Default values are grabbed from the system
# By default values are grabbed from the system
# Overwrite thresholds for a specific sensor
#temperature_core_Ambient_careful=45
#temperature_core_Ambient_warning=65
#temperature_core_Ambient_critical=80
#temperature_core_Ambient_log=False
# Overwrite thresholds for a specific type of sensor
#temperature_core_careful=45
#temperature_core_warning=65
#temperature_core_critical=80
# Temperatures threshold in °C for hddtemp
# Default values if not defined: 45/52/60
temperature_hdd_careful=45
temperature_hdd_warning=52
temperature_hdd_critical=60
#temperature_hdd_careful=45
#temperature_hdd_warning=52
#temperature_hdd_critical=60
# Battery threshold in %
battery_careful=80
battery_warning=90
battery_critical=95
# Default values if not defined: 70/80/90
#battery_careful=70
#battery_warning=80
#battery_critical=90
# Fan speed threshold in RPM
#fan_speed_careful=100
# Sensors alias

View File

@ -13,29 +13,44 @@ Glances can display the sensors information using ``psutil``,
- hard disk temperature
- battery capacity
There is no alert on this information.
Limit values and sensors alias names can be defined in the configuration
file under the ``[sensors]`` section.
Limit can be defined for a specific sensor, a type of sensor or defineby the system
thresholds (default behavor).
.. code-block:: ini
[sensors]
# Sensors core thresholds (in Celsius...)
# By default values are grabbed from the system
# Overwrite thresholds for a specific sensor
temperature_core_Ambient_careful=45
temperature_core_Ambient_warning=65
temperature_core_Ambient_critical=80
temperature_core_Ambient_log=False
# Overwrite thresholds for a specific type of sensor
#temperature_core_careful=45
#temperature_core_warning=65
#temperature_core_critical=80
.. note 1::
Limit values and sensors alias names can be defined in the
configuration file under the ``[sensors]`` section.
.. note 2::
The support for multiple batteries is only available if
you have the batinfo Python lib installed on your system
because for the moment PSUtil only support one battery.
.. note 3::
.. note 2::
If a sensors has temperature and fan speed with the same name unit,
it is possible to alias it using:
alias=unitname_temperature_core_alias:Alias for temp,unitname_fan_speed_alias:Alias for fan speed
.. note 4::
.. note 3::
If a sensors has multiple identical features names (see #2280), then
Glances will add a suffix to the feature name.
For example, if you have one sensor with two Composite features, the
second one will be named Composite_1.
.. note 5::
.. note 4::
The plugin could crash on some operating system (FreeBSD) with the
TCP or UDP blackhole option > 0 (see issue #2106). In this case, you
should disable the sensors (--disable-plugin sensors or from the

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "GLANCES" "1" "Nov 17, 2024" "4.3.0_dev04" "Glances"
.TH "GLANCES" "1" "Dec 21, 2024" "4.3.0_dev05" "Glances"
.SH NAME
glances \- An eye on your system
.SH SYNOPSIS

View File

@ -261,9 +261,8 @@ class Config:
# Sensors
if not self.parser.has_section('sensors'):
self.parser.add_section('sensors')
self.set_default_cwc('sensors', 'temperature_core', cwc=['60', '70', '80'])
self.set_default_cwc('sensors', 'temperature_hdd', cwc=['45', '52', '60'])
self.set_default_cwc('sensors', 'battery', cwc=['80', '90', '95'])
self.set_default_cwc('sensors', 'battery', cwc=['70', '80', '90'])
# Process list
if not self.parser.has_section('processlist'):

View File

@ -613,7 +613,7 @@ class GlancesPluginModel:
def get_stat_name(self, header=""):
"""Return the stat name with an optional header"""
ret = self.plugin_name
if header != "":
if header != '':
ret += '_' + header
return ret
@ -662,32 +662,26 @@ class GlancesPluginModel:
return 'DEFAULT'
# Build the stat_name
stat_name = self.get_stat_name(header=header)
stat_name = self.get_stat_name(header=header).lower()
# Manage limits
# If is_max is set then default style is set to MAX else default is set to OK
ret = 'MAX' if is_max else 'OK'
# Iter through limits
try:
limit = self.get_limit('critical', stat_name=stat_name)
except KeyError:
try:
limit = self.get_limit('warning', stat_name=stat_name)
except KeyError:
try:
limit = self.get_limit('careful', stat_name=stat_name)
except KeyError:
return 'DEFAULT'
else:
if value >= limit:
ret = 'CAREFUL'
else:
if value >= limit:
ret = 'WARNING'
critical = self.get_limit('critical', stat_name=stat_name)
warning = self.get_limit('warning', stat_name=stat_name)
careful = self.get_limit('careful', stat_name=stat_name)
if critical and value >= critical:
ret = 'CRITICAL'
elif warning and value >= warning:
ret = 'WARNING'
elif careful and value >= careful:
ret = 'CAREFUL'
elif not careful and not warning and not critical:
ret = 'DEFAULT'
else:
if value >= limit:
ret = 'CRITICAL'
ret = 'OK'
if current < minimum:
ret = 'CAREFUL'
@ -727,9 +721,8 @@ class GlancesPluginModel:
def manage_action(self, stat_name, trigger, header, action_key):
"""Manage the action for the current stat."""
# Here is a command line for the current trigger ?
try:
command, repeat = self.get_limit_action(trigger, stat_name=stat_name)
except KeyError:
command, repeat = self.get_limit_action(trigger, stat_name=stat_name)
if not command and not repeat:
# Reset the trigger
self.actions.set(stat_name, trigger)
else:
@ -762,9 +755,7 @@ class GlancesPluginModel:
def is_limit(self, criticality, stat_name=""):
"""Return true if the criticality limit exist for the given stat_name"""
if stat_name == "":
return self.plugin_name + '_' + criticality in self._limits
return stat_name + '_' + criticality in self._limits
return self.get_stat_name(stat_name).lower() + '_' + criticality in self._limits
def get_limit(self, criticality=None, stat_name=""):
"""Return the limit value for the given criticality.
@ -774,13 +765,13 @@ class GlancesPluginModel:
# Get the limit for stat + header
# Example: network_wlan0_rx_careful
stat_name = stat_name.lower()
if stat_name + '_' + criticality in self._limits:
return self._limits[stat_name + '_' + criticality]
if self.plugin_name + '_' + criticality in self._limits:
return self._limits[self.plugin_name + '_' + criticality]
# No key found, the raise an error
raise KeyError
return None
def get_limit_action(self, criticality, stat_name=""):
"""Return the tuple (action, repeat) for the alert.
@ -801,8 +792,8 @@ class GlancesPluginModel:
if r[0] in self._limits:
return self._limits[r[0]], r[1]
# No key found, the raise an error
raise KeyError
# No key found, return None
return None, None
def get_limit_log(self, stat_name, default_action=False):
"""Return the log tag for the alert."""

View File

@ -256,21 +256,13 @@ class PluginModel(GlancesPluginModel):
def get_nice_alert(self, value):
"""Return the alert relative to the Nice configuration list"""
value = str(value)
try:
if value in self.get_limit('nice_critical'):
return 'CRITICAL'
except KeyError:
pass
try:
if value in self.get_limit('nice_warning'):
return 'WARNING'
except KeyError:
pass
try:
if value in self.get_limit('nice_careful'):
return 'CAREFUL'
except KeyError:
pass
if self.get_limit('nice_critical') and value in self.get_limit('nice_critical'):
return 'CRITICAL'
if self.get_limit('nice_warning') and value in self.get_limit('nice_warning'):
return 'WARNING'
if self.get_limit('nice_careful') and value in self.get_limit('nice_careful'):
return 'CAREFUL'
return 'DEFAULT'
def _get_process_curses_cpu_percent(self, p, selected, args):

View File

@ -220,6 +220,19 @@ class PluginModel(GlancesPluginModel):
return stats
def __get_system_thresholds(self, sensor):
"""Return the alert level thanks to the system thresholds"""
alert = 'OK'
if sensor['critical'] is None:
alert = 'DEFAULT'
elif sensor['value'] >= sensor['critical']:
alert = 'CRITICAL'
elif sensor['warning'] is None:
alert = 'DEFAULT'
elif sensor['value'] >= sensor['warning']:
alert = 'WARNING'
return alert
def update_views(self):
"""Update stats views."""
# Call the father's method
@ -232,26 +245,22 @@ class PluginModel(GlancesPluginModel):
continue
# Alert processing
if i['type'] == SensorType.CPU_TEMP:
if self.is_limit('critical', stat_name=SensorType.CPU_TEMP + '_' + i['label']):
# By default use the thresholds configured in the glances.conf file (see #2058)
alert = self.get_alert(current=i['value'], header=SensorType.CPU_TEMP + '_' + i['label'])
if self.is_limit('critical', stat_name=i["type"].value + '_' + i['label']):
# Get thresholds for the specific sensor in the glances.conf file (see #2058)
alert = self.get_alert(current=i['value'], header=i["type"].value + '_' + i['label'])
elif self.is_limit('critical', stat_name=i["type"].value):
# Get thresholds for the sensor type in the glances.conf file (see #3049)
logger.info("Using sensor type thresholds")
logger.info(self._limits)
alert = self.get_alert(current=i['value'], header=i["type"].value)
else:
# Else use the system thresholds
if i['critical'] is None:
alert = 'DEFAULT'
elif i['value'] >= i['critical']:
alert = 'CRITICAL'
elif i['warning'] is None:
alert = 'DEFAULT'
elif i['value'] >= i['warning']:
alert = 'WARNING'
else:
alert = 'OK'
alert = self.__get_system_thresholds(i)
elif i['type'] == SensorType.BATTERY:
# Battery is in %
alert = self.get_alert(current=100 - i['value'], header=i['type'])
alert = self.get_alert(current=100 - i['value'], header=i['type'].value)
else:
alert = self.get_alert(current=i['value'], header=i['type'])
alert = self.get_alert(current=i['value'], header=i['type'].value)
# Set the alert in the view
self.views[i[self.get_key()]]['value']['decoration'] = alert