diff options
author | nicolargo <nicolashennion@gmail.com> | 2024-06-16 17:05:53 +0200 |
---|---|---|
committer | nicolargo <nicolashennion@gmail.com> | 2024-06-16 17:05:53 +0200 |
commit | 0874e13f1d1d9257464fd1cf311b87923b46f931 (patch) | |
tree | 387af33f2eb3add57c007fb8e1d16f95b9cab783 | |
parent | 8b4ef8c2359e386145f4820c270c64f48b6aa03a (diff) |
Enhance Glances browser color #977
-rw-r--r-- | glances/client_browser.py | 12 | ||||
-rw-r--r-- | glances/outputs/glances_curses.py | 254 | ||||
-rw-r--r-- | glances/outputs/glances_curses_browser.py | 43 |
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... |