mirror of
https://github.com/OkaeriPoland/okaeri-timings.git
synced 2026-01-18 03:28:20 +01:00
Create frontend PoC
This commit is contained in:
23
frontend/.gitignore
vendored
Normal file
23
frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
24
frontend/README.md
Normal file
24
frontend/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# frontend
|
||||
|
||||
## Project setup
|
||||
```
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
yarn serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
5
frontend/babel.config.js
Normal file
5
frontend/babel.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
||||
50
frontend/package.json
Normal file
50
frontend/package.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.0-5",
|
||||
"apexcharts": "^3.33.0",
|
||||
"core-js": "^3.6.5",
|
||||
"mdb-vue-ui-kit": "^1.9.0",
|
||||
"typeface-roboto": "^1.1.13",
|
||||
"vue": "^3.0.0",
|
||||
"vue3-apexcharts": "^1.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^7.0.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
}
|
||||
BIN
frontend/public/favicon.ico
Normal file
BIN
frontend/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
17
frontend/public/index.html
Normal file
17
frontend/public/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>Okaeri Timings</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
50
frontend/public/otimings.sh
Normal file
50
frontend/public/otimings.sh
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
print_metadata() {
|
||||
echo "#"
|
||||
echo "# Okaeri Timings 1.0"
|
||||
echo "#"
|
||||
echo "# Hostname: $(hostname)"
|
||||
# echo "# IP: $(curl -s https://checkip.amazonaws.com/)"
|
||||
echo "# User: $(whoami)"
|
||||
echo "#"
|
||||
echo "# Kernel: $(uname -r)"
|
||||
echo "# OS: $(cat /etc/os-release | grep PRETTY_NAME | awk -F '"' '{print $2}')"
|
||||
echo "#"
|
||||
}
|
||||
|
||||
print_header() {
|
||||
echo "timestamp,cpu/user,cpu/nice,cpu/system,cpu/idle,cpu/iowait,cpu/irq,cpu/softirq,cpu/steal,cpu/guest,cpu/guest_nice,mem/total,mem/free,mem/available,mem/buffers,mem/cached,swap/cached,swap/total,swap/free"
|
||||
}
|
||||
|
||||
print_data() {
|
||||
timestamp=$(date --iso-8601=seconds)
|
||||
|
||||
procstatout=$(cat /proc/stat | grep -m1 ^cpu | cut -d ' ' -f 3-)
|
||||
user=$(echo "$procstatout" | awk '{print $1}')
|
||||
nice=$(echo "$procstatout" | awk '{print $2}')
|
||||
system=$(echo "$procstatout" | awk '{print $3}')
|
||||
idle=$(echo "$procstatout" | awk '{print $4}')
|
||||
iowait=$(echo "$procstatout" | awk '{print $5}')
|
||||
irq=$(echo "$procstatout" | awk '{print $6}')
|
||||
softirq=$(echo "$procstatout" | awk '{print $7}')
|
||||
steal=$(echo "$procstatout" | awk '{print $8}')
|
||||
guest=$(echo "$procstatout" | awk '{print $9}')
|
||||
guest_nice=$(echo "$procstatout" | awk '{print $10}')
|
||||
|
||||
meminfout=$(cat /proc/meminfo)
|
||||
memtotal=$(echo "$meminfout" | grep ^MemTotal: | awk '{print $2}')
|
||||
memfree=$(echo "$meminfout" | grep ^MemFree: | awk '{print $2}')
|
||||
membuffers=$(echo "$meminfout" | grep ^Buffers: | awk '{print $2}')
|
||||
memcached=$(echo "$meminfout" | grep ^Cached: | awk '{print $2}')
|
||||
memavailable=$(echo "$meminfout" | grep ^MemAvailable: | awk '{print $2}')
|
||||
swapcached=$(echo "$meminfout" | grep ^SwapCached: | awk '{print $2}')
|
||||
swaptotal=$(echo "$meminfout" | grep ^SwapTotal: | awk '{print $2}')
|
||||
swapfree=$(echo "$meminfout" | grep ^SwapFree: | awk '{print $2}')
|
||||
|
||||
echo "$timestamp,$user,$nice,$system,$idle,$iowait,$irq,$softirq,$steal,$guest,$guest_nice,$memtotal,$memfree,$memavailable,$membuffers,$memcached,$swapcached,$swaptotal,$swapfree"
|
||||
}
|
||||
|
||||
print_metadata
|
||||
print_header
|
||||
print_data
|
||||
271
frontend/src/App.vue
Normal file
271
frontend/src/App.vue
Normal file
@@ -0,0 +1,271 @@
|
||||
<template>
|
||||
|
||||
<MDBNavbar expand="lg" dark bg="dark" container>
|
||||
<MDBNavbarNav class="mb-lg-0">
|
||||
<MDBNavbarItem href="#" class="font-weight-bold" active>Okaeri Timings</MDBNavbarItem>
|
||||
</MDBNavbarNav>
|
||||
<MDBNavbarNav right class="mb-lg-0">
|
||||
<MDBNavbarItem href="https://github.com/OkaeriPoland/okaeri-timings" active>
|
||||
<font-awesome-icon :icon="['fab', 'github']"/>
|
||||
GitHub
|
||||
</MDBNavbarItem>
|
||||
</MDBNavbarNav>
|
||||
</MDBNavbar>
|
||||
|
||||
<MDBContainer class="my-5">
|
||||
<MDBRow class="gy-4">
|
||||
|
||||
<MDBCol md="12" v-if="!summaryLoaded">
|
||||
<MDBCard>
|
||||
<MDBCardBody>
|
||||
<MDBCardTitle>1. Generate report</MDBCardTitle>
|
||||
<MDBCardText>
|
||||
Execute this command on your Linux based system:
|
||||
<pre class="mt-2 mb-4">curl -s https://timings.okaeri.eu/otimings.sh | bash -s 60</pre>
|
||||
<strong>Note:</strong> report generation takes a long time. Make sure it runs till the end (e.g. using <code>screen</code>)
|
||||
for the best results. The default run-time is <code>60</code> minutes and cannot be shorter than 5 minutes. After the script
|
||||
finalizes its run, the file named 'okaeri-timings-XXX.csv' (e.g. 'okaeri-timings-1642975054.csv') will be available.
|
||||
</MDBCardText>
|
||||
</MDBCardBody>
|
||||
</MDBCard>
|
||||
</MDBCol>
|
||||
|
||||
<MDBCol md="12" v-if="!summaryLoaded">
|
||||
<MDBCard>
|
||||
<MDBCardBody>
|
||||
<MDBCardTitle>2. Upload report</MDBCardTitle>
|
||||
<MDBFile size="lg" label="Please upload 'okaeri-timings-XXX.csv' file" accept=".csv" v-model="files"/>
|
||||
</MDBCardBody>
|
||||
</MDBCard>
|
||||
</MDBCol>
|
||||
|
||||
<MDBCol md="12" v-if="summaryLoaded">
|
||||
<MDBCard>
|
||||
<MDBCardBody>
|
||||
<MDBCardTitle class="d-flex">
|
||||
<span class="me-1">Summary</span>
|
||||
<MDBBadge color="primary">/proc/stat</MDBBadge>
|
||||
</MDBCardTitle>
|
||||
<MDBCardText>
|
||||
This section contains raw data from <code>/proc/stat</code>, visualised and with calculated relative (percent) share of the total CPU time.
|
||||
<ul>
|
||||
<li><em>Current run</em> represents the data between the start and the end of the report generation.</li>
|
||||
<li><em>All time</em> represents absolute values from the last system restart until the end of the report generation.</li>
|
||||
</ul>
|
||||
</MDBCardText>
|
||||
<MDBTabs v-model="summaryTab">
|
||||
<MDBTabNav tabsClasses="mb-3">
|
||||
<MDBTabItem tabId="summary-current-run" href="summary-current-run">Current run</MDBTabItem>
|
||||
<MDBTabItem tabId="summary-all-time" href="summary-all-time">All time</MDBTabItem>
|
||||
</MDBTabNav>
|
||||
<MDBTabContent>
|
||||
<MDBTabPane tabId="summary-current-run">
|
||||
<Summary :key="summaryTab" :stats="summaryStats" :chart-series="summarySeries"/>
|
||||
</MDBTabPane>
|
||||
<MDBTabPane tabId="summary-all-time">
|
||||
<Summary :key="summaryTab" :stats="summaryStatsAll" :chart-series="summarySeriesAll"/>
|
||||
</MDBTabPane>
|
||||
</MDBTabContent>
|
||||
</MDBTabs>
|
||||
</MDBCardBody>
|
||||
</MDBCard>
|
||||
</MDBCol>
|
||||
|
||||
<MDBCol md="12" v-if="summaryLoaded">
|
||||
<MDBCard>
|
||||
<MDBCardBody>
|
||||
<MDBCardTitle class="d-flex">
|
||||
<span class="me-1">History</span>
|
||||
<MDBBadge color="primary">/proc/stat</MDBBadge>
|
||||
</MDBCardTitle>
|
||||
<MDBCardText>
|
||||
This section contains data (currently <code>{{ historyTab.replace('history-', '') }}</code>) changes over time represented as a relative (percent) share of the total CPU time.
|
||||
</MDBCardText>
|
||||
<MDBTabs v-model="historyTab">
|
||||
<MDBTabNav tabsClasses="mb-3">
|
||||
<MDBTabItem v-for="label in dataLabels" :key="label" :tabId="`history-${label}`" :href="`history-${label}`">{{ label }}</MDBTabItem>
|
||||
</MDBTabNav>
|
||||
<MDBTabContent>
|
||||
<MDBTabPane v-for="label in dataLabels" :key="label" :tabId="`history-${label}`">
|
||||
<History :key="historyTab" :name="label" :chart-series="historySeries[label]"/>
|
||||
</MDBTabPane>
|
||||
</MDBTabContent>
|
||||
</MDBTabs>
|
||||
</MDBCardBody>
|
||||
</MDBCard>
|
||||
</MDBCol>
|
||||
|
||||
<MDBCol md="12" v-if="summaryLoaded">
|
||||
<MDBCard>
|
||||
<MDBCardBody>
|
||||
<MDBCardTitle class="d-flex">
|
||||
<span class="me-1">History</span>
|
||||
<MDBBadge color="primary">/proc/meminfo</MDBBadge>
|
||||
</MDBCardTitle>
|
||||
<MDBCardText>
|
||||
This section contains memory usage changes over time.
|
||||
</MDBCardText>
|
||||
<code>TODO</code>
|
||||
</MDBCardBody>
|
||||
</MDBCard>
|
||||
</MDBCol>
|
||||
|
||||
</MDBRow>
|
||||
</MDBContainer>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
MDBBadge,
|
||||
MDBCard,
|
||||
MDBCardBody,
|
||||
MDBCardText,
|
||||
MDBCardTitle,
|
||||
MDBCol,
|
||||
MDBContainer,
|
||||
MDBFile,
|
||||
MDBNavbar,
|
||||
MDBNavbarItem,
|
||||
MDBNavbarNav,
|
||||
MDBRow,
|
||||
MDBTabContent,
|
||||
MDBTabItem,
|
||||
MDBTabNav,
|
||||
MDBTabPane,
|
||||
MDBTabs
|
||||
} from 'mdb-vue-ui-kit';
|
||||
import Summary from "@/components/Summary";
|
||||
import History from "@/components/History";
|
||||
import {ref} from "vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
History,
|
||||
Summary,
|
||||
MDBNavbar,
|
||||
MDBNavbarNav,
|
||||
MDBNavbarItem,
|
||||
MDBContainer,
|
||||
MDBCard,
|
||||
MDBCardBody,
|
||||
MDBCardTitle,
|
||||
MDBFile,
|
||||
MDBRow,
|
||||
MDBCol,
|
||||
MDBTabs,
|
||||
MDBTabNav,
|
||||
MDBTabItem,
|
||||
MDBTabContent,
|
||||
MDBTabPane,
|
||||
MDBCardText,
|
||||
MDBBadge
|
||||
},
|
||||
props: {
|
||||
msg: String
|
||||
},
|
||||
watch: {
|
||||
files: async function (value) {
|
||||
this.rawData = (await this.fileToString(value[0])).split(/\r?\n/).map(l => l.split(" "));
|
||||
const firstLineData = this.rawData[0].slice(1).map(i => parseInt(i));
|
||||
const lastLineData = this.rawData[this.rawData.length - 1].slice(1).map(i => parseInt(i));
|
||||
// update summary
|
||||
this.summarySeriesAll = lastLineData;
|
||||
this.summarySeries = lastLineData.map((i, index) => i - firstLineData[index]);
|
||||
this.summaryLoaded = true;
|
||||
// update history
|
||||
this.dataLabels.forEach((label, index) => {
|
||||
this.historySeries[label] = this.calculateHistory(this.rawData, index);
|
||||
});
|
||||
},
|
||||
summarySeries: function (value) {
|
||||
this.summaryStats = this.calculateSummaryStats(value);
|
||||
},
|
||||
summarySeriesAll: function (value) {
|
||||
this.summaryStatsAll = this.calculateSummaryStats(value);
|
||||
}
|
||||
},
|
||||
setup: function () {
|
||||
return {
|
||||
dataLabels: ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq', 'steal', 'guest', 'guest_nice']
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
files: ref([]),
|
||||
rawData: undefined,
|
||||
// summary
|
||||
summaryTab: ref('summary-current-run'),
|
||||
summaryLoaded: false,
|
||||
summaryStats: [],
|
||||
summaryStatsAll: [],
|
||||
summarySeries: [],
|
||||
summarySeriesAll: [],
|
||||
// steal
|
||||
historyTab: ref('history-steal'),
|
||||
historySeries: {},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
fileToString(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(file, "UTF-8");
|
||||
reader.onload = event => resolve(event.target.result)
|
||||
reader.onerror = event => reject(event);
|
||||
});
|
||||
},
|
||||
calculateSummaryStats(data) {
|
||||
const dataTotal = data.reduce((a, b) => a + b, 0);
|
||||
let stats = [];
|
||||
this.dataLabels.forEach((label, index) => {
|
||||
stats[index] = {
|
||||
name: label,
|
||||
value: data[index],
|
||||
percent: (data[index] / dataTotal) * 100
|
||||
}
|
||||
});
|
||||
stats.sort((a, b) => {
|
||||
return (a.value > b.value) ? -1 : 1;
|
||||
});
|
||||
return stats;
|
||||
},
|
||||
calculateHistory(rawData, index) {
|
||||
let history = [];
|
||||
let lastTotal = 0;
|
||||
let lastValue = 0;
|
||||
rawData.forEach(line => {
|
||||
const date = new Date(line[0]);
|
||||
const rawValue = parseInt(line[index + 1]);
|
||||
const value = rawValue - lastValue;
|
||||
const rawTotal = line.slice(1).map(i => parseInt(i)).reduce((a, b) => a + b, 0);
|
||||
const total = rawTotal - lastTotal;
|
||||
history.push([date, ((value / total) * 100)])
|
||||
lastTotal = rawTotal;
|
||||
lastValue = rawValue;
|
||||
})
|
||||
return history;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
min-height: 100vh;
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: 'Roboto', Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
pre {
|
||||
border: 1px solid;
|
||||
border-radius: 2px;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
BIN
frontend/src/assets/logo.png
Normal file
BIN
frontend/src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
42
frontend/src/components/History.vue
Normal file
42
frontend/src/components/History.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<apexchart type="line" height="300" :options="chartOptions" :series="[{name: name, data: chartSeries}]"></apexchart>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
chartOptions: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {
|
||||
fill: {type: 'solid'},
|
||||
xaxis: {type: 'datetime'},
|
||||
yaxis: {
|
||||
labels: {
|
||||
formatter: function (value) {
|
||||
return value.toFixed(3) + '%';
|
||||
}
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
x: {
|
||||
format: "yyyy-MM-dd HH:mm:ss"
|
||||
}
|
||||
},
|
||||
dataLabels: {enabled: false},
|
||||
animations: {enabled: false},
|
||||
stroke: {curve: 'straight'}
|
||||
};
|
||||
}
|
||||
},
|
||||
chartSeries: {
|
||||
type: Array
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
239
frontend/src/components/Summary.vue
Normal file
239
frontend/src/components/Summary.vue
Normal file
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<MDBRow>
|
||||
<MDBCol md="7">
|
||||
<MDBTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style="width: 30%">#</th>
|
||||
<th scope="col" style="width: 40%">Value</th>
|
||||
<th scope="col" style="width: 30%">Share</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="stat in stats" :key="stat.name">
|
||||
<th scope="row">{{ stat.name }}</th>
|
||||
<td>{{ stat.value }}</td>
|
||||
<td>
|
||||
<template v-if="warningPoints[stat.name] && warningPoints[stat.name](stat.percent) !== null">
|
||||
<MDBBadge :color="warningPoints[stat.name](stat.percent)">
|
||||
{{ (stat.percent).toFixed(3) }}%
|
||||
<font-awesome-icon icon="exclamation-triangle"/>
|
||||
</MDBBadge>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ (stat.percent).toFixed(3) }}%
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MDBTable>
|
||||
</MDBCol>
|
||||
<MDBCol md="5" class="d-flex flex-column">
|
||||
<apexchart type="pie" height="300" class="mb-4" :options="chartOptions" :series="chartSeries"></apexchart>
|
||||
<MDBBtn outline="primary" class="mt-auto ms-auto" aria-controls="summaryHelp" @click="summaryHelpModal = true">
|
||||
<font-awesome-icon icon="question-circle"/>
|
||||
Help
|
||||
</MDBBtn>
|
||||
</MDBCol>
|
||||
|
||||
<MDBModal id="summaryHelpModal" tabindex="-1" labelledby="summaryHelpModalLabel" class="modal-big" v-model="summaryHelpModal">
|
||||
<MDBModalHeader>
|
||||
<MDBModalTitle id="summaryHelpModalLabel"><font-awesome-icon icon="question-circle"/> Help</MDBModalTitle>
|
||||
</MDBModalHeader>
|
||||
<MDBModalBody>
|
||||
<h6>user</h6>
|
||||
<p>
|
||||
Time spent in user mode.<br>
|
||||
(e.g. <mark>applications</mark>)
|
||||
</p>
|
||||
|
||||
<h6>nice</h6>
|
||||
<p>
|
||||
Time spent in user mode with low priority (nice).<br>
|
||||
(e.g. <mark>applications running with <a href="https://en.wikipedia.org/wiki/Nice_(Unix)" target="_blank" rel="noopener nofollow noreferrer">nice > 0</a></mark>)
|
||||
</p>
|
||||
|
||||
<h6>system</h6>
|
||||
<p>
|
||||
Time spent in system mode.<br>
|
||||
(e.g. <mark>networking</mark>, <mark>firewall</mark>, <mark>drivers</mark>)
|
||||
</p>
|
||||
|
||||
<h6>idle</h6>
|
||||
<p>Time spent in the idle task. This value should be USER_HZ times the second entry in the /proc/uptime pseudo-file.</p>
|
||||
|
||||
<h6>iowait <small>(since Linux 2.5.41)</small></h6>
|
||||
<p>Time waiting for I/O to complete. This value is not reliable, for the following reasons:</p>
|
||||
<ol>
|
||||
<li>
|
||||
The CPU will not wait for I/O to complete; iowait is the time that a task is waiting for I/O to complete.
|
||||
When a CPU goes into idle state for outstanding task I/O, another task will be scheduled on this CPU.
|
||||
</li>
|
||||
<li>
|
||||
On a multi-core CPU, the task waiting for I/O to complete is not running on any CPU, so the iowait
|
||||
of each CPU is difficult to calculate.
|
||||
</li>
|
||||
<li>
|
||||
The value in this field may decrease in certain conditions.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h6>irq <small>(since Linux 2.6.0)</small></h6>
|
||||
<p>Time servicing interrupts.</p>
|
||||
|
||||
<h6>softirq <small>(since Linux 2.6.0)</small></h6>
|
||||
<p>Time servicing softirqs.</p>
|
||||
|
||||
<h6>steal <small>(since Linux 2.6.11)</small></h6>
|
||||
<p>Stolen time, which is the time spent in other operating systems when running in a virtualized environment.</p>
|
||||
|
||||
<h6>guest <small>(since Linux 2.6.24)</small></h6>
|
||||
<p>Time spent running a virtual CPU for guest operating systems under the control of the Linux kernel.</p>
|
||||
|
||||
<h6>guest_nice <small>(since Linux 2.6.33)</small></h6>
|
||||
<p>Time spent running a niced guest (virtual CPU for guest operating systems under the control of the Linux kernel).</p>
|
||||
</MDBModalBody>
|
||||
<MDBModalFooter>
|
||||
|
||||
<p class="mb-0 me-auto">
|
||||
This help page comes from the Linux manual for proc:
|
||||
<a href="#" @click="copyrightCollapse = !copyrightCollapse" aria-controls="copyrightCollapse" :aria-expanded="copyrightCollapse">Copyright</a>,
|
||||
<a href="#" @click="licenseCollapse = !licenseCollapse" aria-controls="licenseCollapse" :aria-expanded="licenseCollapse">License</a>
|
||||
</p>
|
||||
<MDBBtn color="primary" @click="summaryHelpModal = false">Close</MDBBtn>
|
||||
|
||||
<MDBCollapse id="copyrightCollapse" v-model="copyrightCollapse" class="w-100">
|
||||
<pre class="mt-2 mb-0">
|
||||
Copyright (C) 1994, 1995 by Daniel Quinlan (quinlan@yggdrasil.com)
|
||||
and Copyright (C) 2002-2008,2017 Michael Kerrisk <mtk.manpages@gmail.com>
|
||||
with networking additions from Alan Cox (A.Cox@swansea.ac.uk)
|
||||
and scsi additions from Michael Neuffer (neuffer@mail.uni-mainz.de)
|
||||
and sysctl additions from Andries Brouwer (aeb@cwi.nl)
|
||||
and System V IPC (as well as various other) additions from
|
||||
Michael Kerrisk <mtk.manpages@gmail.com>
|
||||
</pre>
|
||||
</MDBCollapse>
|
||||
|
||||
<MDBCollapse id="licenseCollapse" v-model="licenseCollapse" class="w-100">
|
||||
<pre class="mt-2 mb-0">
|
||||
This is free documentation; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
The GNU General Public License's references to "object code"
|
||||
and "executables" are to be interpreted as the output of any
|
||||
document formatting or typesetting system, including
|
||||
intermediate and printed output.
|
||||
|
||||
This manual is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this manual; if not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
</pre>
|
||||
</MDBCollapse>
|
||||
|
||||
</MDBModalFooter>
|
||||
</MDBModal>
|
||||
|
||||
</MDBRow>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {MDBBadge, MDBBtn, MDBCol, MDBModal, MDBModalBody, MDBModalFooter, MDBModalHeader, MDBModalTitle, MDBRow, MDBTable, MDBCollapse} from "mdb-vue-ui-kit";
|
||||
import {ref} from "vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MDBRow,
|
||||
MDBCol,
|
||||
MDBTable,
|
||||
MDBBadge,
|
||||
MDBBtn,
|
||||
MDBModal,
|
||||
MDBModalHeader,
|
||||
MDBModalTitle,
|
||||
MDBModalBody,
|
||||
MDBModalFooter,
|
||||
MDBCollapse
|
||||
},
|
||||
watch: {
|
||||
copyrightCollapse: function (value) {
|
||||
if (value) {
|
||||
setTimeout(() => document.getElementById("copyrightCollapse").scrollIntoView({behavior: 'smooth'}), 250);
|
||||
}
|
||||
},
|
||||
licenseCollapse: function (value) {
|
||||
if (value) {
|
||||
setTimeout(() => document.getElementById("licenseCollapse").scrollIntoView({behavior: 'smooth'}), 250);
|
||||
}
|
||||
},
|
||||
},
|
||||
props: {
|
||||
stats: {
|
||||
type: Array
|
||||
},
|
||||
warningPoints: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {
|
||||
user: function (value) {
|
||||
return (value > 90) ? 'danger' : (value > 70) ? 'warning' : null
|
||||
},
|
||||
system: function (value) {
|
||||
return (value > 20) ? 'danger' : (value > 10) ? 'warning' : null
|
||||
},
|
||||
idle: function (value) {
|
||||
return (value < 10) ? 'danger' : (value < 30) ? 'warning' : null
|
||||
},
|
||||
iowait: function (value) {
|
||||
return (value > 10) ? 'danger' : (value > 3) ? 'warning' : null
|
||||
},
|
||||
steal: function (value) {
|
||||
return (value > 20) ? 'danger' : (value > 5) ? 'warning' : null
|
||||
},
|
||||
guest: function (value) {
|
||||
return (value > 90) ? 'danger' : (value > 70) ? 'warning' : null
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
chartOptions: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {
|
||||
labels: ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq', 'steal', 'guest', 'guest_nice'],
|
||||
colors: ['#00aa00', '#0000aa', '#aa0000', '#aaaaaa', '#ff5555', '#ffaa00', '#ff00ff', '#44dddd', '#00aaaa', '#00aaaa'],
|
||||
animations: {enabled: false},
|
||||
};
|
||||
}
|
||||
},
|
||||
chartSeries: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
summaryHelpModal: ref(false),
|
||||
copyrightCollapse: ref(false),
|
||||
licenseCollapse: ref(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.badge {
|
||||
font-size: unset;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.modal-big .modal-dialog {
|
||||
max-width: 1000px;
|
||||
}
|
||||
</style>
|
||||
13
frontend/src/main.js
Normal file
13
frontend/src/main.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'mdb-vue-ui-kit/css/mdb.min.css'
|
||||
import 'typeface-roboto/index.css'
|
||||
|
||||
import {createApp} from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
import fontAwesome from "@/plugins/font-awesome";
|
||||
import VueApexCharts from "vue3-apexcharts";
|
||||
|
||||
const app = createApp(App);
|
||||
app.use(fontAwesome);
|
||||
app.use(VueApexCharts);
|
||||
app.mount('#app')
|
||||
15
frontend/src/plugins/font-awesome.js
Normal file
15
frontend/src/plugins/font-awesome.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import {library} from '@fortawesome/fontawesome-svg-core'
|
||||
import {FontAwesomeIcon, FontAwesomeLayers} from '@fortawesome/vue-fontawesome'
|
||||
|
||||
import {faGithub} from "@fortawesome/free-brands-svg-icons/faGithub";
|
||||
import {faExclamationTriangle} from "@fortawesome/free-solid-svg-icons/faExclamationTriangle";
|
||||
import {faQuestionCircle} from "@fortawesome/free-solid-svg-icons/faQuestionCircle";
|
||||
|
||||
library.add(faGithub);
|
||||
library.add(faExclamationTriangle);
|
||||
library.add(faQuestionCircle);
|
||||
|
||||
export default (app) => {
|
||||
app.component('font-awesome-icon', FontAwesomeIcon);
|
||||
app.component('font-awesome-layers', FontAwesomeLayers);
|
||||
}
|
||||
8796
frontend/yarn.lock
Normal file
8796
frontend/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user