mirror of
https://github.com/nicolargo/glances.git
synced 2026-06-23 04:58:39 -04:00
First version OK, need change on UI
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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(' / ');
|
||||
}
|
||||
|
||||
|
||||
13
glances/outputs/static/package-lock.json
generated
13
glances/outputs/static/package-lock.json
generated
@@ -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"
|
||||
|
||||
BIN
glances/outputs/static/public/browser.js
vendored
BIN
glances/outputs/static/public/browser.js
vendored
Binary file not shown.
BIN
glances/outputs/static/public/glances.js
vendored
BIN
glances/outputs/static/public/glances.js
vendored
Binary file not shown.
Reference in New Issue
Block a user