cloudstack/ui/src/components/view/StatsTab.vue

719 lines
32 KiB
Vue

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<div class="container">
<a-modal
v-model:visible="showFilterStatsModal"
:title="$t('label.select.period')"
:maskClosable="false"
:footer="null">
<filter-stats
:startDateProp="startDate"
:endDateProp="endDate"
@closeAction="closeAction"
@onSubmit="handleSubmit"/>
</a-modal>
<a-modal
v-model:visible="showResourceInfoModal"
:title="resourceInfoModalTitle"
:footer="null">
<resource-stats-info :resourceType="resourceTypeToShowInfo" :key="resourceTypeToShowInfo"/>
</a-modal>
<a-row class="chart-row">
<a-col>
<span class="ant-tag">
<a-button @click="openFilter()">
<FilterOutlined/>
</a-button>
<span v-html="formatedPeriod"></span>
</span>
<InfoCircleOutlined class="info-icon" :title="$t('label.see.more.info.shown.charts')" @click="onClickShowResourceInfoModal('CHART')"/>
</a-col>
</a-row>
<div v-if="loaded">
<div v-if="chartLabels.length > 0">
<a-row class="chart-row">
<a-col>
<strong>CPU</strong>
<InfoCircleOutlined class="info-icon" :title="$t('label.see.more.info.cpu.usage')" @click="onClickShowResourceInfoModal('CPU')"/>
<line-chart
:chartData="prepareData(resourceUsageHistory.cpu)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.cpu, 100, 10), '%')"
:width="1024"
:height="250"
/>
</a-col>
</a-row>
<a-row class="chart-row">
<a-col>
<strong>{{ $t('label.memory') }}</strong>
<InfoCircleOutlined class="info-icon" :title="$t('label.see.more.info.memory.usage')" @click="onClickShowResourceInfoModal('MEM')"/>
<a-select class="chart-type-select" v-model:value="selectedMemoryChartType">
<a-select-option v-for="(type, typeIndex) in memoryChartTypes" :key="typeIndex">
{{ type }}
</a-select-option>
</a-select>
<a-select v-model:value="selectedMemoryUsageType">
<a-select-option v-for="(type, typeIndex) in memoryUsageTypes" :key="typeIndex">
{{ type }}
</a-select-option>
</a-select>
<a-select v-model:value="selectedMemoryUnitOfMeasurement" v-if="selectedMemoryChartType === 0">
<a-select-option v-for="unit in memoryUnitsOfMeasurement" :key="unit">
{{ unit }}
</a-select-option>
</a-select>
<line-chart
v-if="selectedMemoryChartType === 0 && selectedMemoryUsageType === 0 && selectedMemoryUnitOfMeasurement === 'MB'"
:chartData="prepareData(resourceUsageHistory.memory.rawData.used.inMB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.memory.rawData.used.inMB, 10, 100), ' MB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedMemoryChartType === 0 && selectedMemoryUsageType === 0 && selectedMemoryUnitOfMeasurement === 'GB'"
:chartData="prepareData(resourceUsageHistory.memory.rawData.used.inGB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.memory.rawData.used.inGB, 1, 1), ' GB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedMemoryChartType === 0 && selectedMemoryUsageType === 1 && selectedMemoryUnitOfMeasurement === 'MB'"
:chartData="prepareData(resourceUsageHistory.memory.rawData.free.inMB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.memory.rawData.free.inMB, 10, 100), ' MB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedMemoryChartType === 0 && selectedMemoryUsageType === 1 && selectedMemoryUnitOfMeasurement === 'GB'"
:chartData="prepareData(resourceUsageHistory.memory.rawData.free.inGB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.memory.rawData.free.inGB, 1, 1), ' GB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedMemoryChartType === 1 && selectedMemoryUsageType === 0"
:chartData="prepareData(resourceUsageHistory.memory.percentage.used)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.memory.percentage.used, 100, 10), '%')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedMemoryChartType === 1 && selectedMemoryUsageType === 1"
:chartData="prepareData(resourceUsageHistory.memory.percentage.free)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.memory.percentage.free, 100, 10), '%')"
:width="1024"
:height="250"
/>
</a-col>
</a-row>
<a-row class="chart-row">
<a-col>
<strong>{{ $t('label.network') }}</strong>
<InfoCircleOutlined class="info-icon" :title="$t('label.see.more.info.network.usage')" @click="onClickShowResourceInfoModal('NET')"/>
<a-select v-model:value="selectedNetworkUnitOfMeasurement">
<a-select-option v-for="unit in networkUnitsOfMeasurement" :key="unit">
{{ unit }}
</a-select-option>
</a-select>
<line-chart
v-if="selectedNetworkUnitOfMeasurement === 'KiB'"
:chartData="prepareData(resourceUsageHistory.network.inKiB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.network.inKiB, 100, 100), ' KiB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedNetworkUnitOfMeasurement === 'MiB'"
:chartData="prepareData(resourceUsageHistory.network.inMiB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.network.inMiB, 100, 100), ' MiB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedNetworkUnitOfMeasurement === 'GiB'"
:chartData="prepareData(resourceUsageHistory.network.inGiB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.network.inGiB, 1, 1), ' GiB')"
:width="1024"
:height="250"
/>
</a-col>
</a-row>
<a-row class="chart-row">
<a-col>
<strong>{{ $t('label.disk') }}</strong>
<InfoCircleOutlined class="info-icon" :title="$t('label.see.more.info.disk.usage')" @click="onClickShowResourceInfoModal('DISK')"/>
<a-select class="chart-type-select" v-model:value="selectedDiskChartType">
<a-select-option v-for="(type, typeIndex) in diskChartTypes" :key="typeIndex">
{{ type }}
</a-select-option>
</a-select>
<a-select
v-if="selectedDiskChartType === 1"
v-model:value="selectedDiskUnitOfMeasurement">
<a-select-option v-for="unit in diskUnitsOfMeasurement" :key="unit">
{{ unit }}
</a-select-option>
</a-select>
<line-chart
v-if="selectedDiskChartType === 0"
:chartData="prepareData(resourceUsageHistory.disk.iops)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.disk.iops, 100, 100), ' IOPS')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedDiskChartType === 1 && selectedDiskUnitOfMeasurement === 'KiB'"
:chartData="prepareData(resourceUsageHistory.disk.readAndWrite.inKiB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.disk.readAndWrite.inKiB, 100, 100), ' KiB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedDiskChartType === 1 && selectedDiskUnitOfMeasurement === 'MiB'"
:chartData="prepareData(resourceUsageHistory.disk.readAndWrite.inMiB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.disk.readAndWrite.inMiB, 10, 10), ' MiB')"
:width="1024"
:height="250"
/>
<line-chart
v-if="selectedDiskChartType === 1 && selectedDiskUnitOfMeasurement === 'GiB'"
:chartData="prepareData(resourceUsageHistory.disk.readAndWrite.inGiB)"
:chartOptions="getChartOptions(calculateMaxYAxisAndStepSize(resourceUsageHistory.disk.readAndWrite.inGiB, 1, 1), ' GiB')"
:width="1024"
:height="250"
/>
</a-col>
</a-row>
</div>
<div v-else>
<a-alert :message="$t('message.no.data.to.show.for.period')" banner />
</div>
</div>
<a-spin v-else></a-spin>
</div>
</template>
<script>
import { api } from '@/api'
import moment from 'moment'
import 'chartjs-adapter-moment'
import FilterStats from './stats/FilterStats'
import ResourceStatsInfo from './stats/ResourceStatsInfo'
import LineChart from './chart/LineChart'
export default {
props: {
resource: {
type: Object,
required: true
}
},
components: {
FilterStats,
ResourceStatsInfo,
LineChart
},
data () {
return {
resourceTypeToShowInfo: null,
showResourceInfoModal: false,
resourceInfoModalTitle: null,
loaded: false,
showCpuInfo: false,
showFilterStatsModal: false,
endDate: this.getEndDate(),
startDate: this.getStartDate(),
formatedPeriod: null,
selectedMemoryChartType: 0,
selectedMemoryUsageType: 0,
memoryChartTypes: [this.$t('label.raw.data'), this.$t('label.percentage')],
memoryUsageTypes: [this.$t('label.used'), this.$t('label.free')],
selectedMemoryUnitOfMeasurement: 'GB',
memoryUnitsOfMeasurement: ['MB', 'GB'],
selectedNetworkUnitOfMeasurement: 'MiB',
networkUnitsOfMeasurement: ['KiB', 'MiB', 'GiB'],
selectedDiskChartType: 0,
diskChartTypes: ['IOPS', this.$t('label.read.and.write')],
selectedDiskUnitOfMeasurement: 'KiB',
diskUnitsOfMeasurement: ['KiB', 'MiB', 'GiB'],
chartLabels: [],
resourceUsageHistory: {
cpu: [],
memory: {
percentage: {
free: [],
used: []
},
rawData: {
free: {
inMB: [],
inGB: []
},
used: {
inMB: [],
inGB: []
}
}
},
network: {
inKiB: [],
inMiB: [],
inGiB: []
},
disk: {
iops: [],
readAndWrite: {
inKiB: [],
inMiB: [],
inGiB: []
}
}
}
}
},
mounted () {
this.fetchData()
},
computed: {
usebrowsertimezone: function () {
return this.$store.getters.usebrowsertimezone
}
},
watch: {
resource: function (newItem) {
if (!newItem || !newItem.id) {
return
}
this.fetchData()
},
usebrowsertimezone: function () {
if (this.startDate) {
this.startDate = this.onToggleUseBrowserTimezone(new Date(this.startDate))
}
if (this.endDate) {
this.endDate = this.onToggleUseBrowserTimezone(new Date(this.endDate))
}
this.fetchData()
}
},
methods: {
openFilter () {
this.showFilterStatsModal = true
},
onClickShowResourceInfoModal (resource) {
switch (resource) {
case 'CHART':
this.resourceInfoModalTitle = this.$t('label.chart.info')
break
case 'CPU':
this.resourceInfoModalTitle = this.$t('label.cpu.usage.info')
break
case 'MEM':
this.resourceInfoModalTitle = this.$t('label.memory.usage.info')
break
case 'NET':
this.resourceInfoModalTitle = this.$t('label.network.usage.info')
break
case 'DISK':
this.resourceInfoModalTitle = this.$t('label.disk.usage.info')
break
}
this.resourceTypeToShowInfo = resource
this.showResourceInfoModal = true
},
handleSubmit (values) {
if (values.startDate) {
this.startDate = new Date(values.startDate)
} else {
this.startDate = null
}
if (values.endDate) {
this.endDate = new Date(values.endDate)
} else {
this.endDate = null
}
this.showFilterStatsModal = false
this.fetchData()
},
closeAction () {
this.showFilterStatsModal = false
},
getStartDate () {
var now = new Date()
if (!this.$store.getters.usebrowsertimezone) {
var dateInUTC = new Date(now.getTime() + now.getTimezoneOffset() * 60000)
return dateInUTC.setHours(dateInUTC.getHours() - 1)
}
now.setHours(now.getHours() - 1)
return now
},
getEndDate () {
var now = new Date()
if (this.$store.getters.usebrowsertimezone) {
return now
}
return new Date(now.getTime() + now.getTimezoneOffset() * 60000)
},
onToggleUseBrowserTimezone (date) {
if (this.$store.getters.usebrowsertimezone) {
return this.$toLocalDate(date)
}
return new Date(date.getTime() + date.getTimezoneOffset() * 60000)
},
convertAndFormatDateAppropriately (date) {
if (this.$store.getters.usebrowsertimezone) {
var dateInUTC = new Date(date).toISOString().split('T')
return dateInUTC[0] + ' ' + dateInUTC[1].split('-')[0].split('.')[0]
}
return moment(date).format('YYYY-MM-DD HH:mm:ss')
},
fetchData () {
this.loaded = false
this.showResourceInfoModal = false
this.formatPeriod()
var params = { id: this.resource.id }
if (this.startDate) {
params.startDate = this.convertAndFormatDateAppropriately(this.startDate)
}
if (this.endDate) {
params.endDate = this.convertAndFormatDateAppropriately(this.endDate)
}
api('listVirtualMachinesUsageHistory', params).then(response => {
this.handleStatsResponse(response)
}).catch(error => {
this.$notifyError(error)
})
},
formatPeriod () {
var formatedStartDate = null
var formatedEndDate = null
if (this.startDate) {
formatedStartDate = moment(this.startDate).format('MMM DD, YYYY') + ' at ' + moment(this.startDate).format('HH:mm:ss')
}
if (this.endDate) {
formatedEndDate = moment(this.endDate).format('MMM DD, YYYY') + ' at ' + moment(this.endDate).format('HH:mm:ss')
}
if (formatedStartDate && formatedEndDate) {
this.formatedPeriod = ' ' + this.$t('label.vm.stats.filter.period', { startDate: formatedStartDate, endDate: formatedEndDate })
} else if (formatedStartDate && !formatedEndDate) {
this.formatedPeriod = ' ' + this.$t('label.vm.stats.filter.starting', { startDate: formatedStartDate })
} else if (!formatedStartDate && formatedEndDate) {
this.formatedPeriod = ' ' + this.$t('label.vm.stats.filter.up.to', { endDate: formatedEndDate })
} else {
this.formatedPeriod = ' <b>' + this.$t('label.all.available.data') + '</b>'
}
},
handleStatsResponse (responseData) {
this.resetData()
const vm = responseData.listvirtualmachinesusagehistoryresponse.virtualmachine
const chartPointRadius = this.getChartPointRadius(vm[0].stats.length)
const blue = '#166ab7'
const green = '#389357'
const blueInRgba = 'rgba(24, 144, 255, 0.5)'
const greenInRgba = 'rgba(59, 198, 133, 0.65)'
const red = '#ff4d4f'
const redInRgba = 'rgb(255, 77, 79, 0.65)'
const cpuLine = { label: 'CPU', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const memFreeLinePercent = { label: this.$t('label.memory.free'), backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const memUsedLinePercent = { label: this.$t('label.memory.used'), backgroundColor: redInRgba, borderColor: red, data: [], pointRadius: chartPointRadius }
const memAllocatedLineInMB = { label: this.$t('label.memoryallocated'), backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const memFreeLineInMB = { label: this.$t('label.memory.free'), backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const memUsedLineInMB = { label: this.$t('label.memory.used'), backgroundColor: redInRgba, borderColor: red, data: [], pointRadius: chartPointRadius }
const memAllocatedLineInGB = { label: this.$t('label.memoryallocated'), backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const memFreeLineInGB = { label: this.$t('label.memory.free'), backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const memUsedLineInGB = { label: this.$t('label.memory.used'), backgroundColor: redInRgba, borderColor: red, data: [], pointRadius: chartPointRadius }
const netDownloadLineInKiB = { label: 'Download', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const netUploadLineInKiB = { label: 'Upload', backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const netDownloadLineInMiB = { label: 'Download', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const netUploadLineInMiB = { label: 'Upload', backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const netDownloadLineInGiB = { label: 'Download', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const netUploadLineInGiB = { label: 'Upload', backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const diskReadLineInKiB = { label: 'Read', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const diskWriteLineInKiB = { label: 'Write', backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const diskReadLineInMiB = { label: 'Read', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const diskWriteLineInMiB = { label: 'Write', backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const diskReadLineInGiB = { label: 'Read', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
const diskWriteLineInGiB = { label: 'Write', backgroundColor: greenInRgba, borderColor: green, data: [], pointRadius: chartPointRadius }
const diskIopsLine = { label: 'IOPS', backgroundColor: blueInRgba, borderColor: blue, data: [], pointRadius: chartPointRadius }
for (const element of vm[0].stats) {
var ts = this.$toLocalDate(element.timestamp)
const currentLabel = ts.split('T')[0] + ' ' + ts.split('T')[1].split('-')[0]
this.chartLabels.push(currentLabel)
cpuLine.data.push({ timestamp: currentLabel, stat: element.cpuused.split('%')[0] })
element.memoryusedkbs = element.memorykbs - element.memoryintfreekbs
memFreeLinePercent.data.push({ timestamp: currentLabel, stat: this.calculateMemoryPercentage(false, element.memorykbs, element.memoryintfreekbs) })
memUsedLinePercent.data.push({ timestamp: currentLabel, stat: this.calculateMemoryPercentage(true, element.memorykbs, element.memoryintfreekbs) })
memAllocatedLineInMB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.memorykbs, 1) })
memFreeLineInMB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.memoryintfreekbs, 1) })
memUsedLineInMB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.memoryusedkbs, 1) })
memAllocatedLineInGB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.memorykbs, 2) })
memFreeLineInGB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.memoryintfreekbs, 2) })
memUsedLineInGB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.memoryusedkbs, 2) })
netDownloadLineInKiB.data.push({ timestamp: currentLabel, stat: element.networkkbsread })
netUploadLineInKiB.data.push({ timestamp: currentLabel, stat: element.networkkbswrite })
netDownloadLineInMiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.networkkbsread, 1) })
netUploadLineInMiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.networkkbswrite, 1) })
netDownloadLineInGiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.networkkbsread, 2) })
netUploadLineInGiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.networkkbswrite, 2) })
diskReadLineInKiB.data.push({ timestamp: currentLabel, stat: element.diskkbsread })
diskWriteLineInKiB.data.push({ timestamp: currentLabel, stat: element.diskkbswrite })
diskReadLineInMiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.diskkbsread, 1) })
diskWriteLineInMiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.diskkbswrite, 1) })
diskReadLineInGiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.diskkbsread, 2) })
diskWriteLineInGiB.data.push({ timestamp: currentLabel, stat: this.convertByteBasedUnitOfMeasure(element.diskkbswrite, 2) })
diskIopsLine.data.push({ timestamp: currentLabel, stat: element.diskiopstotal })
}
this.resourceUsageHistory.cpu.push(cpuLine)
this.resourceUsageHistory.memory.percentage.free.push(memFreeLinePercent)
this.resourceUsageHistory.memory.percentage.used.push(memUsedLinePercent)
this.resourceUsageHistory.memory.rawData.free.inMB.push(memFreeLineInMB)
this.resourceUsageHistory.memory.rawData.free.inMB.push(memAllocatedLineInMB)
this.resourceUsageHistory.memory.rawData.used.inMB.push(memUsedLineInMB)
this.resourceUsageHistory.memory.rawData.used.inMB.push(memAllocatedLineInMB)
this.resourceUsageHistory.memory.rawData.free.inGB.push(memFreeLineInGB)
this.resourceUsageHistory.memory.rawData.free.inGB.push(memAllocatedLineInGB)
this.resourceUsageHistory.memory.rawData.used.inGB.push(memUsedLineInGB)
this.resourceUsageHistory.memory.rawData.used.inGB.push(memAllocatedLineInGB)
this.resourceUsageHistory.network.inKiB.push(netDownloadLineInKiB)
this.resourceUsageHistory.network.inKiB.push(netUploadLineInKiB)
this.resourceUsageHistory.network.inMiB.push(netDownloadLineInMiB)
this.resourceUsageHistory.network.inMiB.push(netUploadLineInMiB)
this.resourceUsageHistory.network.inGiB.push(netDownloadLineInGiB)
this.resourceUsageHistory.network.inGiB.push(netUploadLineInGiB)
this.resourceUsageHistory.disk.readAndWrite.inKiB.push(diskReadLineInKiB)
this.resourceUsageHistory.disk.readAndWrite.inKiB.push(diskWriteLineInKiB)
this.resourceUsageHistory.disk.readAndWrite.inMiB.push(diskReadLineInMiB)
this.resourceUsageHistory.disk.readAndWrite.inMiB.push(diskWriteLineInMiB)
this.resourceUsageHistory.disk.readAndWrite.inGiB.push(diskReadLineInGiB)
this.resourceUsageHistory.disk.readAndWrite.inGiB.push(diskWriteLineInGiB)
this.resourceUsageHistory.disk.iops.push(diskIopsLine)
this.loaded = true
},
/**
* Calculates the ideal chart points radius based on the number of data points and the screen width.
* @param numberOfDataPoints the number of data points.
* @returns the ideal chart points radius (which is the size of the points on the chart).
*/
getChartPointRadius (numberOfDataPoints) {
const maxSizeLimit = 3
const minSizeLimit = 2
const minSize = 0.1 // the smallest value that allows to render the point in the chart
const result = (screen.width * 0.04) / numberOfDataPoints
if (result > maxSizeLimit) {
return maxSizeLimit
} else if (result < minSizeLimit) {
return minSize
}
return parseFloat(result).toFixed(2)
},
/**
* Converts a value (Byte-based) from an unit to other one. For example: from Byte to KiB; from GiB to MiB; etc.
* To use it consider the following sequence: Byte -> KiB -> MiB -> GiB ...
* So, from Byte to MiB there are 2 steps, while from MiB to Byte there are -2 steps.
* @param value the value to be converted.
* @param step the number of steps between Byte-based units of measure.
* @returns the converted value.
*/
convertByteBasedUnitOfMeasure (value, step) {
if (value === 0) {
return 0.00
}
if (step === 0) {
return value
}
if (step > 0) {
return parseFloat(value / (Math.pow(1024, step))).toFixed(2)
}
return parseFloat(value * (Math.pow(1024, Math.abs(step)))).toFixed(2)
},
resetData () {
this.chartLabels = []
this.resourceUsageHistory.cpu = []
this.resourceUsageHistory.memory.percentage.free = []
this.resourceUsageHistory.memory.percentage.used = []
this.resourceUsageHistory.memory.rawData.free.inMB = []
this.resourceUsageHistory.memory.rawData.free.inGB = []
this.resourceUsageHistory.memory.rawData.used.inMB = []
this.resourceUsageHistory.memory.rawData.used.inGB = []
this.resourceUsageHistory.network.inKiB = []
this.resourceUsageHistory.network.inMiB = []
this.resourceUsageHistory.network.inGiB = []
this.resourceUsageHistory.disk.iops = []
this.resourceUsageHistory.disk.readAndWrite.inKiB = []
this.resourceUsageHistory.disk.readAndWrite.inMiB = []
this.resourceUsageHistory.disk.readAndWrite.inGiB = []
},
/**
* Calculates the memory percentage.
* @param isUsed "true" if the memory used percentage should be returned, "false" if the free memory percentage should be returned.
* @param memoryTotalInKB the memory total (in KB).
* @param memoryFreeInKB the memory free (in KB).
* @returns the percentage of used/free memory.
*/
calculateMemoryPercentage (isUsed, memoryTotalInKB, memoryFreeInKB) {
if (memoryTotalInKB == null || memoryFreeInKB == null) {
return -1
}
if (isUsed) {
return parseFloat(100.0 * (memoryTotalInKB - memoryFreeInKB) / memoryTotalInKB).toFixed(2)
}
return parseFloat(100.0 * memoryFreeInKB / memoryTotalInKB).toFixed(2)
},
/**
* Calculates the maximum Y axis and the step size based on the chart data.
* @param chartLines the chart lines with their respective data.
* @param initialMaxValue the initial maximum value to the Y axis.
* @param incrementValue the increment value.
* @returns an object containing the maximum Y axis and the step size for the chart.
*/
calculateMaxYAxisAndStepSize (chartLines, initialMaxYAxis, incrementValue) {
const numberOfLabelsOnYaxis = 4
var highestValue = 0
var maxYAxis = initialMaxYAxis
for (const line of chartLines) {
for (const d of line.data) {
const currentValue = parseFloat(d.stat)
if (currentValue > highestValue) {
highestValue = currentValue
while (highestValue > maxYAxis) {
maxYAxis += incrementValue
}
}
}
}
return { maxYAxes: maxYAxis, stepSize: maxYAxis / numberOfLabelsOnYaxis }
},
/**
* Returns the chart options.
* @param yAxesStepSize the step size for the Y axes.
* @param yAxesUnitOfMeasurement the unit of measurement label used on the Y axes.
* @returns the chart options.
*/
getChartOptions (yAxesOptions, yAxesUnitOfMeasurement) {
var chartOptions = {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxis: {
min: 0,
max: yAxesOptions.maxYAxes,
reverse: false,
ticks: {
stepSize: yAxesOptions.stepSize,
callback: function (label) {
return label + yAxesUnitOfMeasurement
}
}
},
xAxis: {
type: 'time',
autoSkip: false,
time: {
parser: 'YYYY-MM-DD HH:mm:ss',
unit: 'second',
displayFormats: {
second: 'HH:mm:ss'
}
}
}
}
}
const dateTimes = this.convertStringArrayToDateArray(JSON.parse(JSON.stringify(this.chartLabels)))
const averageDifference = this.averageDifferenceBetweenTimes(dateTimes)
chartOptions.scales.xAxis.time.stepSize = this.calculateStepSize(this.chartLabels.length, averageDifference)
return chartOptions
},
convertStringArrayToDateArray (stringArray) {
const dateArray = []
for (const element of stringArray) {
dateArray.push(new Date(element.replace(' ', 'T')))
}
return dateArray
},
averageDifferenceBetweenTimes (timeList) {
const oneSecond = 1000 // 1 second represented as milliseconds
const differences = []
var previus = timeList.splice(0, 1)[0]
for (const time of timeList) {
differences.push((time - previus) / oneSecond) // push the difference in seconds
previus = time
}
if (differences.length === 0) {
return 1
}
const averageDifference = Math.trunc(differences.reduce((a, b) => a + b, 0) / differences.length)
return averageDifference
},
calculateStepSize (numberOfDataPoints, differenceBetweenTimes) {
const idealNumberOfLabels = 8
const result = numberOfDataPoints / idealNumberOfLabels
if (result > 1) {
return result * differenceBetweenTimes
}
return differenceBetweenTimes
},
prepareData (chartData) {
const datasetList = []
for (const element of chartData) {
datasetList.push(
{
backgroundColor: element.backgroundColor,
borderColor: element.borderColor,
borderWidth: 3,
label: element.label,
data: element.data.map(d => d.stat),
hidden: this.hideLine(element.data.map(d => d.stat)),
pointRadius: element.pointRadius,
fill: 'origin'
}
)
}
return {
labels: this.chartLabels,
datasets: datasetList
}
},
hideLine (data) {
for (const d of data) {
if (d < 0) {
return true
}
}
return false
}
}
}
</script>
<style lang="scss" scoped>
@import '@/style/components/view/StatsTab.scss';
</style>