feat(lite): network throughput chart (#6610)

This commit is contained in:
rajaa-b
2023-01-19 16:10:36 +01:00
committed by GitHub
parent 2fd6f521f8
commit fe0cc2ebb9
6 changed files with 123 additions and 9 deletions

View File

@@ -8,6 +8,7 @@
- Display RAM usage in pool dashboard (PR [#6419](https://github.com/vatesfr/xen-orchestra/pull/6419))
- Implement not found page (PR [#6410](https://github.com/vatesfr/xen-orchestra/pull/6410))
- Display CPU usage chart in pool dashboard (PR [#6577](https://github.com/vatesfr/xen-orchestra/pull/6577))
- Display network throughput chart in pool dashboard (PR [#6610](https://github.com/vatesfr/xen-orchestra/pull/6610))
## **0.1.0**

View File

@@ -0,0 +1,93 @@
<template>
<!-- TODO: add a loader when data is not fully loaded or undefined -->
<LinearChart
:data="data"
:max-value="customMaxValue"
:subtitle="$t('last-week')"
:title="$t('network-throughput')"
:value-formatter="customValueFormatter"
/>
</template>
<script lang="ts" setup>
import { computed, inject } from "vue";
import { map } from "lodash-es";
import { useI18n } from "vue-i18n";
import LinearChart from "@/components/charts/LinearChart.vue";
import type { FetchedStats } from "@/composables/fetch-stats.composable";
import { formatSize } from "@/libs/utils";
import type { HostStats } from "@/libs/xapi-stats";
import type { LinearChartData } from "@/types/chart";
import { RRD_STEP_FROM_STRING } from "@/libs/xapi-stats";
import type { XenApiHost } from "@/libs/xen-api";
const { t } = useI18n();
const hostLastWeekStats =
inject<FetchedStats<XenApiHost, HostStats>>("hostLastWeekStats");
const data = computed<LinearChartData>(() => {
const stats = hostLastWeekStats?.stats?.value;
const timestampStart = hostLastWeekStats?.timestampStart?.value;
if (timestampStart === undefined || stats === undefined) {
return [];
}
const results = {
tx: new Map<number, { timestamp: number; value: number }>(),
rx: new Map<number, { timestamp: number; value: number }>(),
};
const addResult = (stats: HostStats, type: "tx" | "rx") => {
const networkStats = Object.values(stats.pifs[type]);
for (let hourIndex = 0; hourIndex < networkStats[0].length; hourIndex++) {
const timestamp =
(timestampStart + hourIndex * RRD_STEP_FROM_STRING.hours) * 1000;
const networkThroughput = networkStats.reduce(
(total, throughput) => total + throughput[hourIndex],
0
);
results[type].set(timestamp, {
timestamp,
value: (results[type].get(timestamp)?.value ?? 0) + networkThroughput,
});
}
};
stats.forEach((host) => {
if (!host.stats) {
return;
}
addResult(host.stats, "rx");
addResult(host.stats, "tx");
});
return [
{
label: t("network-upload"),
data: Array.from(results["tx"].values()),
},
{
label: t("network-download"),
data: Array.from(results["rx"].values()),
},
];
});
// TODO: improve the way to get the max value of graph
// See: https://github.com/vatesfr/xen-orchestra/pull/6610/files#r1072237279
const customMaxValue = computed(
() =>
Math.max(
...map(data.value[0].data, "value"),
...map(data.value[1].data, "value")
) * 1.5
);
const customValueFormatter = (value: number) => String(formatSize(value));
</script>

View File

@@ -1,4 +1,4 @@
import { computed, onUnmounted, ref } from "vue";
import { computed, onUnmounted, ref, type ComputedRef } from "vue";
import { type Pausable, promiseTimeout, useTimeoutPoll } from "@vueuse/core";
import {
type GRANULARITY,
@@ -23,6 +23,17 @@ export type Stat<T> = {
pausable: Pausable;
};
export type FetchedStats<
T extends XenApiHost | XenApiVm,
S extends HostStats | VmStats
> = {
register: (object: T) => void;
unregister: (object: T) => void;
stats?: ComputedRef<Stat<S>[]>;
timestampStart?: ComputedRef<number>;
timestampEnd?: ComputedRef<number>;
};
export default function useFetchStats<
T extends XenApiHost | XenApiVm,
S extends HostStats | VmStats

View File

@@ -40,6 +40,9 @@
"login": "Login",
"migrate": "Migrate",
"network": "Network",
"network-download": "Download",
"network-throughput": "Network throughput",
"network-upload": "Upload",
"news": "News",
"news-name": "{name} news",
"object-not-found": "Object {id} can't be found…",

View File

@@ -40,6 +40,9 @@
"login": "Connexion",
"migrate": "Migrer",
"network": "Réseau",
"network-download": "Descendant",
"network-throughput": "Débit du réseau",
"network-upload": "Montant",
"news": "Actualités",
"news-name": "Actualités {name}",
"object-not-found": "L'objet {id} est introuvable…",

View File

@@ -12,6 +12,9 @@
<div class="item">
<PoolDashboardRamUsage />
</div>
<div class="item">
<PoolDashboardNetworkChart />
</div>
<div class="item">
<PoolCpuUsageChart />
</div>
@@ -26,6 +29,7 @@ import { differenceBy } from "lodash-es";
import { computed, onMounted, provide, watch } from "vue";
import PoolCpuUsageChart from "@/components/pool/dashboard/cpuUsage/PoolCpuUsageChart.vue";
import PoolDashboardCpuUsage from "@/components/pool/dashboard/PoolDashboardCpuUsage.vue";
import PoolDashboardNetworkChart from "@/components/pool/dashboard/PoolDashboardNetworkChart.vue";
import PoolDashboardRamUsage from "@/components/pool/dashboard/PoolDashboardRamUsage.vue";
import PoolDashboardStatus from "@/components/pool/dashboard/PoolDashboardStatus.vue";
import PoolDashboardStorageUsage from "@/components/pool/dashboard/PoolDashboardStorageUsage.vue";
@@ -50,11 +54,10 @@ const {
stats: vmStats,
} = useFetchStats<XenApiVm, VmStats>("vm", GRANULARITY.Seconds);
const {
register: hostLastWeekStatsRegister,
unregister: hostLastWeekStatsUnregister,
...hostLastWeekStats
} = useFetchStats<XenApiHost, HostStats>("host", GRANULARITY.Hours);
const hostLastWeekStats = useFetchStats<XenApiHost, HostStats>(
"host",
GRANULARITY.Hours
);
const runningHosts = computed(() => hostStore.allRecords.filter(isHostRunning));
const runningVms = computed(() =>
@@ -70,13 +73,13 @@ watch(runningHosts, (hosts, previousHosts) => {
// turned On
differenceBy(hosts, previousHosts ?? [], "uuid").forEach((host) => {
hostRegister(host);
hostLastWeekStatsRegister(host);
hostLastWeekStats.register(host);
});
// turned Off
differenceBy(previousHosts, hosts, "uuid").forEach((host) => {
hostUnregister(host);
hostLastWeekStatsUnregister(host);
hostLastWeekStats.unregister(host);
});
});
@@ -91,7 +94,7 @@ watch(runningVms, (vms, previousVms) => {
onMounted(() => {
runningHosts.value.forEach((host) => {
hostRegister(host);
hostLastWeekStatsRegister(host);
hostLastWeekStats.register(host);
});
runningVms.value.forEach((vm) => vmRegister(vm));