mirror of
https://github.com/nicolargo/glances.git
synced 2024-11-23 11:35:19 +03:00
Thread mode ('j' hotkey) is not taken into accound in the WebUI #3019
This commit is contained in:
parent
fa57d5a5ab
commit
a7d5b1e869
@ -123,6 +123,7 @@ Columns display
|
||||
The non-swapped physical memory a process is
|
||||
using (what's currently in the physical memory).
|
||||
``PID`` Process ID (column is replaced by NPROCS in accumulated mode)
|
||||
``NPROCS`` Number of process + childs (only in accumulated mode)
|
||||
``USER`` User ID
|
||||
``THR`` Threads number of the process
|
||||
``TIME+`` Cumulative CPU time used by the process
|
||||
|
569
docs/api.rst
569
docs/api.rst
File diff suppressed because it is too large
Load Diff
@ -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 16, 2024" "4.3.0_dev03" "Glances"
|
||||
.TH "GLANCES" "1" "Nov 17, 2024" "4.3.0_dev04" "Glances"
|
||||
.SH NAME
|
||||
glances \- An eye on your system
|
||||
.SH SYNOPSIS
|
||||
|
@ -616,8 +616,8 @@ Examples of use:
|
||||
args.network_sum = False
|
||||
args.network_cumul = False
|
||||
|
||||
# Processlist id updated in processcount
|
||||
if getattr(args, 'enable_processlist', False):
|
||||
# Processlist is updated in processcount
|
||||
if getattr(args, 'enable_processlist', False) or getattr(args, 'enable_programlist', False):
|
||||
enable(args, 'processcount')
|
||||
|
||||
# Set a default export_process_filter (with all process) when using the stdout mode
|
||||
|
@ -124,8 +124,8 @@ class _GlancesCurses:
|
||||
_left_sidebar_min_width = 23
|
||||
_left_sidebar_max_width = 34
|
||||
|
||||
# Define right sidebar
|
||||
_right_sidebar = ['vms', 'containers', 'processcount', 'amps', 'processlist', 'alert']
|
||||
# Define right sidebar in a method because it depends of self.args.programs
|
||||
# See def _right_sidebar method
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
# Init
|
||||
@ -204,6 +204,16 @@ class _GlancesCurses:
|
||||
# Set the left sidebar list
|
||||
self._left_sidebar = config.get_list_value('outputs', 'left_menu', default=self._left_sidebar)
|
||||
|
||||
def _right_sidebar(self):
|
||||
return [
|
||||
'vms',
|
||||
'containers',
|
||||
'processcount',
|
||||
'amps',
|
||||
'programlist' if self.args.programs else 'processlist',
|
||||
'alert',
|
||||
]
|
||||
|
||||
def _init_history(self):
|
||||
"""Init the history option."""
|
||||
|
||||
@ -790,7 +800,7 @@ class _GlancesCurses:
|
||||
|
||||
# Display right sidebar
|
||||
self.new_column()
|
||||
for p in self._right_sidebar:
|
||||
for p in self._right_sidebar():
|
||||
if (hasattr(self.args, 'enable_' + p) or hasattr(self.args, 'disable_' + p)) and p in stat_display:
|
||||
self.new_line()
|
||||
if p == 'processlist':
|
||||
|
@ -252,10 +252,9 @@ export default {
|
||||
});
|
||||
|
||||
// j => Accumulate processes by program
|
||||
// Disable for the moment, see https://github.com/nicolargo/glances/issues/3019
|
||||
// hotkeys('j', () => {
|
||||
// this.store.args.programs = !this.store.args.programs;
|
||||
// });
|
||||
hotkeys('j', () => {
|
||||
this.store.args.programs = !this.store.args.programs;
|
||||
});
|
||||
|
||||
// k => Show/hide connections stats
|
||||
hotkeys('k', () => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<section class="plugin" id="processlist">
|
||||
<table class="table table-sm table-borderless table-striped table-hover">
|
||||
<section class="plugin" id="processlist" v-if="!args.programs">
|
||||
<!-- Display processes -->
|
||||
<table class=" table table-sm table-borderless table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<td scope="col" :class="['sortable', sorter.column === 'cpu_percent' && 'sort']"
|
||||
@ -40,12 +41,12 @@
|
||||
<td scope="row" v-show="!getDisableStats().includes('nice')">NI</td>
|
||||
<td scope="row" class="table-cell widtd-60" v-show="!getDisableStats().includes('status')">S
|
||||
</td>
|
||||
<td scope="row" v-show="ioReadWritePresent && !getDisableStats().includes('io_counters')"
|
||||
<td scope="row" v-show="ioReadWritePresentProcesses && !getDisableStats().includes('io_counters')"
|
||||
class="hidden-xs hidden-sm" :class="['sortable', sorter.column === 'io_counters' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_counters')">
|
||||
IOR/s
|
||||
</td>
|
||||
<td scope="row" v-show="ioReadWritePresent && !getDisableStats().includes('io_counters')"
|
||||
<td scope="row" v-show="ioReadWritePresentProcesses && !getDisableStats().includes('io_counters')"
|
||||
class="text-start hidden-xs hidden-sm"
|
||||
:class="['sortable', sorter.column === 'io_counters' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_counters')">
|
||||
@ -102,11 +103,133 @@
|
||||
{{ process.status }}
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm"
|
||||
v-show="ioReadWritePresent && !getDisableStats().includes('io_counters')">
|
||||
v-show="ioReadWritePresentProcesses && !getDisableStats().includes('io_counters')">
|
||||
{{ $filters.bytes(process.io_read) }}
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm"
|
||||
v-show="ioReadWritePresent && !getDisableStats().includes('io_counters')">
|
||||
v-show="ioReadWritePresentProcesses && !getDisableStats().includes('io_counters')">
|
||||
{{ $filters.bytes(process.io_write) }}
|
||||
</td>
|
||||
<td scope="row" class="text-truncate"
|
||||
v-show="args.process_short_name && !getDisableStats().includes('cmdline')">
|
||||
{{ process.name }}
|
||||
</td>
|
||||
<td scope="row" v-show="!args.process_short_name && !getDisableStats().includes('cmdline')">
|
||||
{{ process.cmdline }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<section class="plugin" id="processlist" v-if="args.programs">
|
||||
<!-- Display programs -->
|
||||
<table class=" table table-sm table-borderless table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<td scope="col" :class="['sortable', sorter.column === 'cpu_percent' && 'sort']"
|
||||
@click="$emit('update:sorter', 'cpu_percent')"
|
||||
v-show="!getDisableStats().includes('cpu_percent')">
|
||||
CPU%
|
||||
</td>
|
||||
<td scope="col" :class="['sortable', sorter.column === 'memory_percent' && 'sort']"
|
||||
@click="$emit('update:sorter', 'memory_percent')"
|
||||
v-show="!getDisableStats().includes('memory_percent')">
|
||||
MEM%
|
||||
</td>
|
||||
<td scope="col" class="hidden-xs hidden-sm" v-show="!getDisableStats().includes('memory_info')">
|
||||
VIRT
|
||||
</td>
|
||||
<td scope="col" class="hidden-xs hidden-sm" v-show="!getDisableStats().includes('memory_info')">
|
||||
RES
|
||||
</td>
|
||||
<td scope="col" v-show="!getDisableStats().includes('nprocs')">
|
||||
NPROCS
|
||||
</td>
|
||||
<td scope="row" :class="['sortable', sorter.column === 'username' && 'sort']"
|
||||
@click="$emit('update:sorter', 'username')" v-show="!getDisableStats().includes('username')">
|
||||
USER
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm"
|
||||
:class="['sortable', sorter.column === 'timemillis' && 'sort']"
|
||||
@click="$emit('update:sorter', 'timemillis')" v-show="!getDisableStats().includes('cpu_times')">
|
||||
TIME+
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm"
|
||||
:class="['sortable', sorter.column === 'num_threads' && 'sort']"
|
||||
@click="$emit('update:sorter', 'num_threads')"
|
||||
v-show="!getDisableStats().includes('num_threads')">
|
||||
THR
|
||||
</td>
|
||||
<td scope="row" v-show="!getDisableStats().includes('nice')">NI</td>
|
||||
<td scope="row" class="table-cell widtd-60" v-show="!getDisableStats().includes('status')">S
|
||||
</td>
|
||||
<td scope="row" v-show="ioReadWritePresentPrograms && !getDisableStats().includes('io_counters')"
|
||||
class="hidden-xs hidden-sm" :class="['sortable', sorter.column === 'io_counters' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_counters')">
|
||||
IOR/s
|
||||
</td>
|
||||
<td scope="row" v-show="ioReadWritePresentPrograms && !getDisableStats().includes('io_counters')"
|
||||
class="text-start hidden-xs hidden-sm"
|
||||
:class="['sortable', sorter.column === 'io_counters' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_counters')">
|
||||
IOW/s
|
||||
</td>
|
||||
<td scope="row" :class="['sortable', sorter.column === 'name' && 'sort']"
|
||||
@click="$emit('update:sorter', 'name')" v-show="!getDisableStats().includes('cmdline')">
|
||||
Command
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(process, processId) in programs" :key="processId">
|
||||
<td scope="row" :class="getCpuPercentAlert(process)"
|
||||
v-show="!getDisableStats().includes('cpu_percent')">
|
||||
{{ process.cpu_percent == -1 ? '?' : $filters.number(process.cpu_percent, 1) }}
|
||||
</td>
|
||||
<td scope="row" :class="getMemoryPercentAlert(process)"
|
||||
v-show="!getDisableStats().includes('memory_percent')">
|
||||
{{ process.memory_percent == -1 ? '?' : $filters.number(process.memory_percent, 1) }}
|
||||
</td>
|
||||
<td scope="row" v-show="!getDisableStats().includes('memory_info')">
|
||||
{{ $filters.bytes(process.memvirt) }}
|
||||
</td>
|
||||
<td scope="row" v-show="!getDisableStats().includes('memory_info')">
|
||||
{{ $filters.bytes(process.memres) }}
|
||||
</td>
|
||||
<td scope="row" v-show="!getDisableStats().includes('nprocs')">
|
||||
{{ process.nprocs }}
|
||||
</td>
|
||||
<td scope="row" v-show="!getDisableStats().includes('username')">
|
||||
{{ process.username }}
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm" v-if="process.timeplus != '?'"
|
||||
v-show="!getDisableStats().includes('cpu_times')">
|
||||
<span v-show="process.timeplus.hours > 0" class="highlight">{{ process.timeplus.hours }}h</span>
|
||||
{{ $filters.leftPad(process.timeplus.minutes, 2, '0') }}:{{
|
||||
$filters.leftPad(process.timeplus.seconds,
|
||||
2, '0') }}
|
||||
<span v-show="process.timeplus.hours <= 0">.{{ $filters.leftPad(process.timeplus.milliseconds,
|
||||
2, '0')
|
||||
}}</span>
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm" v-if="process.timeplus == '?'"
|
||||
v-show="!getDisableStats().includes('cpu_times')">?</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm" v-show="!getDisableStats().includes('num_threads')">
|
||||
{{ process.num_threads == -1 ? '?' : process.num_threads }}
|
||||
</td>
|
||||
<td scope="row" :class="{ nice: process.isNice }" v-show="!getDisableStats().includes('nice')">
|
||||
{{ $filters.exclamation(process.nice) }}
|
||||
</td>
|
||||
<td scope="row" :class="{ status: process.status == 'R' }"
|
||||
v-show="!getDisableStats().includes('status')">
|
||||
{{ process.status }}
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm"
|
||||
v-show="ioReadWritePresentPrograms && !getDisableStats().includes('io_counters')">
|
||||
{{ $filters.bytes(process.io_read) }}
|
||||
</td>
|
||||
<td scope="row" class="hidden-xs hidden-sm"
|
||||
v-show="ioReadWritePresentPrograms && !getDisableStats().includes('io_counters')">
|
||||
{{ $filters.bytes(process.io_write) }}
|
||||
</td>
|
||||
<td scope="row" class="text-truncate"
|
||||
@ -149,13 +272,13 @@ export default {
|
||||
config() {
|
||||
return this.store.config || {};
|
||||
},
|
||||
stats() {
|
||||
stats_processlist() {
|
||||
return this.data.stats['processlist'];
|
||||
},
|
||||
processes() {
|
||||
const { sorter } = this;
|
||||
const isWindows = this.data.stats['isWindows'];
|
||||
const processes = (this.stats || []).map((process) => {
|
||||
const processes = (this.stats_processlist || []).map((process) => {
|
||||
process.memvirt = '?';
|
||||
process.memres = '?';
|
||||
if (process.memory_info) {
|
||||
@ -224,8 +347,86 @@ export default {
|
||||
[sorter.isReverseColumn(sorter.column) ? 'desc' : 'asc']
|
||||
).slice(0, this.limit);
|
||||
},
|
||||
ioReadWritePresent() {
|
||||
return (this.stats || []).some(({ io_counters }) => io_counters);
|
||||
ioReadWritePresentProcesses() {
|
||||
return (this.stats_processlist || []).some(({ io_counters }) => io_counters);
|
||||
},
|
||||
stats_programlist() {
|
||||
return this.data.stats['programlist'];
|
||||
},
|
||||
programs() {
|
||||
const { sorter } = this;
|
||||
const isWindows = this.data.stats['isWindows'];
|
||||
const programs = (this.stats_programlist || []).map((process) => {
|
||||
process.memvirt = '?';
|
||||
process.memres = '?';
|
||||
if (process.memory_info) {
|
||||
process.memvirt = process.memory_info.vms;
|
||||
process.memres = process.memory_info.rss;
|
||||
}
|
||||
|
||||
if (isWindows && process.username !== null) {
|
||||
process.username = last(process.username.split('\\'));
|
||||
}
|
||||
|
||||
process.timeplus = '?';
|
||||
process.timemillis = '?';
|
||||
if (process.cpu_times) {
|
||||
process.timeplus = timedelta(process.cpu_times);
|
||||
process.timemillis = timemillis(process.cpu_times);
|
||||
}
|
||||
|
||||
if (process.num_threads === null) {
|
||||
process.num_threads = -1;
|
||||
}
|
||||
|
||||
if (process.cpu_percent === null) {
|
||||
process.cpu_percent = -1;
|
||||
}
|
||||
|
||||
if (process.memory_percent === null) {
|
||||
process.memory_percent = -1;
|
||||
}
|
||||
|
||||
process.io_read = null;
|
||||
process.io_write = null;
|
||||
|
||||
if (process.io_counters) {
|
||||
process.io_read =
|
||||
(process.io_counters[0] - process.io_counters[2]) /
|
||||
process.time_since_update;
|
||||
process.io_write =
|
||||
(process.io_counters[1] - process.io_counters[3]) /
|
||||
process.time_since_update;
|
||||
}
|
||||
|
||||
process.isNice =
|
||||
process.nice !== undefined &&
|
||||
((isWindows && process.nice != 32) || (!isWindows && process.nice != 0));
|
||||
|
||||
if (Array.isArray(process.cmdline)) {
|
||||
process.cmdline = process.cmdline.join(' ').replace(/\n/g, ' ');
|
||||
}
|
||||
|
||||
if (process.cmdline === null || process.cmdline.length === 0) {
|
||||
process.cmdline = process.name;
|
||||
}
|
||||
|
||||
return process;
|
||||
});
|
||||
|
||||
return orderBy(
|
||||
programs,
|
||||
[sorter.column].reduce((retval, col) => {
|
||||
if (col === 'io_counters') {
|
||||
col = ['io_read', 'io_write']
|
||||
}
|
||||
return retval.concat(col);
|
||||
}, []),
|
||||
[sorter.isReverseColumn(sorter.column) ? 'desc' : 'asc']
|
||||
).slice(0, this.limit);
|
||||
},
|
||||
ioReadWritePresentPrograms() {
|
||||
return (this.stats_programlist || []).some(({ io_counters }) => io_counters);
|
||||
},
|
||||
limit() {
|
||||
return this.config.outputs !== undefined
|
||||
|
6
glances/outputs/static/public/glances.js
vendored
6
glances/outputs/static/public/glances.js
vendored
File diff suppressed because one or more lines are too long
@ -81,7 +81,7 @@ class PluginModel(GlancesPluginModel):
|
||||
# Update the stats
|
||||
if self.input_method == 'local':
|
||||
# Update stats using the standard system lib
|
||||
# Here, update is call for processcount AND processlist
|
||||
# Here, update is call for processcount, processlist and programlist
|
||||
glances_processes.update()
|
||||
|
||||
# For the ProcessCount, only return the processes count
|
||||
|
@ -230,7 +230,10 @@ class PluginModel(GlancesPluginModel):
|
||||
"""Update processes stats using the input method."""
|
||||
# Update the stats
|
||||
if self.input_method == 'local':
|
||||
stats = self.update_local()
|
||||
# Update stats using the standard system lib
|
||||
# Note: Update is done in the processcount plugin
|
||||
# Just return the result
|
||||
stats = glances_processes.get_list()
|
||||
else:
|
||||
stats = self.get_init_value()
|
||||
|
||||
@ -243,17 +246,6 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
return self.stats
|
||||
|
||||
def update_local(self):
|
||||
# Update stats using the standard system lib
|
||||
# Note: Update is done in the processcount plugin
|
||||
# Just return the result
|
||||
if self.args.programs:
|
||||
stats = glances_processes.get_list(as_programs=True)
|
||||
else:
|
||||
stats = glances_processes.get_list()
|
||||
|
||||
return stats
|
||||
|
||||
def get_export(self):
|
||||
"""Return the processes list to export.
|
||||
Not all the processeses are exported.
|
||||
@ -345,15 +337,8 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
def _get_process_curses_pid(self, p, selected, args):
|
||||
"""Return process PID curses"""
|
||||
if not self.args.programs:
|
||||
# Display processes, so the PID should be displayed
|
||||
msg = self.layout_stat['pid'].format(p['pid'], width=self.__max_pid_size())
|
||||
else:
|
||||
# Display programs, so the PID should not be displayed
|
||||
# Instead displays the number of children
|
||||
msg = self.layout_stat['pid'].format(
|
||||
len(p['childrens']) if 'childrens' in p else '_', width=self.__max_pid_size()
|
||||
)
|
||||
# Display processes, so the PID should be displayed
|
||||
msg = self.layout_stat['pid'].format(p['pid'], width=self._max_pid_size())
|
||||
return self.curse_add_line(msg)
|
||||
|
||||
def _get_process_curses_username(self, p, selected, args):
|
||||
@ -538,19 +523,19 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
# Compute the sort key
|
||||
process_sort_key = glances_processes.sort_key
|
||||
processes_list_sorted = self.__sort_stats(process_sort_key)
|
||||
processes_list_sorted = self._sort_stats(process_sort_key)
|
||||
|
||||
# Display extended stats for selected process
|
||||
#############################################
|
||||
|
||||
if self.is_selected_process(args):
|
||||
self.__msg_curse_extended_process(ret, glances_processes.extended_process)
|
||||
self._msg_curse_extended_process(ret, glances_processes.extended_process)
|
||||
|
||||
# Display others processes list
|
||||
###############################
|
||||
|
||||
# Header
|
||||
self.__msg_curse_header(ret, process_sort_key, args)
|
||||
self._msg_curse_header(ret, process_sort_key, args)
|
||||
|
||||
# Process list
|
||||
# Loop over processes (sorted by the sort key previously compute)
|
||||
@ -563,15 +548,15 @@ class PluginModel(GlancesPluginModel):
|
||||
if glances_processes.process_filter is not None:
|
||||
if args.reset_minmax_tag:
|
||||
args.reset_minmax_tag = not args.reset_minmax_tag
|
||||
self.__mmm_reset()
|
||||
self.__msg_curse_sum(ret, args=args)
|
||||
self.__msg_curse_sum(ret, mmm='min', args=args)
|
||||
self.__msg_curse_sum(ret, mmm='max', args=args)
|
||||
self._mmm_reset()
|
||||
self._msg_curse_sum(ret, args=args)
|
||||
self._msg_curse_sum(ret, mmm='min', args=args)
|
||||
self._msg_curse_sum(ret, mmm='max', args=args)
|
||||
|
||||
# Return the message with decoration
|
||||
return ret
|
||||
|
||||
def __msg_curse_extended_process(self, ret, p):
|
||||
def _msg_curse_extended_process(self, ret, p):
|
||||
"""Get extended curses data for the selected process (see issue #2225)
|
||||
|
||||
The result depends of the process type (process or thread).
|
||||
@ -598,18 +583,7 @@ class PluginModel(GlancesPluginModel):
|
||||
'cpu_max': 7.0,
|
||||
'cpu_mean': 3.2}
|
||||
"""
|
||||
if self.args.programs:
|
||||
self.__msg_curse_extended_process_program(ret, p)
|
||||
else:
|
||||
self.__msg_curse_extended_process_thread(ret, p)
|
||||
|
||||
def __msg_curse_extended_process_program(self, ret, p):
|
||||
# Title
|
||||
msg = "Pinned program {} ('e' to unpin)".format(p['name'])
|
||||
ret.append(self.curse_add_line(msg, "TITLE"))
|
||||
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_new_line())
|
||||
self._msg_curse_extended_process_thread(ret, p)
|
||||
|
||||
def add_title_line(self, ret, prog):
|
||||
ret.append(self.curse_add_line("Pinned thread ", "TITLE"))
|
||||
@ -713,7 +687,7 @@ class PluginModel(GlancesPluginModel):
|
||||
ret.append(self.curse_add_line(' {} '.format(stat_prefix.replace('num_', ''))))
|
||||
return ret
|
||||
|
||||
def __msg_curse_extended_process_thread(self, ret, prog):
|
||||
def _msg_curse_extended_process_thread(self, ret, prog):
|
||||
# `append_newlines` has dummy arguments for piping thru `functools.reduce`
|
||||
def append_newlines(ret, prog):
|
||||
(ret.append(self.curse_new_line()),)
|
||||
@ -733,7 +707,7 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
functools.reduce(lambda ret, step: step(ret, prog), steps, ret)
|
||||
|
||||
def __msg_curse_header(self, ret, process_sort_key, args=None):
|
||||
def _msg_curse_header(self, ret, process_sort_key, args=None):
|
||||
"""Build the header and add it to the ret dict."""
|
||||
sort_style = 'SORT'
|
||||
|
||||
@ -757,10 +731,7 @@ class PluginModel(GlancesPluginModel):
|
||||
msg = self.layout_header['res'].format('RES')
|
||||
ret.append(self.curse_add_line(msg, optional=True))
|
||||
if 'pid' in display_stats:
|
||||
if not self.args.programs:
|
||||
msg = self.layout_header['pid'].format('PID', width=self.__max_pid_size())
|
||||
else:
|
||||
msg = self.layout_header['pid'].format('NPROCS', width=self.__max_pid_size())
|
||||
msg = self.layout_header['pid'].format('PID', width=self._max_pid_size())
|
||||
ret.append(self.curse_add_line(msg))
|
||||
if 'username' in display_stats:
|
||||
msg = self.layout_header['user'].format('USER')
|
||||
@ -793,17 +764,14 @@ class PluginModel(GlancesPluginModel):
|
||||
)
|
||||
)
|
||||
if args.is_standalone and not args.disable_cursor:
|
||||
if self.args.programs:
|
||||
shortkey = "('k' to kill)"
|
||||
else:
|
||||
shortkey = "('e' to pin | 'k' to kill)"
|
||||
shortkey = "('e' to pin | 'k' to kill)"
|
||||
else:
|
||||
shortkey = ""
|
||||
if 'cmdline' in display_stats:
|
||||
msg = self.layout_header['command'].format("Programs" if self.args.programs else "Command", shortkey)
|
||||
msg = self.layout_header['command'].format("Command", shortkey)
|
||||
ret.append(self.curse_add_line(msg, sort_style if process_sort_key == 'name' else 'DEFAULT'))
|
||||
|
||||
def __msg_curse_sum(self, ret, sep_char='_', mmm=None, args=None):
|
||||
def _msg_curse_sum(self, ret, sep_char='_', mmm=None, args=None):
|
||||
"""
|
||||
Build the sum message (only when filter is on) and add it to the ret dict.
|
||||
|
||||
@ -818,11 +786,11 @@ class PluginModel(GlancesPluginModel):
|
||||
ret.append(self.curse_new_line())
|
||||
# CPU percent sum
|
||||
msg = ' '
|
||||
msg += self.layout_stat['cpu'].format(self.__sum_stats('cpu_percent', mmm=mmm))
|
||||
ret.append(self.curse_add_line(msg, decoration=self.__mmm_deco(mmm)))
|
||||
msg += self.layout_stat['cpu'].format(self._sum_stats('cpu_percent', mmm=mmm))
|
||||
ret.append(self.curse_add_line(msg, decoration=self._mmm_deco(mmm)))
|
||||
# MEM percent sum
|
||||
msg = self.layout_stat['mem'].format(self.__sum_stats('memory_percent', mmm=mmm))
|
||||
ret.append(self.curse_add_line(msg, decoration=self.__mmm_deco(mmm)))
|
||||
msg = self.layout_stat['mem'].format(self._sum_stats('memory_percent', mmm=mmm))
|
||||
ret.append(self.curse_add_line(msg, decoration=self._mmm_deco(mmm)))
|
||||
# VIRT and RES memory sum
|
||||
if (
|
||||
'memory_info' in self.stats[0]
|
||||
@ -831,21 +799,21 @@ class PluginModel(GlancesPluginModel):
|
||||
):
|
||||
# VMS
|
||||
msg = self.layout_stat['virt'].format(
|
||||
self.auto_unit(self.__sum_stats('memory_info', sub_key='vms', mmm=mmm), low_precision=False)
|
||||
self.auto_unit(self._sum_stats('memory_info', sub_key='vms', mmm=mmm), low_precision=False)
|
||||
)
|
||||
ret.append(self.curse_add_line(msg, decoration=self.__mmm_deco(mmm), optional=True))
|
||||
ret.append(self.curse_add_line(msg, decoration=self._mmm_deco(mmm), optional=True))
|
||||
# RSS
|
||||
msg = self.layout_stat['res'].format(
|
||||
self.auto_unit(self.__sum_stats('memory_info', sub_key='rss', mmm=mmm), low_precision=False)
|
||||
self.auto_unit(self._sum_stats('memory_info', sub_key='rss', mmm=mmm), low_precision=False)
|
||||
)
|
||||
ret.append(self.curse_add_line(msg, decoration=self.__mmm_deco(mmm), optional=True))
|
||||
ret.append(self.curse_add_line(msg, decoration=self._mmm_deco(mmm), optional=True))
|
||||
else:
|
||||
msg = self.layout_header['virt'].format('')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = self.layout_header['res'].format('')
|
||||
ret.append(self.curse_add_line(msg))
|
||||
# PID
|
||||
msg = self.layout_header['pid'].format('', width=self.__max_pid_size())
|
||||
msg = self.layout_header['pid'].format('', width=self._max_pid_size())
|
||||
ret.append(self.curse_add_line(msg))
|
||||
# USER
|
||||
msg = self.layout_header['user'].format('')
|
||||
@ -866,24 +834,24 @@ class PluginModel(GlancesPluginModel):
|
||||
if 'io_counters' in self.stats[0] and mmm is None:
|
||||
# IO read
|
||||
io_rs = int(
|
||||
(self.__sum_stats('io_counters', 0) - self.__sum_stats('io_counters', sub_key=2, mmm=mmm))
|
||||
(self._sum_stats('io_counters', 0) - self._sum_stats('io_counters', sub_key=2, mmm=mmm))
|
||||
/ self.stats[0]['time_since_update']
|
||||
)
|
||||
if io_rs == 0:
|
||||
msg = self.layout_stat['ior'].format('0')
|
||||
else:
|
||||
msg = self.layout_stat['ior'].format(self.auto_unit(io_rs, low_precision=True))
|
||||
ret.append(self.curse_add_line(msg, decoration=self.__mmm_deco(mmm), optional=True, additional=True))
|
||||
ret.append(self.curse_add_line(msg, decoration=self._mmm_deco(mmm), optional=True, additional=True))
|
||||
# IO write
|
||||
io_ws = int(
|
||||
(self.__sum_stats('io_counters', 1) - self.__sum_stats('io_counters', sub_key=3, mmm=mmm))
|
||||
(self._sum_stats('io_counters', 1) - self._sum_stats('io_counters', sub_key=3, mmm=mmm))
|
||||
/ self.stats[0]['time_since_update']
|
||||
)
|
||||
if io_ws == 0:
|
||||
msg = self.layout_stat['iow'].format('0')
|
||||
else:
|
||||
msg = self.layout_stat['iow'].format(self.auto_unit(io_ws, low_precision=True))
|
||||
ret.append(self.curse_add_line(msg, decoration=self.__mmm_deco(mmm), optional=True, additional=True))
|
||||
ret.append(self.curse_add_line(msg, decoration=self._mmm_deco(mmm), optional=True, additional=True))
|
||||
else:
|
||||
msg = self.layout_header['ior'].format('')
|
||||
ret.append(self.curse_add_line(msg, optional=True, additional=True))
|
||||
@ -898,18 +866,18 @@ class PluginModel(GlancesPluginModel):
|
||||
msg = '(\'M\' to reset)'
|
||||
ret.append(self.curse_add_line(msg, optional=True))
|
||||
|
||||
def __mmm_deco(self, mmm):
|
||||
def _mmm_deco(self, mmm):
|
||||
"""Return the decoration string for the current mmm status."""
|
||||
if mmm is not None:
|
||||
return 'DEFAULT'
|
||||
return 'FILTER'
|
||||
|
||||
def __mmm_reset(self):
|
||||
def _mmm_reset(self):
|
||||
"""Reset the MMM stats."""
|
||||
self.mmm_min = {}
|
||||
self.mmm_max = {}
|
||||
|
||||
def __sum_stats(self, key, sub_key=None, mmm=None):
|
||||
def _sum_stats(self, key, sub_key=None, mmm=None):
|
||||
"""Return the sum of the stats value for the given key.
|
||||
|
||||
:param sub_key: If sub_key is set, get the p[key][sub_key]
|
||||
@ -930,7 +898,7 @@ class PluginModel(GlancesPluginModel):
|
||||
ret += p[key][sub_key]
|
||||
|
||||
# Manage Min/Max/Mean
|
||||
mmm_key = self.__mmm_key(key, sub_key)
|
||||
mmm_key = self._mmm_key(key, sub_key)
|
||||
if mmm == 'min':
|
||||
try:
|
||||
if self.mmm_min[mmm_key] > ret:
|
||||
@ -954,17 +922,17 @@ class PluginModel(GlancesPluginModel):
|
||||
|
||||
return ret
|
||||
|
||||
def __mmm_key(self, key, sub_key):
|
||||
def _mmm_key(self, key, sub_key):
|
||||
ret = key
|
||||
if sub_key is not None:
|
||||
ret += str(sub_key)
|
||||
return ret
|
||||
|
||||
def __sort_stats(self, sorted_by=None):
|
||||
def _sort_stats(self, sorted_by=None):
|
||||
"""Return the stats (dict) sorted by (sorted_by)."""
|
||||
return sort_stats(self.stats, sorted_by, reverse=glances_processes.sort_reverse)
|
||||
|
||||
def __max_pid_size(self):
|
||||
def _max_pid_size(self):
|
||||
"""Return the maximum PID size in number of char."""
|
||||
if self.pid_max is not None:
|
||||
return len(str(self.pid_max))
|
||||
|
@ -54,6 +54,11 @@ def update_program_dict(program, p):
|
||||
program['status'] = p['status'] if p['status'] == program['status'] else '_'
|
||||
|
||||
|
||||
def compute_nprocs(p):
|
||||
p['nprocs'] = len(p['childrens'])
|
||||
return p
|
||||
|
||||
|
||||
def processes_to_programs(processes):
|
||||
"""Convert a list of processes to a list of programs."""
|
||||
# Start to build a dict of programs (key is program name)
|
||||
@ -66,4 +71,4 @@ def processes_to_programs(processes):
|
||||
update_program_dict(programs_dict[p[key]], p)
|
||||
|
||||
# Convert the dict to a list of programs
|
||||
return [programs_dict[p] for p in programs_dict]
|
||||
return [compute_nprocs(p) for p in programs_dict.values()]
|
||||
|
@ -23,7 +23,6 @@ from glances.globals import LINUX, WINDOWS, pretty_date, string_value_to_float,
|
||||
from glances.main import GlancesMain
|
||||
from glances.outputs.glances_bars import Bar
|
||||
from glances.plugins.plugin.model import GlancesPluginModel
|
||||
from glances.programs import processes_to_programs
|
||||
from glances.stats import GlancesStats
|
||||
from glances.thresholds import (
|
||||
GlancesThresholdCareful,
|
||||
@ -470,12 +469,14 @@ class TestGlances(unittest.TestCase):
|
||||
print(f'INFO: SMART stats: {stats_grab}')
|
||||
|
||||
def test_017_programs(self):
|
||||
"""Check Programs function (it's not a plugin)."""
|
||||
"""Check Programs plugin."""
|
||||
# stats_to_check = [ ]
|
||||
print('INFO: [TEST_017] Check PROGRAM stats')
|
||||
stats_grab = processes_to_programs(stats.get_plugin('processlist').get_raw())
|
||||
self.assertIsInstance(stats_grab, list, msg='Programs stats list is not a list')
|
||||
self.assertIsInstance(stats_grab[0], dict, msg='First item should be a dict')
|
||||
print('INFO: [TEST_022] Check PROGRAMS stats')
|
||||
stats_grab = stats.get_plugin('programlist').get_raw()
|
||||
self.assertTrue(isinstance(stats_grab, list), msg='Programs stats is not a list')
|
||||
if stats_grab:
|
||||
self.assertTrue(isinstance(stats_grab[0], dict), msg='Programs stats is not a list of dict')
|
||||
self.assertTrue('nprocs' in stats_grab[0], msg='No nprocs')
|
||||
|
||||
def test_018_string_value_to_float(self):
|
||||
"""Check string_value_to_float function"""
|
||||
|
Loading…
Reference in New Issue
Block a user