summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicolargo <nicolashennion@gmail.com>2024-06-16 17:05:53 +0200
committernicolargo <nicolashennion@gmail.com>2024-06-16 17:05:53 +0200
commit0874e13f1d1d9257464fd1cf311b87923b46f931 (patch)
tree387af33f2eb3add57c007fb8e1d16f95b9cab783
parent8b4ef8c2359e386145f4820c270c64f48b6aa03a (diff)
Enhance Glances browser color #977
-rw-r--r--glances/client_browser.py12
-rw-r--r--glances/outputs/glances_curses.py254
-rw-r--r--glances/outputs/glances_curses_browser.py43
3 files changed, 153 insertions, 156 deletions
diff --git a/glances/client_browser.py b/glances/client_browser.py
index 8e0ec721..12a52680 100644
--- a/glances/client_browser.py
+++ b/glances/client_browser.py
@@ -95,12 +95,16 @@ class GlancesClientBrowser:
# Mandatory stats
try:
# CPU%
- cpu_percent = 100 - orjson.loads(s.getPlugin('cpu'))['idle']
- server['cpu_percent'] = f'{cpu_percent:.1f}'
+ # logger.info(f"CPU stats {s.getPlugin('cpu')}")
+ # logger.info(f"CPU views {s.getPluginView('cpu')}")
+ server['cpu_percent'] = orjson.loads(s.getPlugin('cpu'))['total']
+ server['cpu_percent_decoration'] = orjson.loads(s.getPluginView('cpu'))['total']['decoration']
# MEM%
server['mem_percent'] = orjson.loads(s.getPlugin('mem'))['percent']
+ server['mem_percent_decoration'] = orjson.loads(s.getPluginView('mem'))['percent']['decoration']
# OS (Human Readable name)
server['hr_name'] = orjson.loads(s.getPlugin('system'))['hr_name']
+ server['hr_name_decoration'] = 'DEFAULT'
except (OSError, Fault, KeyError) as e:
logger.debug(f"Error while grabbing stats form server ({e})")
server['status'] = 'OFFLINE'
@@ -120,8 +124,8 @@ class GlancesClientBrowser:
# Optional stats (load is not available on Windows OS)
try:
# LOAD
- load_min5 = orjson.loads(s.getPlugin('load'))['min5']
- server['load_min5'] = f'{load_min5:.2f}'
+ server['load_min5'] = round(orjson.loads(s.getPlugin('load'))['min5'], 1)
+ server['load_min5_decoration'] = orjson.loads(s.getPluginView('load'))['min5']['decoration']
except Exception as e:
logger.warning(f"Error while grabbing stats form server ({e})")
diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py
index 16b26079..9280c54d 100644
--- a/glances/outputs/glances_curses.py
+++ b/glances/outputs/glances_curses.py
@@ -162,7 +162,7 @@ class _GlancesCurses:
self._init_cursor()
# Init the colors
- self._init_colors()
+ self.colors_list = build_colors_list(args)
# Init main window
self.term_window = self.screen.subwin(0, 0)
@@ -216,133 +216,6 @@ class _GlancesCurses:
curses.cbreak()
self.set_cursor(0)
- def _init_colors(self):
- """Init the Curses color layout."""
-
- # Set curses options
- try:
- if hasattr(curses, 'start_color'):
- curses.start_color()
- logger.debug(f'Curses interface compatible with {curses.COLORS} colors')
- if hasattr(curses, 'use_default_colors'):
- curses.use_default_colors()
- except Exception as e:
- logger.warning(f'Error initializing terminal color ({e})')
-
- # Init colors
- if self.args.disable_bold:
- A_BOLD = 0
- self.args.disable_bg = True
- else:
- A_BOLD = curses.A_BOLD
-
- self.title_color = A_BOLD
- self.title_underline_color = A_BOLD | curses.A_UNDERLINE
- self.help_color = A_BOLD
-
- if curses.has_colors():
- # The screen is compatible with a colored design
- # ex: export TERM=xterm-256color
- # export TERM=xterm-color
-
- curses.init_pair(1, -1, -1)
- if self.args.disable_bg:
- curses.init_pair(2, curses.COLOR_RED, -1)
- curses.init_pair(3, curses.COLOR_GREEN, -1)
- curses.init_pair(5, curses.COLOR_MAGENTA, -1)
- else:
- curses.init_pair(2, -1, curses.COLOR_RED)
- curses.init_pair(3, -1, curses.COLOR_GREEN)
- curses.init_pair(5, -1, curses.COLOR_MAGENTA)
- curses.init_pair(4, curses.COLOR_BLUE, -1)
- curses.init_pair(6, curses.COLOR_RED, -1)
- curses.init_pair(7, curses.COLOR_GREEN, -1)
- curses.init_pair(8, curses.COLOR_MAGENTA, -1)
-
- # Colors text styles
- self.no_color = curses.color_pair(1)
- self.default_color = curses.color_pair(3) | A_BOLD
- self.nice_color = curses.color_pair(8)
- self.cpu_time_color = curses.color_pair(8)
- self.ifCAREFUL_color = curses.color_pair(4) | A_BOLD
- self.ifWARNING_color = curses.color_pair(5) | A_BOLD
- self.ifCRITICAL_color = curses.color_pair(2) | A_BOLD
- self.default_color2 = curses.color_pair(7)
- self.ifCAREFUL_color2 = curses.color_pair(4)
- self.ifWARNING_color2 = curses.color_pair(8) | A_BOLD
- self.ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
- self.ifINFO_color = curses.color_pair(4)
- self.filter_color = A_BOLD
- self.selected_color = A_BOLD
- self.separator = curses.color_pair(1)
-
- if curses.COLORS > 8:
- # ex: export TERM=xterm-256color
- colors_list = [curses.COLOR_CYAN, curses.COLOR_YELLOW]
- for i in range(0, 3):
- try:
- curses.init_pair(i + 9, colors_list[i], -1)
- except Exception:
- curses.init_pair(i + 9, -1, -1)
- self.filter_color = curses.color_pair(9) | A_BOLD
- self.selected_color = curses.color_pair(10) | A_BOLD
- # Define separator line style
- try:
- curses.init_color(11, 500, 500, 500)
- curses.init_pair(11, curses.COLOR_BLACK, -1)
- self.separator = curses.color_pair(11)
- except Exception:
- # Catch exception in TMUX
- pass
- else:
- # The screen is NOT compatible with a colored design
- # switch to B&W text styles
- # ex: export TERM=xterm-mono
- self.no_color = -1
- self.default_color = -1
- self.nice_color = A_BOLD
- self.cpu_time_color = A_BOLD
- self.ifCAREFUL_color = A_BOLD
- self.ifWARNING_color = curses.A_UNDERLINE
- self.ifCRITICAL_color = curses.A_REVERSE
- self.default_color2 = -1
- self.ifCAREFUL_color2 = A_BOLD
- self.ifWARNING_color2 = curses.A_UNDERLINE
- self.ifCRITICAL_color2 = curses.A_REVERSE
- self.ifINFO_color = A_BOLD
- self.filter_color = A_BOLD
- self.selected_color = A_BOLD
- self.separator = -1
-
- # Define the colors list (hash table) for stats
- self.colors_list = {
- 'DEFAULT': self.no_color,
- 'UNDERLINE': curses.A_UNDERLINE,
- 'BOLD': A_BOLD,
- 'SORT': curses.A_UNDERLINE | A_BOLD,
- 'OK': self.default_color2,
- 'MAX': self.default_color2 | A_BOLD,
- 'FILTER': self.filter_color,
- 'TITLE': self.title_color,
- 'PROCESS': self.default_color2,
- 'PROCESS_SELECTED': self.default_color2 | curses.A_UNDERLINE,
- 'STATUS': self.default_color2,
- 'NICE': self.nice_color,
- 'CPU_TIME': self.cpu_time_color,
- 'CAREFUL': self.ifCAREFUL_color2,
- 'WARNING': self.ifWARNING_color2,
- 'CRITICAL': self.ifCRITICAL_color2,
- 'OK_LOG': self.default_color,
- 'CAREFUL_LOG': self.ifCAREFUL_color,
- 'WARNING_LOG': self.ifWARNING_color,
- 'CRITICAL_LOG': self.ifCRITICAL_color,
- 'PASSWORD': curses.A_PROTECT,
- 'SELECTED': self.selected_color,
- 'INFO': self.ifINFO_color,
- 'ERROR': self.selected_color,
- 'SEPARATOR': self.separator,
- }
-
def set_cursor(self, value):
"""Configure the curse cursor appearance.
@@ -1303,3 +1176,128 @@ class GlancesTextboxYesNo(Textbox):
def do_command(self, ch):
return super().do_command(ch)
+
+
+def build_colors_list(args):
+ """Init the Curses color layout."""
+ # Set curses options
+ try:
+ if hasattr(curses, 'start_color'):
+ curses.start_color()
+ logger.debug(f'Curses interface compatible with {curses.COLORS} colors')
+ if hasattr(curses, 'use_default_colors'):
+ curses.use_default_colors()
+ except Exception as e:
+ logger.warning(f'Error initializing terminal color ({e})')
+
+ # Init colors
+ if args.disable_bold:
+ A_BOLD = 0
+ args.disable_bg = True
+ else:
+ A_BOLD = curses.A_BOLD
+
+ title_color = A_BOLD
+
+ if curses.has_colors():
+ # The screen is compatible with a colored design
+ # ex: export TERM=xterm-256color
+ # export TERM=xterm-color
+
+ curses.init_pair(1, -1, -1)
+ if args.disable_bg:
+ curses.init_pair(2, curses.COLOR_RED, -1)
+ curses.init_pair(3, curses.COLOR_GREEN, -1)
+ curses.init_pair(5, curses.COLOR_MAGENTA, -1)
+ else:
+ curses.init_pair(2, -1, curses.COLOR_RED)
+ curses.init_pair(3, -1, curses.COLOR_GREEN)
+ curses.init_pair(5, -1, curses.COLOR_MAGENTA)
+ curses.init_pair(4, curses.COLOR_BLUE, -1)
+ curses.init_pair(6, curses.COLOR_RED, -1)
+ curses.init_pair(7, curses.COLOR_GREEN, -1)
+ curses.init_pair(8, curses.COLOR_MAGENTA, -1)
+
+ # Colors text styles
+ no_color = curses.color_pair(1)
+ default_color = curses.color_pair(3) | A_BOLD
+ nice_color = curses.color_pair(8)
+ cpu_time_color = curses.color_pair(8)
+ ifCAREFUL_color = curses.color_pair(4) | A_BOLD
+ ifWARNING_color = curses.color_pair(5) | A_BOLD
+ ifCRITICAL_color = curses.color_pair(2) | A_BOLD
+ default_color2 = curses.color_pair(7)
+ ifCAREFUL_color2 = curses.color_pair(4)
+ ifWARNING_color2 = curses.color_pair(8) | A_BOLD
+ ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
+ ifINFO_color = curses.color_pair(4)
+ filter_color = A_BOLD
+ selected_color = A_BOLD
+ separator = curses.color_pair(1)
+
+ if curses.COLORS > 8:
+ # ex: export TERM=xterm-256color
+ colors_list = [curses.COLOR_CYAN, curses.COLOR_YELLOW]
+ for i in range(0, 3):
+ try:
+ curses.init_pair(i + 9, colors_list[i], -1)
+ except Exception:
+ curses.init_pair(i + 9, -1, -1)
+ filter_color = curses.color_pair(9) | A_BOLD
+ selected_color = curses.color_pair(10) | A_BOLD
+ # Define separator line style
+ try:
+ curses.init_color(11, 500, 500, 500)
+ curses.init_pair(11, curses.COLOR_BLACK, -1)
+ separator = curses.color_pair(11)
+ except Exception:
+ # Catch exception in TMUX
+ pass
+ else:
+ # The screen is NOT compatible with a colored design
+ # switch to B&W text styles
+ # ex: export TERM=xterm-mono
+ no_color = -1
+ default_color = -1
+ nice_color = A_BOLD
+ cpu_time_color = A_BOLD
+ ifCAREFUL_color = A_BOLD
+ ifWARNING_color = curses.A_UNDERLINE
+ ifCRITICAL_color = curses.A_REVERSE
+ default_color2 = -1
+ ifCAREFUL_color2 = A_BOLD
+ ifWARNING_color2 = curses.A_UNDERLINE
+ ifCRITICAL_color2 = curses.A_REVERSE
+ ifINFO_color = A_BOLD
+ filter_color = A_BOLD
+ selected_color = A_BOLD
+ separator = -1
+
+ # Define the colors list (hash table) for stats
+ return {
+ 'DEFAULT': no_color,
+ 'UNDERLINE': curses.A_UNDERLINE,
+ 'BOLD': A_BOLD,
+ 'SORT': curses.A_UNDERLINE | A_BOLD,
+ 'OK': default_color2,
+ 'MAX': default_color2 | A_BOLD,
+ 'FILTER': filter_color,
+ 'TITLE': title_color,
+ 'PROCESS': default_color2,
+ 'PROCESS_SELECTED': default_color2 | curses.A_UNDERLINE,
+ 'STATUS': default_color2,
+ 'NICE': nice_color,
+ 'CPU_TIME': cpu_time_color,
+ 'CAREFUL': ifCAREFUL_color2,
+ 'WARNING': ifWARNING_color2,
+ 'CRITICAL': ifCRITICAL_color2,
+ 'OK_LOG': default_color,
+ 'CAREFUL_LOG': ifCAREFUL_color,
+ 'WARNING_LOG': ifWARNING_color,
+ 'CRITICAL_LOG': ifCRITICAL_color,
+ 'PASSWORD': curses.A_PROTECT,
+ 'SELECTED': selected_color,
+ 'INFO': ifINFO_color,
+ 'ERROR': selected_color,
+ 'SEPARATOR': separator,
+ }
diff --git a/glances/outputs/glances_curses_browser.py b/glances/outputs/glances_curses_browser.py
index 858fd5fc..20d0972f 100644
--- a/glances/outputs/glances_curses_browser.py
+++ b/glances/outputs/glances_curses_browser.py
@@ -24,11 +24,11 @@ class GlancesCursesBrowser(_GlancesCurses):
super().__init__(args=args)
_colors_list = {
- 'UNKNOWN': self.no_color,
- 'SNMP': self.default_color2,
- 'ONLINE': self.default_color2,
- 'OFFLINE': self.ifCRITICAL_color2,
- 'PROTECTED': self.ifWARNING_color2,
+ 'UNKNOWN': self.colors_list['DEFAULT'],
+ 'SNMP': self.colors_list['OK'],
+ 'ONLINE': self.colors_list['OK'],
+ 'OFFLINE': self.colors_list['CRITICAL'],
+ 'PROTECTED': self.colors_list['WARNING'],
}
self.colors_list.update(_colors_list)
@@ -299,13 +299,11 @@ class GlancesCursesBrowser(_GlancesCurses):
# Item description: [stats_id, column name, column size]
column_def = [
['name', 'Name', 16],
- ['alias', None, None],
['load_min5', 'LOAD', 6],
['cpu_percent', 'CPU%', 5],
['mem_percent', 'MEM%', 5],
['status', 'STATUS', 9],
['ip', 'IP', 15],
- # ['port', 'PORT', 5],
['hr_name', 'OS', 16],
]
y = 2
@@ -331,24 +329,10 @@ class GlancesCursesBrowser(_GlancesCurses):
# Display table
line = 0
- for v in current_page:
+ for server_stat in current_page:
# Limit the number of displayed server (see issue #1256)
if line >= stats_max:
continue
- # Get server stats
- server_stat = {}
- for c in column_def:
- try:
- server_stat[c[0]] = v[c[0]]
- except KeyError as e:
- logger.debug(f"Cannot grab stats {c[0]} from server (KeyError: {e})")
- server_stat[c[0]] = '?'
- # Display alias instead of name
- try:
- if c[0] == 'alias' and v[c[0]] is not None:
- server_stat['name'] = v[c[0]]
- except KeyError:
- pass
# Display line for server stats
cpt = 0
@@ -362,9 +346,20 @@ class GlancesCursesBrowser(_GlancesCurses):
# Display the line
xc += 2
for c in column_def:
- if xc < screen_x and y < screen_y and c[1] is not None:
+ if xc < screen_x and y < screen_y:
# Display server stats
- self.term_window.addnstr(y, xc, format(server_stat[c[0]]), c[2], self.colors_list[v['status']])
+ value = format(server_stat.get(c[0], '?'))
+ if c[0] == 'name' and 'alias' in server_stat:
+ value = server_stat['alias']
+ decoration = self.colors_list.get(
+ server_stat[c[0] + '_decoration'].replace('_LOG', '')
+ if c[0] + '_decoration' in server_stat
+ else self.colors_list[server_stat['status']],
+ self.colors_list['DEFAULT'],
+ )
+ if c[0] == 'status':
+ decoration = self.colors_list[server_stat['status']]
+ self.term_window.addnstr(y, xc, value, c[2], decoration)
xc += c[2] + self.space_between_column
cpt += 1
# Next line, next server...