529 lines
14 KiB
Vue
529 lines
14 KiB
Vue
<template>
|
|
<v-row v-if="this.formState.ready" v-resize="onResize">
|
|
<gz-error :error-box-message="formState.errorBoxMessage"></gz-error>
|
|
<v-col cols="12" sm="6" lg="4" xl="3">
|
|
<v-select
|
|
v-model="selectedTimePeriod"
|
|
:items="selectLists.dateFilterTokens"
|
|
item-text="name"
|
|
item-value="id"
|
|
append-outer-icon="$ayiSync"
|
|
@click:append-outer="getDataFromApi"
|
|
@input="timePeriodChanged"
|
|
data-cy="selectedTimePeriod"
|
|
></v-select>
|
|
</v-col>
|
|
|
|
<v-tabs v-model="tab" @change="tabChanged">
|
|
<v-tabs-slider></v-tabs-slider>
|
|
<v-tab>{{ $ay.t("MetricCPUMemory") }}</v-tab>
|
|
<v-tab>{{ $ay.t("Database") }}</v-tab>
|
|
<v-tab>{{ $ay.t("MetricFileStorage") }}</v-tab>
|
|
|
|
<v-tabs-items v-model="tab">
|
|
<v-tab-item>
|
|
<v-col cols="12">
|
|
<gz-chart-line
|
|
:chart-data="memAllChartData"
|
|
:options="timeLineChartOptions"
|
|
class="my-12"
|
|
/>
|
|
</v-col>
|
|
<v-col cols="12">
|
|
<gz-chart-line
|
|
:chart-data="cpuChartData"
|
|
:options="timeLineChartOptions"
|
|
class="my-12"
|
|
/>
|
|
</v-col>
|
|
</v-tab-item>
|
|
<v-tab-item>
|
|
<v-col cols="12">
|
|
<gz-chart-line
|
|
:chart-data="dbChartData"
|
|
:options="timeLineChartOptions"
|
|
class="my-12"
|
|
/>
|
|
</v-col>
|
|
<v-col cols="12" lg="10" xl="8">
|
|
<gz-chart-bar-horizontal
|
|
:chart-data="dbTopTablesChartData"
|
|
:options="{
|
|
responsive: true,
|
|
scales: {
|
|
xAxes: [{ gridLines: { display: true } }],
|
|
yAxes: [{ gridLines: { display: false } }]
|
|
}
|
|
}"
|
|
class="my-12"
|
|
/>
|
|
</v-col>
|
|
</v-tab-item>
|
|
<v-tab-item>
|
|
<v-col cols="12">
|
|
<gz-chart-line
|
|
:chart-data="fileSizeChartData"
|
|
:options="timeLineChartOptions"
|
|
class="my-12"
|
|
/>
|
|
</v-col>
|
|
<v-col cols="12">
|
|
<gz-chart-line
|
|
:chart-data="attachmentCountChartData"
|
|
:options="timeLineChartOptions"
|
|
class="my-12"
|
|
/>
|
|
</v-col>
|
|
</v-tab-item>
|
|
</v-tabs-items>
|
|
</v-tabs>
|
|
</v-row>
|
|
</template>
|
|
|
|
<script>
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/* Xeslint-disable */
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//https://blog.hubspot.com/marketing/types-of-graphs-for-data-visualization
|
|
//https://medium.com/javascript-in-plain-english/exploring-chart-js-e3ba70b07aa4
|
|
import relativeDatefilterCalculator from "../api/relative-date-filter-calculator.js";
|
|
import Palette from "../api/palette";
|
|
const FORM_KEY = "ops-metrics";
|
|
|
|
export default {
|
|
async created() {
|
|
let vm = this;
|
|
try {
|
|
await initForm(vm);
|
|
window.$gz.eventBus.$on("menu-click", clickHandler);
|
|
generateMenu(vm);
|
|
await vm.getDataFromApi();
|
|
} catch (err) {
|
|
vm.formState.ready = true;
|
|
window.$gz.errorHandler.handleFormError(err, vm);
|
|
}
|
|
},
|
|
beforeDestroy() {
|
|
window.$gz.eventBus.$off("menu-click", clickHandler);
|
|
},
|
|
data() {
|
|
return {
|
|
storage: { isnew: true },
|
|
memcpu: { isnew: true },
|
|
db: { isnew: true },
|
|
timeLineChartOptions: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
xAxes: [
|
|
{
|
|
type: "time",
|
|
|
|
// distribution: "linear",
|
|
gridLines: {
|
|
drawOnChartArea: false
|
|
}
|
|
}
|
|
],
|
|
yAxes: [
|
|
{
|
|
gridLines: {
|
|
drawOnChartArea: false
|
|
},
|
|
ticks: {
|
|
beginAtZero: true
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
selectedTimePeriod: "*past6hours*",
|
|
selectLists: {
|
|
dateFilterTokens: []
|
|
},
|
|
lastFetchBreakPoint: null,
|
|
tab: 0,
|
|
formState: {
|
|
ready: false,
|
|
loading: false,
|
|
errorBoxMessage: null,
|
|
appError: null,
|
|
serverError: {}
|
|
}
|
|
};
|
|
},
|
|
|
|
methods: {
|
|
onResize() {
|
|
let breakPoint = "xl";
|
|
if (window.innerWidth < 1904) {
|
|
breakPoint = "lg";
|
|
}
|
|
if (window.innerWidth < 1264) {
|
|
breakPoint = "md";
|
|
}
|
|
if (window.innerWidth < 960) {
|
|
breakPoint = "sm";
|
|
}
|
|
if (window.innerWidth < 600) {
|
|
breakPoint = "xs";
|
|
}
|
|
if (breakPoint != this.lastFetchBreakPoint) {
|
|
this.getDataFromApi(breakPoint);
|
|
}
|
|
},
|
|
timePeriodChanged: function() {
|
|
this.getDataFromApi();
|
|
},
|
|
tabChanged: function(tab) {
|
|
let vm = this;
|
|
if (vm[tabIndexToRoute(vm.tab)].isnew) {
|
|
vm.getDataFromApi();
|
|
}
|
|
},
|
|
|
|
async getDataFromApi(breakPoint) {
|
|
let vm = this;
|
|
if (vm.formState.loading) {
|
|
return;
|
|
}
|
|
let filterDates = relativeDatefilterCalculator.tokenToDates(
|
|
vm.selectedTimePeriod
|
|
);
|
|
|
|
vm.formState.loading = true;
|
|
if (breakPoint == null) {
|
|
breakPoint = vm.$vuetify.breakpoint.name;
|
|
}
|
|
//##########################################################################################################################################
|
|
//Visually, 200 points max looks best on full screen widths and 40 on galaxy s9 minimum standard
|
|
//there is no relevant loss of fidelity with this downsampling
|
|
let max = 200;
|
|
//https://vuetifyjs.com/en/customization/breakpoints/#breakpoint-service-object
|
|
//Note: used geometric progression of 1.5 for this
|
|
//40*1.5=60, 60*1.5=90 etc etc etc
|
|
//wanted it to fit between 40 at lowest end and 200 at highest end
|
|
|
|
switch (breakPoint) {
|
|
case "xs":
|
|
max = 40;
|
|
break;
|
|
case "sm":
|
|
max = 60;
|
|
break;
|
|
case "md":
|
|
max = 90;
|
|
break;
|
|
case "lg":
|
|
max = 135;
|
|
break;
|
|
case "xl":
|
|
max = 200;
|
|
break;
|
|
default:
|
|
max = 200;
|
|
}
|
|
|
|
let url =
|
|
"server-metric/" +
|
|
tabIndexToRoute(vm.tab) +
|
|
"?maxRecords=" +
|
|
max +
|
|
"&tsStart=" +
|
|
filterDates.after +
|
|
"&tsEnd=" +
|
|
filterDates.before;
|
|
|
|
window.$gz.form.deleteAllErrorBoxErrors(vm);
|
|
try {
|
|
let res = await window.$gz.api.get(url);
|
|
|
|
if (res.error) {
|
|
if (res.error.code == "2010") {
|
|
window.$gz.form.handleObjectNotFound(vm);
|
|
}
|
|
vm.formState.serverError = res.error;
|
|
window.$gz.form.setErrorBoxErrors(vm);
|
|
} else {
|
|
vm[tabIndexToRoute(vm.tab)] = res.data;
|
|
vm.lastFetchBreakPoint = breakPoint;
|
|
window.$gz.form.setFormState({
|
|
vm: vm,
|
|
dirty: false,
|
|
valid: true,
|
|
loading: false
|
|
});
|
|
|
|
vm.formState.ready = true;
|
|
}
|
|
} catch (error) {
|
|
window.$gz.form.setFormState({
|
|
vm: vm,
|
|
loading: false
|
|
});
|
|
window.$gz.errorHandler.handleFormError(error, vm);
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
cpuChartData() {
|
|
return {
|
|
datasets: [
|
|
{
|
|
label: "CPU %",
|
|
borderColor: Palette.color.soft_sand,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.memcpu.cpu
|
|
}
|
|
]
|
|
};
|
|
},
|
|
dbChartData() {
|
|
return {
|
|
datasets: [
|
|
{
|
|
label: this.$ay.t("MetricDBSize"),
|
|
borderColor: Palette.color.blue,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.db.totalSize
|
|
}
|
|
]
|
|
};
|
|
},
|
|
dbTopTablesChartData() {
|
|
// debugger;
|
|
if (!this.db.topTables) {
|
|
return { labels: [], datasets: [] };
|
|
}
|
|
return {
|
|
// These labels appear in the legend and in the tooltips when hovering different arcs
|
|
//_.map(users, 'user');
|
|
//de-lodash
|
|
// labels: window.$gz. _.map(this.db.topTables, "name"),
|
|
labels: this.db.topTables.map(z => z.name),
|
|
datasets: [
|
|
{
|
|
label: this.$ay.t("MetricTopTablesSize"),
|
|
//de-lodash
|
|
// data: window.$gz. _.map(this.db.topTables, "value"),
|
|
data: this.db.topTables.map(z => z.value),
|
|
backgroundColor: Palette.getSoftPaletteArray(
|
|
this.db.topTables ? this.db.topTables.length : 3
|
|
),
|
|
minBarLength: 5
|
|
}
|
|
]
|
|
};
|
|
},
|
|
memAllChartData() {
|
|
return {
|
|
datasets: [
|
|
{
|
|
label: this.$ay.t("MetricAllocatedMemory"),
|
|
borderColor: Palette.color.soft_brown_darker,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.memcpu.allocated
|
|
},
|
|
{
|
|
label: this.$ay.t("MetricWorkingSet"),
|
|
borderColor: Palette.color.soft_green,
|
|
//borderWidth:4,
|
|
// pointStyle: "rectRot",
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
// borderDash: [20, 3, 3, 3, 3, 3, 3, 3],
|
|
fill: false,
|
|
data: this.memcpu.workingSet
|
|
},
|
|
{
|
|
label: this.$ay.t("MetricPrivateBytes"),
|
|
borderColor: Palette.color.soft_deep_blue,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.memcpu.privateBytes
|
|
}
|
|
]
|
|
};
|
|
},
|
|
fileSizeChartData() {
|
|
return {
|
|
datasets: [
|
|
{
|
|
label: this.$ay.t("MetricAttachmentsMB"),
|
|
borderColor: Palette.color.purple,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.storage.attachmentFileSize
|
|
},
|
|
{
|
|
label: this.$ay.t("MetricBackupMB"),
|
|
borderColor: Palette.color.orange,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.storage.utilityFileSize
|
|
},
|
|
{
|
|
label: this.$ay.t("MetricAvailableDiskSpace"),
|
|
borderColor: Palette.color.green,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.storage.attachmentFilesAvailableSpace
|
|
}
|
|
]
|
|
};
|
|
},
|
|
attachmentCountChartData() {
|
|
return {
|
|
datasets: [
|
|
{
|
|
label: this.$ay.t("MetricAttachmentsCount"),
|
|
borderColor: Palette.color.blue,
|
|
fill: false,
|
|
radius: 0,
|
|
hoverRadius: 10,
|
|
hitRadius: 4,
|
|
data: this.storage.attachmentFileCount
|
|
}
|
|
]
|
|
};
|
|
}
|
|
}
|
|
};
|
|
|
|
//////////////////////
|
|
//
|
|
//
|
|
function tabIndexToRoute(tabIndex) {
|
|
switch (tabIndex) {
|
|
case 0:
|
|
return "memcpu";
|
|
|
|
case 1:
|
|
return "db";
|
|
|
|
case 2:
|
|
return "storage";
|
|
}
|
|
}
|
|
//////////////////////
|
|
//
|
|
//
|
|
function generateMenu(vm) {
|
|
let menuOptions = {
|
|
isMain: true,
|
|
icon: "$ayiFileMedicalAlt",
|
|
title: "ServerMetrics",
|
|
helpUrl: "ops-metrics",
|
|
formData: {
|
|
ayaType: window.$gz.type.ServerMetrics
|
|
},
|
|
menuItems: [
|
|
// {
|
|
// title: "DEV_TEST_COLLECT",
|
|
// icon: "fa - bolt",
|
|
// surface: true,
|
|
// key: FORM_KEY + ":collect",
|
|
// vm: vm
|
|
// }
|
|
]
|
|
};
|
|
|
|
window.$gz.eventBus.$emit("menu-change", menuOptions);
|
|
}
|
|
|
|
/////////////////////////////
|
|
//
|
|
//
|
|
function clickHandler(menuItem) {
|
|
if (!menuItem) {
|
|
return;
|
|
}
|
|
let m = window.$gz.menu.parseMenuItem(menuItem);
|
|
if (m.owner == FORM_KEY && !m.disabled) {
|
|
switch (m.key) {
|
|
// case "collect":
|
|
// //trigger garbage collection
|
|
// window.$gz.api.get("server-metric/collect");
|
|
// break;
|
|
default:
|
|
window.$gz.eventBus.$emit(
|
|
"notify-warning",
|
|
FORM_KEY + "::context click: [" + m.key + "]"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////
|
|
//
|
|
//
|
|
async function initForm(vm) {
|
|
await fetchTranslatedText(vm);
|
|
await populateSelectionLists(vm);
|
|
}
|
|
|
|
/////////////////////////////////
|
|
//
|
|
//
|
|
function populateSelectionLists(vm) {
|
|
vm.selectLists.dateFilterTokens.push(
|
|
...[
|
|
{ name: vm.$ay.t("DateRangePast6Hours"), id: "*past6hours*" },
|
|
{ name: vm.$ay.t("DateRangePast24Hours"), id: "*past24hours*" },
|
|
{ name: vm.$ay.t("DateRangePast7Days"), id: "*past7days*" },
|
|
{ name: vm.$ay.t("DateRangePast30Days"), id: "*past30days*" },
|
|
{
|
|
name: vm.$ay.t("DateRangeInTheLastSixMonths"),
|
|
id: "*last6months*"
|
|
},
|
|
{ name: vm.$ay.t("DateRangePastYear"), id: "*pastyear*" }
|
|
]
|
|
);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////
|
|
//
|
|
// Ensures UI translated text is available
|
|
//
|
|
async function fetchTranslatedText(vm) {
|
|
await window.$gz.translation.cacheTranslations([
|
|
"DateRangePast6Hours",
|
|
"DateRangePast24Hours",
|
|
"DateRangePast7Days",
|
|
"DateRangePast30Days",
|
|
"DateRangeInTheLastSixMonths",
|
|
"DateRangePastYear",
|
|
"MetricFileStorage",
|
|
"MetricAttachmentsMB",
|
|
"MetricBackupMB",
|
|
"MetricAvailableDiskSpace",
|
|
"MetricAttachmentsCount",
|
|
"Database",
|
|
"MetricDBSize",
|
|
"MetricTopTablesSize",
|
|
"MetricCPUMemory",
|
|
"MetricAllocatedMemory",
|
|
"MetricWorkingSet",
|
|
"MetricPrivateBytes"
|
|
]);
|
|
}
|
|
</script>
|