First version OK, need change on UI

This commit is contained in:
nicolargo
2025-02-23 19:50:48 +01:00
parent c32d363897
commit f9bbcea9e1
8 changed files with 131 additions and 90 deletions

View File

@@ -222,6 +222,9 @@ class GlancesRestfulApi:
# POST
router.add_api_route(f'{base_path}/events/clear/warning', self._events_clear_warning, methods=['POST'])
router.add_api_route(f'{base_path}/events/clear/all', self._events_clear_all, methods=['POST'])
router.add_api_route(
f'{base_path}/processes/extended/disable', self._api_disable_extended_processes, methods=['POST']
)
router.add_api_route(
f'{base_path}/processes/extended/{{pid}}', self._api_set_extended_processes, methods=['POST']
)
@@ -924,6 +927,18 @@ class GlancesRestfulApi:
return GlancesJSONResponse(True)
def _api_disable_extended_processes(self):
"""Glances API RESTful implementation.
Disable extended process stats
HTTP/200 if OK
HTTP/400 if PID is not found
HTTP/404 if others error
"""
glances_processes.extended_process = None
return GlancesJSONResponse(True)
def _api_get_extended_processes(self):
"""Glances API RESTful implementation.
@@ -937,8 +952,6 @@ class GlancesRestfulApi:
if not process_stats:
process_stats = {}
print("Call _api_get_extended_processes")
return GlancesJSONResponse(process_stats)
def _api_get_processes(self, pid: str):

View File

@@ -168,7 +168,7 @@ body {
margin-bottom: 1em;
}
.clear-button {
.button {
background-color: $glances-link-hover-color !important;
color: white;
border: none;
@@ -178,7 +178,7 @@ body {
transition-duration: 0.4s;
}
.clear-button:hover {
.button:hover {
background-color: white;
color: black;
}
@@ -393,6 +393,7 @@ body {
}
#processlist {
overflow-y: auto;
height: 600px;
.table {

View File

@@ -3,7 +3,7 @@
<span class="title" v-if="hasAlerts">
Warning or critical alerts (last {{ countAlerts }} entries)
<span>
<button class="clear-button" v-on:click="clear()">Clear alerts</button>
<button class="button" v-on:click="clear()">Clear alerts</button>
</span>
</span>
<span class="title" v-else>No warning or critical alert detected</span>

View File

@@ -2,7 +2,33 @@
<!-- Display processes -->
<section class="plugin" id="processlist" v-if="!args.programs">
<div>PIN PROCESS: {{ extended_stat }} - {{ getPinProcess() }}</div>
<div class="extendedstats" v-if="extended_stats !== null">
<div>
<span class="title">Pinned thread: </span>
<span>{{ $filters.limitTo(extended_stats.cmdline, 80) }}</span>
<span><button class="button" v-on:click="disableExtendedStats()">Upin</button></span>
</div>
<div>
<span>CPU Min/Max/Mean: </span>
<span class="careful">{{ $filters.number(extended_stats.cpu_min, 1)
}}% / {{
$filters.number(extended_stats.cpu_max, 1) }}% / {{ $filters.number(extended_stats.cpu_mean, 1)
}}%</span>
<span>Affinity: </span>
<span class="careful">{{ extended_stats.cpu_affinity | length }}</span>
</div>
<div>
<span>MEM Min/Max/Mean: </span>
<span class="careful">{{ $filters.number(extended_stats.memory_min, 1) }}% / {{
$filters.number(extended_stats.memory_max, 1) }}% / {{ $filters.number(extended_stats.memory_mean,
1)
}}%</span>
<span>Memory info: </span>
<span class="careful">
{{ $filters.dictToString(extended_stats.memory_info) }}
</span>
</div>
</div>
<div class="table-responsive d-lg-none">
<table class="table table-sm table-borderless table-striped table-hover">
<thead>
@@ -32,7 +58,7 @@
</tr>
</thead>
<tbody>
<tr v-for="(process, processId) in processes" :key="processId" @click="setPinProcess(process)"
<tr v-for="(process, processId) in processes" :key="processId" @click="setExtendedStats(process)"
style="cursor: pointer">
<td scope="row" :class="getCpuPercentAlert(process)"
v-show="!getDisableStats().includes('cpu_percent')">
@@ -116,8 +142,8 @@
</tr>
</thead>
<tbody>
<tr v-for="(process, processId) in processes" :key="processId" @click="setPinProcess(process.pid)"
style="cursor: pointer">
<tr v-for="(process, processId) in processes" :key="processId"
@click="setExtendedStats(process.pid)" style="cursor: pointer">
<td scope="row" :class="getCpuPercentAlert(process)"
v-show="!getDisableStats().includes('cpu_percent')">
{{ process.cpu_percent == -1 ? '?' : $filters.number(process.cpu_percent, 1) }}
@@ -342,7 +368,7 @@
<script>
import { orderBy, last } from 'lodash';
import { timemillis, timedelta } from '../filters.js';
import { timemillis, timedelta, limitTo, number, dictToString } from '../filters.js';
import { GlancesHelper } from '../services.js';
import { store } from '../store.js';
@@ -357,17 +383,9 @@ export default {
},
data() {
return {
store,
extended_stat: undefined,
intervalId: null
store
};
},
mounted() {
// Refresh every second
this.intervalId = setInterval(() => {
this.getPinProcess()
}, 1000)
},
beforeUnmount() {
clearInterval(this.intervalId)
},
@@ -381,67 +399,13 @@ export default {
stats_processlist() {
return this.data.stats['processlist'];
},
extended_stats() {
return this.stats_processlist.find(item => item['extended_stats'] === true) || null;
},
processes() {
const { sorter } = this;
const isWindows = this.data.stats['isWindows'];
const processes = (this.stats_processlist || []).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.timeforhuman = '?';
if (process.cpu_times) {
process.timeplus = timedelta([process.cpu_times['user'], process.cpu_times['system']]);
process.timeforhuman = process.timeplus.hours.toString().padStart(2, '0') + ':' +
process.timeplus.minutes.toString().padStart(2, '0') + ':' +
process.timeplus.seconds.toString().padStart(2, '0')
}
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.name = process.name + ' ' + process.cmdline.slice(1).join(' ').replace(/\n/g, ' ');
process.cmdline = process.cmdline.join(' ').replace(/\n/g, ' ');
}
if (process.cmdline === null || process.cmdline.length === 0) {
process.cmdline = process.name;
}
return process;
return this.updateProcess(process, this.data.stats['isWindows']);
});
return orderBy(
@@ -541,9 +505,67 @@ export default {
return this.config.outputs !== undefined
? this.config.outputs.max_processes_display
: undefined;
},
}
},
methods: {
updateProcess(process, isWindows) {
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.timeforhuman = '?';
if (process.cpu_times) {
process.timeplus = timedelta([process.cpu_times['user'], process.cpu_times['system']]);
process.timeforhuman = process.timeplus.hours.toString().padStart(2, '0') + ':' +
process.timeplus.minutes.toString().padStart(2, '0') + ':' +
process.timeplus.seconds.toString().padStart(2, '0')
}
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.name = process.name + ' ' + process.cmdline.slice(1).join(' ').replace(/\n/g, ' ');
process.cmdline = process.cmdline.join(' ').replace(/\n/g, ' ');
}
if (process.cmdline === null || process.cmdline.length === 0) {
process.cmdline = process.name;
}
return process
},
getCpuPercentAlert(process) {
return GlancesHelper.getAlert('processlist', 'processlist_cpu_', process.cpu_percent);
},
@@ -553,14 +575,13 @@ export default {
getDisableStats() {
return GlancesHelper.getLimit('processlist', 'processlist_disable_stats') || [];
},
setPinProcess(pid) {
setExtendedStats(pid) {
fetch('api/4/processes/extended/' + pid.toString(), { method: 'POST' })
.then((response) => response.json());
},
getPinProcess() {
fetch('api/4/processes/extended', { method: 'GET' })
.then((response) => response.json())
.then((response) => (this.extended_stat = response));
disableExtendedStats() {
fetch('api/4/processes/extended/disable', { method: 'POST' })
.then((response) => response.json());
}
}
};

View File

@@ -105,7 +105,7 @@ export function nl2br(input) {
export function number(value, options) {
return new Intl.NumberFormat(
undefined,
"en-US",
typeof options === 'number' ? { maximumFractionDigits: options } : options
).format(value);
}
@@ -129,3 +129,8 @@ export function timedelta(value) {
milliseconds: parseInt('' + d.getUTCMilliseconds() / 10)
};
}
export function dictToString(dict) {
return Object.entries(dict).map(([key, value]) => `${key}: ${value}`).join(' / ');
}

View File

@@ -4873,10 +4873,11 @@
"license": "MIT"
},
"node_modules/serialize-javascript": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"randombytes": "^2.1.0"
}
@@ -9523,9 +9524,9 @@
}
},
"serialize-javascript": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"

View File

Binary file not shown.

View File

Binary file not shown.