mirror of https://github.com/nicolargo/glances
Merge pull request #2145 from fr4nc0is/2138-added-sortable-columns-docker-plugin
added sortable columns in docker pluginpull/2153/head
commit
a4067cd856
|
@ -234,6 +234,41 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
setupHotKeys() {
|
||||
// a => Sort processes/docker automatically
|
||||
hotkeys('a', () => {
|
||||
this.store.args.sort_processes_key = null;
|
||||
});
|
||||
|
||||
// c => Sort processes/docker by CPU%
|
||||
hotkeys('c', () => {
|
||||
this.store.args.sort_processes_key = 'cpu_percent';
|
||||
});
|
||||
|
||||
// m => Sort processes/docker by MEM%
|
||||
hotkeys('m', () => {
|
||||
this.store.args.sort_processes_key = 'memory_percent';
|
||||
});
|
||||
|
||||
// u => Sort processes/docker by user
|
||||
hotkeys('u', () => {
|
||||
this.store.args.sort_processes_key = 'username';
|
||||
});
|
||||
|
||||
// p => Sort processes/docker by name
|
||||
hotkeys('p', () => {
|
||||
this.store.args.sort_processes_key = 'name';
|
||||
});
|
||||
|
||||
// i => Sort processes/docker by I/O rate
|
||||
hotkeys('i', () => {
|
||||
this.store.args.sort_processes_key = 'io_counters';
|
||||
});
|
||||
|
||||
// t => Sort processes/docker by time
|
||||
hotkeys('t', () => {
|
||||
this.store.args.sort_processes_key = 'timemillis';
|
||||
});
|
||||
|
||||
// A => Enable/disable AMPs
|
||||
hotkeys('shift+A', () => {
|
||||
this.store.args.disable_amps = !this.store.args.disable_amps;
|
||||
|
|
|
@ -1,14 +1,32 @@
|
|||
<template>
|
||||
<section id="containers-plugin" class="plugin" v-if="containers.length">
|
||||
<span class="title">CONTAINERS</span>
|
||||
{{ containers.length }} (served by Docker {{ version }})
|
||||
{{ containers.length }} sorted by {{ sorter.getColumnLabel(sorter.column) }}
|
||||
<div class="table">
|
||||
<div class="table-row">
|
||||
<div class="table-cell text-left">Name</div>
|
||||
<div
|
||||
class="table-cell text-left"
|
||||
:class="['sortable', sorter.column === 'name' && 'sort']"
|
||||
@click="args.sort_processes_key = 'name'"
|
||||
>
|
||||
Name
|
||||
</div>
|
||||
<div class="table-cell">Status</div>
|
||||
<div class="table-cell">Uptime</div>
|
||||
<div class="table-cell">CPU%</div>
|
||||
<div class="table-cell">MEM</div>
|
||||
<div
|
||||
class="table-cell"
|
||||
:class="['sortable', sorter.column === 'cpu_percent' && 'sort']"
|
||||
@click="args.sort_processes_key = 'cpu_percent'"
|
||||
>
|
||||
CPU%
|
||||
</div>
|
||||
<div
|
||||
class="table-cell"
|
||||
:class="['sortable', sorter.column === 'memory_percent' && 'sort']"
|
||||
@click="args.sort_processes_key = 'memory_percent'"
|
||||
>
|
||||
MEM
|
||||
</div>
|
||||
<div class="table-cell">/MAX</div>
|
||||
<div class="table-cell">IOR/s</div>
|
||||
<div class="table-cell">IOW/s</div>
|
||||
|
@ -29,10 +47,10 @@
|
|||
{{ container.uptime }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ $filters.number(container.cpu, 1) }}
|
||||
{{ $filters.number(container.cpu_percent, 1) }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ $filters.bytes(container.memory) }}
|
||||
{{ $filters.bytes(container.memory_usage) }}
|
||||
</div>
|
||||
<div class="table-cell">
|
||||
{{ $filters.bytes(container.limit) }}
|
||||
|
@ -58,26 +76,42 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { orderBy } from 'lodash';
|
||||
import { store } from '../store.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
data: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
store,
|
||||
sorter: undefined
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
args() {
|
||||
return this.store.args || {};
|
||||
},
|
||||
sortProcessesKey() {
|
||||
return this.args.sort_processes_key;
|
||||
},
|
||||
stats() {
|
||||
return this.data.stats['docker'];
|
||||
},
|
||||
containers() {
|
||||
return (this.stats.containers || []).map((containerData) => {
|
||||
const { sorter } = this;
|
||||
const containers = (this.stats.containers || []).map((containerData) => {
|
||||
// prettier-ignore
|
||||
return {
|
||||
'id': containerData.Id,
|
||||
'name': containerData.name,
|
||||
'status': containerData.Status,
|
||||
'uptime': containerData.Uptime,
|
||||
'cpu': containerData.cpu.total,
|
||||
'memory': containerData.memory.usage != undefined ? containerData.memory.usage : '?',
|
||||
'cpu_percent': containerData.cpu.total,
|
||||
'memory_usage': containerData.memory.usage != undefined ? containerData.memory.usage : '?',
|
||||
'limit': containerData.memory.limit != undefined ? containerData.memory.limit : '?',
|
||||
'ior': containerData.io.ior != undefined ? containerData.io.ior : '?',
|
||||
'iow': containerData.io.iow != undefined ? containerData.io.iow : '?',
|
||||
|
@ -87,11 +121,48 @@ export default {
|
|||
'net_time_since_update': containerData.network.time_since_update,
|
||||
'command': containerData.Command.join(' '),
|
||||
'image': containerData.Image
|
||||
};
|
||||
};
|
||||
});
|
||||
},
|
||||
version() {
|
||||
return (this.stats['version'] || {})['Version'];
|
||||
return orderBy(
|
||||
containers,
|
||||
[sorter.column].reduce((retval, col) => {
|
||||
if (col === 'memory_percent') {
|
||||
col = ['memory_usage'];
|
||||
}
|
||||
return retval.concat(col);
|
||||
}, []),
|
||||
[sorter.isReverseColumn(sorter.column) ? 'desc' : 'asc']
|
||||
);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
sortProcessesKey: {
|
||||
immediate: true,
|
||||
handler(sortProcessesKey) {
|
||||
const sortable = ['cpu_percent', 'memory_percent', 'name'];
|
||||
function isReverseColumn(column) {
|
||||
return !['name'].includes(column);
|
||||
}
|
||||
function getColumnLabel(value) {
|
||||
const labels = {
|
||||
io_counters: 'disk IO',
|
||||
cpu_percent: 'CPU consumption',
|
||||
memory_usage: 'memory consumption',
|
||||
cpu_times: 'uptime',
|
||||
name: 'container name',
|
||||
None: 'None'
|
||||
};
|
||||
return labels[value] || value;
|
||||
}
|
||||
if (!sortProcessesKey || sortable.includes(sortProcessesKey)) {
|
||||
this.sorter = {
|
||||
column: this.args.sort_processes_key || 'cpu_percent',
|
||||
auto: !this.args.sort_processes_key,
|
||||
isReverseColumn,
|
||||
getColumnLabel
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<span v-if="port.status == 'null'">Scanning</span>
|
||||
<span v-else-if="port.status == 'false'">Timeout</span>
|
||||
<span v-else-if="port.status == 'true'">Open</span>
|
||||
<span v-else> {{ $filters.number(numberport.status * 1000.0, 0) }}ms </span>
|
||||
<span v-else>{{ $filters.number(port.status * 1000.0, 0) }}ms</span>
|
||||
</div>
|
||||
<div :class="getWebDecoration(port)" class="table-cell" v-if="port.url">
|
||||
<span v-if="port.status == 'null'">Scanning</span>
|
||||
|
|
|
@ -10,13 +10,12 @@
|
|||
<glances-plugin-processlist
|
||||
:sorter="sorter"
|
||||
:data="data"
|
||||
@update:sorter="sorter.column = $event"
|
||||
@update:sorter="args.sort_processes_key = $event"
|
||||
></glances-plugin-processlist>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import hotkeys from 'hotkeys-js';
|
||||
import { store } from '../store.js';
|
||||
import GlancesPluginAmps from './plugin-amps.vue';
|
||||
import GlancesPluginProcesscount from './plugin-processcount.vue';
|
||||
|
@ -36,83 +35,56 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
store,
|
||||
sorter: {
|
||||
column: 'cpu_percent',
|
||||
auto: true,
|
||||
isReverseColumn(column) {
|
||||
return !(column === 'username' || column === 'name');
|
||||
},
|
||||
getColumnLabel(column) {
|
||||
if (column === 'io_read' || column === 'io_write') {
|
||||
return 'io_counters';
|
||||
} else {
|
||||
return column;
|
||||
}
|
||||
}
|
||||
}
|
||||
sorter: undefined
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
args() {
|
||||
return this.store.args || {};
|
||||
},
|
||||
sortProcessesKey() {
|
||||
return this.args.sort_processes_key;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setupHotKeys() {
|
||||
// a => Sort processes automatically
|
||||
hotkeys('a', () => {
|
||||
this.sorter.column = 'cpu_percent';
|
||||
this.sorter.auto = true;
|
||||
});
|
||||
|
||||
// c => Sort processes by CPU%
|
||||
hotkeys('c', () => {
|
||||
this.sorter.column = 'cpu_percent';
|
||||
this.sorter.auto = false;
|
||||
});
|
||||
|
||||
// m => Sort processes by MEM%
|
||||
hotkeys('m', () => {
|
||||
this.sorter.column = 'memory_percent';
|
||||
this.sorter.auto = false;
|
||||
});
|
||||
|
||||
// u => Sort processes by user
|
||||
hotkeys('u', () => {
|
||||
this.sorter.column = 'username';
|
||||
this.sorter.auto = false;
|
||||
});
|
||||
|
||||
// p => Sort processes by name
|
||||
hotkeys('p', () => {
|
||||
this.sorter.column = 'name';
|
||||
this.sorter.auto = false;
|
||||
});
|
||||
|
||||
// i => Sort processes by I/O rate
|
||||
hotkeys('i', () => {
|
||||
this.sorter.column = ['io_read', 'io_write'];
|
||||
this.sorter.auto = false;
|
||||
});
|
||||
|
||||
// t => Sort processes by time
|
||||
hotkeys('t', () => {
|
||||
this.sorter.column = 'timemillis';
|
||||
this.sorter.auto = false;
|
||||
});
|
||||
watch: {
|
||||
sortProcessesKey: {
|
||||
immediate: true,
|
||||
handler(sortProcessesKey) {
|
||||
const sortable = [
|
||||
'cpu_percent',
|
||||
'memory_percent',
|
||||
'username',
|
||||
'timemillis',
|
||||
'num_threads',
|
||||
'io_counters',
|
||||
'name'
|
||||
];
|
||||
function isReverseColumn(column) {
|
||||
return !['username', 'name'].includes(column);
|
||||
}
|
||||
function getColumnLabel(value) {
|
||||
const labels = {
|
||||
io_counters: 'disk IO',
|
||||
cpu_percent: 'CPU consumption',
|
||||
memory_percent: 'memory consumption',
|
||||
cpu_times: 'process time',
|
||||
username: 'user name',
|
||||
name: 'process name',
|
||||
timemillis: 'process time',
|
||||
None: 'None'
|
||||
};
|
||||
return labels[value] || value;
|
||||
}
|
||||
if (!sortProcessesKey || sortable.includes(sortProcessesKey)) {
|
||||
this.sorter = {
|
||||
column: this.args.sort_processes_key || 'cpu_percent',
|
||||
auto: !this.args.sort_processes_key,
|
||||
isReverseColumn,
|
||||
getColumnLabel
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setupHotKeys();
|
||||
},
|
||||
beforeUnmount() {
|
||||
hotkeys.unbind('a');
|
||||
hotkeys.unbind('c');
|
||||
hotkeys.unbind('m');
|
||||
hotkeys.unbind('u');
|
||||
hotkeys.unbind('p');
|
||||
hotkeys.unbind('i');
|
||||
hotkeys.unbind('t');
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -5,7 +5,7 @@
|
|||
<span>{{ running }} run,</span>
|
||||
<span>{{ sleeping }} slp,</span>
|
||||
<span>{{ stopped }} oth</span>
|
||||
<span class="title">sorted {{ sorter.auto ? 'automatically' : '' }}</span>
|
||||
<span class="title">{{ sorter.auto ? 'sorted automatically' : 'sorted' }}</span>
|
||||
<span>by {{ sorter.getColumnLabel(sorter.column) }}</span>
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
@ -46,16 +46,16 @@
|
|||
<div
|
||||
v-show="ioReadWritePresent"
|
||||
class="table-cell hidden-xs hidden-sm"
|
||||
:class="['sortable', sorter.column === 'io_read' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_read')"
|
||||
:class="['sortable', sorter.column === 'io_counters' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_counters')"
|
||||
>
|
||||
IOR/s
|
||||
</div>
|
||||
<div
|
||||
v-show="ioReadWritePresent"
|
||||
class="table-cell text-left hidden-xs hidden-sm"
|
||||
:class="['sortable', sorter.column === 'io_write' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_write')"
|
||||
:class="['sortable', sorter.column === 'io_counters' && 'sort']"
|
||||
@click="$emit('update:sorter', 'io_counters')"
|
||||
>
|
||||
IOW/s
|
||||
</div>
|
||||
|
@ -215,7 +215,12 @@ export default {
|
|||
|
||||
return orderBy(
|
||||
processes,
|
||||
[sorter.column],
|
||||
[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);
|
||||
},
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue