jcloud/dashboard/src2/views/server/ServerAnalytics.vue

318 lines
7.4 KiB
Vue

<template>
<div class="space-y-4">
<div class="flex space-x-2">
<FormControl
class="w-40"
label="Server"
type="select"
:options="serverOptions"
v-model="chosenServer"
/>
<FormControl
class="w-32"
label="Duration"
type="select"
:options="
durationOptions.map(option => ({ label: option, value: option }))
"
v-model="duration"
/>
</div>
<div class="grid grid-cols-1 gap-5 sm:grid-cols-2">
<LineChart
type="time"
title="CPU"
:key="cpuData"
:data="cpuData"
unit="%"
:chartTheme="[
$theme.colors.green[500], // idle
$theme.colors.red[500], // iowait
$theme.colors.yellow[500], // irq
$theme.colors.pink[500], // nice
$theme.colors.purple[500], // softirq
$theme.colors.blue[500], // steal
$theme.colors.teal[500], // system
$theme.colors.cyan[500] // user
]"
:loading="$resources.cpu.loading"
:error="$resources.cpu.error"
/>
<LineChart
type="time"
title="Load Average"
:key="loadAverageData"
:data="loadAverageData"
:chartTheme="[
$theme.colors.green[500],
$theme.colors.yellow[400],
$theme.colors.red[500]
]"
:loading="$resources.loadavg.loading"
:error="$resources.loadavg.error"
/>
<LineChart
type="time"
title="Memory"
:key="memoryData"
:data="memoryData"
unit="bytes"
:chartTheme="[$theme.colors.yellow[500]]"
:loading="$resources.memory.loading"
:error="$resources.memory.error"
/>
<LineChart
type="time"
title="Disk Space"
:key="spaceData"
:data="spaceData"
unit="%"
:chartTheme="[$theme.colors.red[500]]"
:loading="$resources.space.loading"
:error="$resources.space.error"
/>
<LineChart
type="time"
title="Network"
:key="networkData"
:data="networkData"
unit="bytes"
:chartTheme="[$theme.colors.blue[500]]"
:loading="$resources.network.loading"
:error="$resources.network.error"
/>
<LineChart
type="time"
title="Disk I/O"
:key="iopsData"
:data="iopsData"
unit="I0ps"
:chartTheme="[$theme.colors.purple[500]]"
:loading="$resources.iops.loading"
:error="$resources.iops.error"
/>
</div>
</div>
</template>
<script>
import { DateTime } from 'luxon';
import { getCachedDocumentResource } from 'jingrow-ui';
import LineChart from '@/components/charts/LineChart.vue';
export default {
name: 'ServerAnalytics',
props: ['serverName'],
components: {
LineChart
},
data() {
return {
duration: '1 Hour',
chosenServer: this.$route.query.server ?? this.serverName,
durationOptions: ['1 Hour', '6 Hour', '24 Hour', '7 Days', '15 Days']
};
},
watch: {
chosenServer() {
this.$router.push({
query: {
server: this.chosenServer
}
});
}
},
resources: {
loadavg() {
let localTimezone = DateTime.local().zoneName;
return {
url: 'jcloud.api.server.analytics',
params: {
name: this.chosenServer,
timezone: localTimezone,
query: 'loadavg',
duration: this.duration
},
auto: true
};
},
cpu() {
let localTimezone = DateTime.local().zoneName;
return {
url: 'jcloud.api.server.analytics',
params: {
name: this.chosenServer,
timezone: localTimezone,
query: 'cpu',
duration: this.duration
},
auto: true
};
},
memory() {
let localTimezone = DateTime.local().zoneName;
return {
url: 'jcloud.api.server.analytics',
params: {
name: this.chosenServer,
timezone: localTimezone,
query: 'memory',
duration: this.duration
},
auto: true
};
},
network() {
let localTimezone = DateTime.local().zoneName;
return {
url: 'jcloud.api.server.analytics',
params: {
name: this.chosenServer,
timezone: localTimezone,
query: 'network',
duration: this.duration
},
auto: true
};
},
iops() {
let localTimezone = DateTime.local().zoneName;
return {
url: 'jcloud.api.server.analytics',
params: {
name: this.chosenServer,
timezone: localTimezone,
query: 'iops',
duration: this.duration
},
auto: true
};
},
space() {
let localTimezone = DateTime.local().zoneName;
return {
url: 'jcloud.api.server.analytics',
params: {
name: this.chosenServer,
timezone: localTimezone,
query: 'space',
duration: this.duration
},
auto: true
};
}
},
computed: {
$server() {
return getCachedDocumentResource('Server', this.serverName);
},
serverOptions() {
return [
{
label: 'Application Server',
value: this.$server.pg.name
},
{
label: 'Database Server',
value: this.$server.pg.database_server
},
{
label: 'Replication Server',
value: this.$server.pg.replication_server
}
].filter(v => v.value);
},
loadAverageData() {
let loadavg = this.$resources.loadavg.data;
if (!loadavg) return;
loadavg.datasets.sort(
(a, b) => Number(a.name.split(' ')[2]) - Number(b.name.split(' ')[2])
);
return this.transformMultiLineChartData(loadavg);
},
cpuData() {
let cpu = this.$resources.cpu.data;
if (!cpu) return;
return this.transformMultiLineChartData(cpu, 'cpu', true);
},
memoryData() {
let memory = this.$resources.memory.data;
if (!memory) return;
return this.transformSingleLineChartData(memory);
},
iopsData() {
let iops = this.$resources.iops.data;
if (!iops) return;
return this.transformSingleLineChartData(iops);
},
spaceData() {
let space = this.$resources.space.data;
if (!space) return;
return this.transformSingleLineChartData(space, true);
},
networkData() {
let network = this.$resources.network.data;
if (!network) return;
return this.transformSingleLineChartData(network);
}
},
methods: {
transformSingleLineChartData(data, percentage = false) {
if (!data.datasets?.length) return;
let dataset = [];
const name = data.datasets ? data.datasets[0]?.name : null;
for (let index = 0; index < data.datasets[0].values.length; index++) {
dataset.push([
+new Date(data.labels[index]),
data.datasets[0].values[index]
]);
}
return {
datasets: [{ dataset: dataset, name }],
yMax: percentage ? 100 : null
};
},
transformMultiLineChartData(data, stack = null, percentage = false) {
if (!data.datasets?.length) return;
let total = [];
if (percentage) {
// the sum of each cpu values tends to differ by few values
// so we need to calculate the total for each timestamp
for (let i = 0; i < data.datasets[0].values.length; i++) {
for (let j = 0; j < data.datasets.length; j++) {
if (!total[i]) total[i] = 0;
total[i] += data.datasets[j].values[i];
}
}
}
const datasets = data.datasets.map(({ name, values }) => {
let dataset = [];
for (let i = 0; i < values.length; i++) {
dataset.push([
+new Date(data.labels[i]),
percentage ? (values[i] / total[i]) * 100 : values[i]
]);
}
return { name, dataset, stack };
});
return { datasets, yMax: percentage ? 100 : null };
}
}
};
</script>