diff --git a/conf/glances-monitor.conf b/conf/glances-monitor.conf index 55456601..dee997cf 100644 --- a/conf/glances-monitor.conf +++ b/conf/glances-monitor.conf @@ -1,4 +1,8 @@ [cpu] +# Default values if not defined: 50/70/90 +careful=50 +warning=70 +critical=90 # Limit values for CPU user in % # Default values if not defined: 50/70/90 user_careful=50 @@ -34,14 +38,14 @@ careful=0.7 warning=1.0 critical=5.0 -[memory] +[mem] # Default limits for free RAM memory in % # Default values if not defined: 50/70/90 careful=50 warning=70 critical=90 -[swap] +[memswap] # Default limits for free swap memory in % # Default values if not defined: 50/70/90 careful=50 diff --git a/conf/glances.conf b/conf/glances.conf index ea296bb5..c7b80d22 100644 --- a/conf/glances.conf +++ b/conf/glances.conf @@ -1,4 +1,7 @@ [cpu] +careful=50 +warning=70 +critical=90 # Limit values for CPU user in % # Default values if not defined: 50/70/90 user_careful=50 diff --git a/glances/core/glances_standalone.py b/glances/core/glances_standalone.py index 80ffd002..0bf45f7b 100644 --- a/glances/core/glances_standalone.py +++ b/glances/core/glances_standalone.py @@ -49,6 +49,7 @@ class GlancesStandalone(): self.stats = GlancesStats(config) # Initial update + # !!! The first time Glances display wrong CPU information self.stats.update() self.refresh_time = refresh_time diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 95c2d692..786c5184 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -114,49 +114,48 @@ class Plugin(GlancesPlugin): # Build the string message # Header - msg = "{0:7} ".format(_("CPU")) - ret.append(self.curse_add_line(msg, "BOLD")) + msg = "{0:8}".format(_("CPU")) + ret.append(self.curse_add_line(msg, "TITLE")) # Total CPU usage msg = "{0}".format(format((100 - self.stats['idle']) / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + ret.append(self.curse_add_line(msg)) # Steal CPU usage - # !!! TODO: if steal not available if ('steal' in self.stats): - msg = " {0:7} {1}".format( - _("steal:"), - format(self.stats['steal'] / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + msg = " {0:8}".format(_("steal:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.stats['steal'] / 100, '>6.1%')) + ret.append(self.curse_add_line(msg, self.get_alert(self.stats['steal']))) else: msg = "{0:>16}".format(" ") - ret.append(self.curse_add_line(msg, "NORMAL")) + ret.append(self.curse_add_line(msg)) # New line ret.append(self.curse_new_line()) # User CPU if ('user' in self.stats): - msg = "{0:7} {1}".format( - _("user:"), - format(self.stats['user'] / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + msg = "{0:8}".format(_("user:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.stats['user'] / 100, '>6.1%')) + ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['user']))) # Nice CPU if ('nice' in self.stats): msg = " {0:7} {1}".format( _("nice:"), - format(self.stats['user'] / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + format(self.stats['nice'] / 100, '>6.1%')) + ret.append(self.curse_add_line(msg, "DEFAULT")) # New line ret.append(self.curse_new_line()) # System CPU if ('system' in self.stats): - msg = "{0:7} {1}".format( - _("system:"), - format(self.stats['system'] / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + msg = "{0:8}".format(_("system:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.stats['system'] / 100, '>6.1%')) + ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['system']))) # IOWait CPU if ('iowait' in self.stats): - msg = " {0:7} {1}".format( - _("iowait:"), - format(self.stats['iowait'] / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + msg = " {0:8}".format(_("iowait:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.stats['iowait'] / 100, '>6.1%')) + ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['iowait']))) # New line ret.append(self.curse_new_line()) # Idles CPU @@ -164,13 +163,13 @@ class Plugin(GlancesPlugin): msg = "{0:7} {1}".format( _("idle:"), format(self.stats['idle'] / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + ret.append(self.curse_add_line(msg, "DEFAULT")) # IRQ CPU if ('irq' in self.stats): msg = " {0:7} {1}".format( _("irq:"), format(self.stats['irq'] / 100, '>6.1%')) - ret.append(self.curse_add_line(msg, "NORMAL")) + ret.append(self.curse_add_line(msg, "DEFAULT")) # Return the message with decoration return ret diff --git a/glances/plugins/glances_load.py b/glances/plugins/glances_load.py index 6ac4627f..4f1bc0a1 100644 --- a/glances/plugins/glances_load.py +++ b/glances/plugins/glances_load.py @@ -75,39 +75,32 @@ class Plugin(GlancesPlugin): # Build the string message # Header msg = "{0:4} ".format(_("LOAD")) - ret.append(self.curse_add_line(msg, "BOLD")) + ret.append(self.curse_add_line(msg, "TITLE")) # Core number msg = "{0:3}-core".format(self.core_plugin.update()) - ret.append(self.curse_add_line(msg, "NORMAL")) + ret.append(self.curse_add_line(msg)) # New line ret.append(self.curse_new_line()) # 1min load - # msg = "{0:7} {1}".format( - # _("1 min:"), - # format(self.stats['min1'], '>5.2f')) - msg = "{0:7} {1} {2}".format( - _("1 min:"), - format(self.stats['min1'], '>5.2f'), - str(self.get_alert(self.stats['min1'], max=100*self.core_plugin.update()))) - ret.append(self.curse_add_line(msg, "NORMAL")) + msg = "{0:8}".format(_("1 min:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.stats['min1'], '>5.2f')) + ret.append(self.curse_add_line(msg)) # New line ret.append(self.curse_new_line()) # 5min load - msg = "{0:7} {1}".format( - _("5 min:"), - format(self.stats['min5'], '>5.2f')) - ret.append(self.curse_add_line(msg, "NORMAL")) + msg = "{0:8}".format(_("5 min:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.stats['min5'], '>5.2f')) + ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['min5'], + max=100*self.core_plugin.update()))) # New line ret.append(self.curse_new_line()) # 15min load - msg = "{0:7} {1}".format( - _("15 min:"), - format(self.stats['min15'], '>5.2f')) - ret.append(self.curse_add_line(msg, "NORMAL")) + msg = "{0:8}".format(_("15 min:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.stats['min15'], '>5.2f')) + ret.append(self.curse_add_line(msg, self.get_alert_log(self.stats['min15'], + max=100*self.core_plugin.update()))) - # !!! Limits (debug only) - ret.append(self.curse_new_line()) - msg = str(self.get_limits()) - ret.append(self.curse_add_line(msg, "NORMAL")) - return ret \ No newline at end of file diff --git a/glances/plugins/glances_mem.py b/glances/plugins/glances_mem.py index aacc7136..313857ce 100644 --- a/glances/plugins/glances_mem.py +++ b/glances/plugins/glances_mem.py @@ -35,6 +35,15 @@ class Plugin(GlancesPlugin): def __init__(self): GlancesPlugin.__init__(self) + # We want to display the stat in the curse interface + self.display_curse = True + # Set the message position + # It is NOT the curse position but the Glances column/line + # Enter -1 to right align + self.column_curse = 2 + # Enter -1 to diplay bottom + self.line_curse = 1 + def update(self): """ @@ -91,3 +100,78 @@ class Plugin(GlancesPlugin): else: self.stats = {} + + def msg_curse(self): + """ + Return the dict to display in the curse interface + """ + # Init the return message + ret = [] + + # Build the string message + # Header + msg = "{0:5} ".format(_("MEM")) + ret.append(self.curse_add_line(msg, "TITLE")) + # Percent memory usage + msg = "{0}".format(format(self.stats['percent'] / 100, '>6.1%')) + ret.append(self.curse_add_line(msg)) + # Active memory usage + if ('active' in self.stats): + msg = " {0:8}".format(_("actif:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.auto_unit(self.stats['active']), '>6')) + ret.append(self.curse_add_line(msg)) + else: + msg = "{0:>16}".format(" ") + ret.append(self.curse_add_line(msg)) + # New line + ret.append(self.curse_new_line()) + # Total memory usage + msg = "{0:8}".format(_("total:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.auto_unit(self.stats['total'], '>6'))) + ret.append(self.curse_add_line(msg)) + # Inactive memory usage + if ('inactive' in self.stats): + msg = " {0:8}".format(_("inactif:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.auto_unit(self.stats['inactive']), '>6')) + ret.append(self.curse_add_line(msg)) + else: + msg = "{0:>16}".format(" ") + ret.append(self.curse_add_line(msg)) + # New line + ret.append(self.curse_new_line()) + # Used memory usage + msg = "{0:8}".format(_("used:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.auto_unit(self.stats['used'], '>6'))) + ret.append(self.curse_add_line(msg, + self.get_alert_log(self.stats['used'], + max=self.stats['total']))) + # Buffers memory usage + if ('buffers' in self.stats): + msg = " {0:8}".format(_("buffers:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.auto_unit(self.stats['buffers']), '>6')) + ret.append(self.curse_add_line(msg)) + else: + msg = "{0:>16}".format(" ") + ret.append(self.curse_add_line(msg)) + # New line + ret.append(self.curse_new_line()) + # Free memory usage + msg = "{0:8}".format(_("free:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.auto_unit(self.stats['free'], '>6'))) + ret.append(self.curse_add_line(msg)) + # Cached memory usage + if ('free' in self.stats): + msg = " {0:8}".format(_("cached:")) + ret.append(self.curse_add_line(msg)) + msg = "{0}".format(format(self.auto_unit(self.stats['cached']), '>6')) + ret.append(self.curse_add_line(msg)) + else: + msg = "{0:>16}".format(" ") + ret.append(self.curse_add_line(msg)) + return ret diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index 93c8804d..98627fa9 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -99,6 +99,7 @@ class GlancesPlugin(object): def get_alert(self, current=0, min=0, max=100): # Return the alert status relative to a current value + # Use this function for minor stat # If current < CAREFUL of max then alert = OK # If current > CAREFUL of max then alert = CAREFUL # If current > WARNING of max then alert = WARNING @@ -119,6 +120,29 @@ class GlancesPlugin(object): return 'OK' + def get_alert_log(self, current=0, min=0, max=100): + # Return the alert status relative to a current value + # Use this function for major stat + # If current < CAREFUL of max then alert = OK_LOG + # If current > CAREFUL of max then alert = CAREFUL_LOG + # If current > WARNING of max then alert = WARNING_LOG + # If current > CRITICAL of max then alert = CRITICAL_LOG + # stat is USER, SYSTEM, IOWAIT or STEAL + try: + value = (current * 100) / max + except ZeroDivisionError: + return 'DEFAULT' + + if (value > self.get_limit_critical()): + return 'CRITICAL_LOG' + elif (value > self.get_limit_warning()): + return 'WARNING_LOG' + elif (value > self.get_limit_careful()): + return 'CAREFUL_LOG' + + return 'OK_LOG' + + def get_limit_critical(self): return self.limits[self.plugin_name + '_' + 'critical'] @@ -164,12 +188,24 @@ class GlancesPlugin(object): 'line': line_curse } - def curse_add_line(self, msg, decoration="NORMAL"): + def curse_add_line(self, msg, decoration="DEFAULT"): """ Return a dict with: { 'msg': msg, 'decoration': decoration } with: msg: string - decoration: NORMAL (no decoration), UNDERLINE, BOLD, REVERSE + decoration: + DEFAULT: no decoration + UNDERLINE: underline + BOLD: bold + TITLE: for stat title + OK: Value is OK and non logged + OK_LOG: Value is OK and logged + CAREFUL: Value is CAREFUL and non logged + CAREFUL_LOG: Value is CAREFUL and logged + WARINING: Value is WARINING and non logged + WARINING_LOG: Value is WARINING and logged + CRITICAL: Value is CRITICAL and non logged + CRITICAL_LOG: Value is CRITICAL and logged """ return { 'msg': msg, 'decoration': decoration } @@ -181,3 +217,52 @@ class GlancesPlugin(object): """ return self.curse_add_line('\n') + + + def auto_unit(self, val, low_precision=False): + """ + Make a nice human readable string out of val + Number of decimal places increases as quantity approaches 1 + + examples: + CASE: 613421788 RESULT: 585M low_precision: 585M + CASE: 5307033647 RESULT: 4.94G low_precision: 4.9G + CASE: 44968414685 RESULT: 41.9G low_precision: 41.9G + CASE: 838471403472 RESULT: 781G low_precision: 781G + CASE: 9683209690677 RESULT: 8.81T low_precision: 8.8T + CASE: 1073741824 RESULT: 1024M low_precision: 1024M + CASE: 1181116006 RESULT: 1.10G low_precision: 1.1G + + parameter 'low_precision=True' returns less decimal places. + potentially sacrificing precision for more readability + """ + symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') + prefix = { + 'Y': 1208925819614629174706176, + 'Z': 1180591620717411303424, + 'E': 1152921504606846976, + 'P': 1125899906842624, + 'T': 1099511627776, + 'G': 1073741824, + 'M': 1048576, + 'K': 1024 + } + + for key in reversed(symbols): + value = float(val) / prefix[key] + if value > 1: + fixed_decimal_places = 0 + if value < 10: + fixed_decimal_places = 2 + elif value < 100: + fixed_decimal_places = 1 + if low_precision: + if key in 'MK': + fixed_decimal_places = 0 + else: + fixed_decimal_places = min(1, fixed_decimal_places) + elif key in 'K': + fixed_decimal_places = 0 + formatter = "{0:.%df}{1}" % fixed_decimal_places + return formatter.format(value, key) + return "{0!s}".format(val) diff --git a/glances/plugins/glances_system.py b/glances/plugins/glances_system.py index 58c9911a..bfc35eca 100644 --- a/glances/plugins/glances_system.py +++ b/glances/plugins/glances_system.py @@ -96,7 +96,7 @@ class Plugin(GlancesPlugin): self.stats['platform']) # Add the line with decoration - ret.append(self.curse_add_line(msg, "UNDERLINE")) + ret.append(self.curse_add_line(msg, "TITLE")) # Return the message with decoration return ret