| @@ -453,6 +453,30 @@ | |||||
| "unit": "ms/time", | "unit": "ms/time", | ||||
| "gpuunit": "us/time", | "gpuunit": "us/time", | ||||
| "chartTitle": "Average Time Consumption Ranking", | "chartTitle": "Average Time Consumption Ranking", | ||||
| "userUtilization": "User Usage", | |||||
| "sysUtilization": "System Usage", | |||||
| "ioUtilization": "I/O Usage", | |||||
| "idleUtilization": "Idle Usage", | |||||
| "avgUserUtilization": "Average User Usage:", | |||||
| "avgSysUtilization": "Average System Usage:", | |||||
| "avgIOUtilization": "Average I/O Usage:", | |||||
| "avgIdleUtilization": "Average Idle Usage:", | |||||
| "avgWaitingProcess": "Average Number of Waiting Threads:", | |||||
| "avgSwitchCount": "Average Number of Context Switches:", | |||||
| "logicCores": "Number of Logical CPU Cores:", | |||||
| "allOperators": "All Operators", | |||||
| "currentOperator": "Current Operator", | |||||
| "cpuStepInputTip": "Enter a positive integer ranging from 1 to {max}. The value of Start Step must be less than or equal to that of End Step.", | |||||
| "startStep": "Start Step:", | |||||
| "endStep": "End Step:", | |||||
| "filterStep": "Filter", | |||||
| "resetStep": "Reset", | |||||
| "cpuUtilization": "CPU Usage", | |||||
| "cpuStepTip": "The step value is a positive integer ranging from 1 to {max}.", | |||||
| "structuralCpuUtil": "CPU Usage of the Entire System", | |||||
| "processCpuUtil": "Process CPU Usage", | |||||
| "operatorCpuUtil": "Operator CPU Usage", | |||||
| "utilizationTitle": "Usage(%)", | |||||
| "memory": { | "memory": { | ||||
| "memoryDetailLink": "Memory Usage Information", | "memoryDetailLink": "Memory Usage Information", | ||||
| "overView": "Memory Allocation OverView", | "overView": "Memory Allocation OverView", | ||||
| @@ -452,6 +452,30 @@ | |||||
| "unit": "ms/次", | "unit": "ms/次", | ||||
| "gpuunit": "us/次", | "gpuunit": "us/次", | ||||
| "chartTitle": "平均耗时排名", | "chartTitle": "平均耗时排名", | ||||
| "userUtilization": "用户利用率", | |||||
| "sysUtilization": "系统利用率", | |||||
| "ioUtilization": "IO利用率", | |||||
| "idleUtilization": "空闲利用率", | |||||
| "avgUserUtilization": "平均用户利用率:", | |||||
| "avgSysUtilization": "平均系统利用率:", | |||||
| "avgIOUtilization": "平均IO利用率:", | |||||
| "avgIdleUtilization": "平均空闲利用率:", | |||||
| "avgWaitingProcess": "平均等待线程数:", | |||||
| "avgSwitchCount": "平均上下文切换次数:", | |||||
| "logicCores": "CPU逻辑核数:", | |||||
| "allOperators": "所有算子", | |||||
| "currentOperator": "当前算子", | |||||
| "cpuStepInputTip": "请输入step范围 (1~{max}的正整数,且起始step小于等于结束step)", | |||||
| "startStep": "起始step:", | |||||
| "endStep": "结束step:", | |||||
| "filterStep": "筛选", | |||||
| "resetStep": "重置", | |||||
| "cpuUtilization": "CPU利用率", | |||||
| "cpuStepTip": "Step的范围为1~{max}的正整数", | |||||
| "structuralCpuUtil": "整机CPU利用率", | |||||
| "processCpuUtil": "进程CPU利用率", | |||||
| "operatorCpuUtil": "算子CPU利用率", | |||||
| "utilizationTitle": "利用率(%)", | |||||
| "memory": { | "memory": { | ||||
| "memoryDetailLink": "内存使用情况", | "memoryDetailLink": "内存使用情况", | ||||
| "overView": "内存分配概览", | "overView": "内存分配概览", | ||||
| @@ -0,0 +1,654 @@ | |||||
| <!-- | |||||
| Copyright 2021 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Licensed 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. | |||||
| --> | |||||
| <script> | |||||
| import echarts from 'echarts'; | |||||
| import {select, selectAll} from 'd3'; | |||||
| const d3 = {select, selectAll}; | |||||
| import 'd3-graphviz'; | |||||
| import RequestService from '@/services/request-service'; | |||||
| import initDot from '../mixins/init-dot'; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| chartGrid: { | |||||
| grid: { | |||||
| left: 40, | |||||
| top: 40, | |||||
| right: 70, | |||||
| bottom: 60, | |||||
| }, | |||||
| }, // The grid setting of chart | |||||
| chartDataZoom: { | |||||
| dataZoom: [ | |||||
| { | |||||
| start: 0, | |||||
| end: 100, | |||||
| bottom: 0, | |||||
| }, | |||||
| { | |||||
| start: 0, | |||||
| end: 100, | |||||
| type: 'inside', | |||||
| bottom: 0, | |||||
| }, | |||||
| ], | |||||
| }, // The data zoom setting of chart | |||||
| deviceCpuChart: { | |||||
| id: 'deviceCpuChart', | |||||
| chartDom: null, | |||||
| option: { | |||||
| tooltip: { | |||||
| trigger: 'axis', | |||||
| formatter: null, | |||||
| confine: true, | |||||
| }, | |||||
| legend: { | |||||
| right: 70, | |||||
| top: 8, | |||||
| data: [], | |||||
| }, | |||||
| xAxis: { | |||||
| name: '', | |||||
| data: [], | |||||
| }, | |||||
| yAxis: { | |||||
| name: this.$t('profiling.utilizationTitle'), | |||||
| type: 'value', | |||||
| }, | |||||
| series: [], | |||||
| }, | |||||
| logicCores: 0, | |||||
| cpuAvgUser: 0, | |||||
| cpuAvgSystem: 0, | |||||
| cpuAvgIO: 0, | |||||
| cpuAvgFree: 0, | |||||
| cpuAvgProcess: 0, | |||||
| cpuAvgSwitch: 0, | |||||
| }, // The total data of device cpu info | |||||
| processCpuChart: { | |||||
| id: 'processCpuChart', | |||||
| chartDom: null, | |||||
| option: { | |||||
| tooltip: { | |||||
| trigger: 'axis', | |||||
| formatter: null, | |||||
| confine: true, | |||||
| }, | |||||
| legend: { | |||||
| right: 70, | |||||
| top: 8, | |||||
| data: [], | |||||
| }, | |||||
| xAxis: { | |||||
| name: '', | |||||
| data: [], | |||||
| }, | |||||
| yAxis: { | |||||
| name: this.$t('profiling.utilizationTitle'), | |||||
| type: 'value', | |||||
| }, | |||||
| series: [], | |||||
| }, | |||||
| cpuAvgUser: 0, | |||||
| cpuAvgSystem: 0, | |||||
| }, // The total data of process cpu info | |||||
| operatorCpuChart: { | |||||
| id: 'operatorCpuChart', | |||||
| chartDom: null, | |||||
| option: { | |||||
| tooltip: { | |||||
| trigger: 'axis', | |||||
| formatter: null, | |||||
| confine: true, | |||||
| }, | |||||
| legend: { | |||||
| right: 70, | |||||
| top: 8, | |||||
| data: [], | |||||
| }, | |||||
| xAxis: { | |||||
| name: '', | |||||
| data: [], | |||||
| }, | |||||
| yAxis: { | |||||
| name: this.$t('profiling.utilizationTitle'), | |||||
| type: 'value', | |||||
| }, | |||||
| series: [], | |||||
| }, | |||||
| opList: {}, | |||||
| cpuAvgTotalUser: 0, | |||||
| cpuAvgTotalSystem: 0, | |||||
| cpuAvgOpUser: 0, | |||||
| cpuAvgOpSystem: 0, | |||||
| processNumber: 0, | |||||
| }, // The total data of operator cpu info | |||||
| cpuInfo: { | |||||
| initOver: false, | |||||
| noData: true, | |||||
| startStep: { | |||||
| step: '', | |||||
| showStep: '', | |||||
| }, | |||||
| endStep: { | |||||
| step: '', | |||||
| showStep: '', | |||||
| }, | |||||
| stepArray: [], | |||||
| step: 0, | |||||
| deviceId: null, | |||||
| stepTip: this.$t('profiling.cpuStepTip'), | |||||
| cpuStepInputTip: '', | |||||
| cpuInfoStr: { | |||||
| user_utilization: this.$t('profiling.userUtilization'), | |||||
| sys_utilization: this.$t('profiling.sysUtilization'), | |||||
| io_utilization: this.$t('profiling.ioUtilization'), | |||||
| idle_utilization: this.$t('profiling.idleUtilization'), | |||||
| }, | |||||
| samplingInterval: 0, | |||||
| }, // The common data of page | |||||
| strokeBeforeClick: undefined, // The stroke info of original dom | |||||
| prevNode: undefined, // The previous clicked node | |||||
| prevGraph: undefined, // The previous clicked graph | |||||
| operatorCPUList: [], // The list of operator cpu info | |||||
| selIndex: null, // The index of selected graph node, to get right operator cpu info | |||||
| }; | |||||
| }, | |||||
| created() { | |||||
| Object.assign(this.deviceCpuChart.option, this.chartGrid, this.chartDataZoom); | |||||
| Object.assign(this.processCpuChart.option, this.chartGrid, this.chartDataZoom); | |||||
| Object.assign(this.operatorCpuChart.option, this.chartGrid, this.chartDataZoom); | |||||
| }, | |||||
| methods: { | |||||
| /** | |||||
| * The logic of query and render graph info of cpu | |||||
| * @return {Promise} | |||||
| */ | |||||
| initCPUGraph() { | |||||
| return new Promise((resolve) => { | |||||
| const params = { | |||||
| params: { | |||||
| train_id: this.trainId, | |||||
| profile: this.dir, | |||||
| }, | |||||
| body: { | |||||
| device_id: this.currentCard, | |||||
| }, | |||||
| }; | |||||
| RequestService.queryOpQueue(params) | |||||
| .then((res) => { | |||||
| if (res.data && res.data.object) { | |||||
| // Keep data order right | |||||
| const newData = this.ensureDataOrder(res.data.object); | |||||
| // Process data | |||||
| const graphData = this.processGraphData(newData); | |||||
| // Transform to dot | |||||
| const dot = initDot.objectToDot(graphData); | |||||
| // Render dot | |||||
| this.initOperatorGraph(dot).then(() => { | |||||
| const nodes = d3.selectAll('g.node'); | |||||
| // Add click event | |||||
| this.addGraphEvent(nodes); | |||||
| // Add cursor style | |||||
| this.updateGraphStyle(nodes); | |||||
| resolve(true); | |||||
| }); | |||||
| } | |||||
| }); | |||||
| }); | |||||
| }, | |||||
| /** | |||||
| * The logic of make sure the index of data is same to id | |||||
| * @param {Array} dataArr | |||||
| * @return {Array} | |||||
| */ | |||||
| ensureDataOrder(dataArr) { | |||||
| const newArr = []; | |||||
| dataArr.forEach((data) => { | |||||
| newArr[data[0]] = data; | |||||
| this.operatorCPUList[data[0]] = `${data[1]}_${data[0]}`; | |||||
| }); | |||||
| this.selIndex = newArr.findIndex((data) => { | |||||
| return data.parent_id === null || newArr[data.parent_id] === undefined; | |||||
| }); | |||||
| return newArr; | |||||
| }, | |||||
| /** | |||||
| * The logic of process operator data into 'initDot' format | |||||
| * @param {Array} dataArr | |||||
| * @return {Object} | |||||
| */ | |||||
| processGraphData(dataArr) { | |||||
| const graphData = { | |||||
| total: { | |||||
| compound: 'true', | |||||
| rankdir: 'LR', | |||||
| id: 'operatorGraph', | |||||
| bgcolor: 'transparent', | |||||
| }, | |||||
| node: { | |||||
| style: 'filled', | |||||
| fontsize: '10px', | |||||
| }, | |||||
| edge: { | |||||
| fontsize: '6px', | |||||
| style: 'filled', | |||||
| fillcolor: '#e6ebf5', | |||||
| color: '#e6ebf5', | |||||
| }, | |||||
| nodes: [], | |||||
| }; | |||||
| const nodeStyle = { | |||||
| shape: 'Mrecord', | |||||
| fillcolor: '#c6e2ff', | |||||
| color: '#c6e2ff', | |||||
| }; | |||||
| if (Array.isArray(dataArr)) { | |||||
| dataArr.forEach((data) => { | |||||
| const text = `${data[1]}_${data[0]}`; | |||||
| const node = Object.assign({ | |||||
| name: text, | |||||
| id: text, | |||||
| label: text, | |||||
| }, nodeStyle); | |||||
| // If has the parent node | |||||
| if (typeof data[6] === 'number') { | |||||
| const next = data[6]; | |||||
| node.next = [ | |||||
| { | |||||
| name: `${dataArr[next][1]}_${dataArr[next][0]}`, | |||||
| }, | |||||
| ]; | |||||
| } | |||||
| graphData.nodes.push(node); | |||||
| }); | |||||
| } | |||||
| return graphData; | |||||
| }, | |||||
| /** | |||||
| * Init operator graph | |||||
| * @param {String} dot | |||||
| * @return {Object} | |||||
| */ | |||||
| initOperatorGraph(dot) { | |||||
| return new Promise((resolve) => { | |||||
| d3.select('#operator-graph') | |||||
| .graphviz() | |||||
| .height('100%') | |||||
| .width('100%') | |||||
| .fit(true) | |||||
| .dot(dot) | |||||
| .render(() => { | |||||
| resolve(true); | |||||
| }); | |||||
| }); | |||||
| }, | |||||
| /** | |||||
| * Add operator graph Event | |||||
| * @param {Array} nodes | |||||
| */ | |||||
| addGraphEvent(nodes) { | |||||
| if (nodes) { | |||||
| nodes.on( | |||||
| 'click', | |||||
| (target, index, nodeslist) => { | |||||
| this.clickEvent(nodeslist[index]); | |||||
| }, | |||||
| false, | |||||
| ); | |||||
| } | |||||
| }, | |||||
| /** | |||||
| * Update operator graph style | |||||
| * @param {Array} nodes | |||||
| */ | |||||
| updateGraphStyle(nodes) { | |||||
| nodes.attr('cursor', 'pointer'); | |||||
| }, | |||||
| /** | |||||
| * The logic of operator graph click event | |||||
| * @param {Object} node | |||||
| */ | |||||
| clickEvent(node) { | |||||
| if (this.prevGraph) { | |||||
| this.prevGraph.setAttribute('stroke', this.strokeBeforeClick); | |||||
| } | |||||
| if (this.prevNode === Node) { | |||||
| return; | |||||
| } else { | |||||
| this.prevNode = node; | |||||
| } | |||||
| const children = node.children; | |||||
| for (let i = 0; i < children.length; i++) { | |||||
| if (children[i].nodeName === 'path') { | |||||
| this.prevGraph = children[i]; | |||||
| this.strokeBeforeClick = children[i].getAttribute('stroke'); | |||||
| children[i].setAttribute('stroke', '#409eff'); | |||||
| } | |||||
| } | |||||
| const strArr = node.id.split('_'); | |||||
| this.selIndex = strArr[strArr.length - 1]; | |||||
| this.updateOperatorCpuChart(this.selIndex); | |||||
| }, | |||||
| /** | |||||
| * Query average rate info | |||||
| * @param {Boolean} isFilter wherter filter step | |||||
| * @param {Boolean} isInitGraph wherter init graph | |||||
| */ | |||||
| queryCpuInfo(isFilter, isInitGraph) { | |||||
| this.cpuInfo.deviceId = this.currentCard; | |||||
| const params = { | |||||
| params: { | |||||
| profile: this.dir, | |||||
| train_id: this.trainId, | |||||
| }, | |||||
| body: { | |||||
| device_id: this.currentCard, | |||||
| filter_condition: {}, | |||||
| }, | |||||
| }; | |||||
| if (isFilter) { | |||||
| params.body.filter_condition.start_step = this.cpuInfo.startStep.step; | |||||
| params.body.filter_condition.end_step = this.cpuInfo.endStep.step; | |||||
| } | |||||
| this.cpuInfo.initOver = false; | |||||
| RequestService.getCpuUtilization(params).then( | |||||
| (res) => { | |||||
| this.cpuInfo.initOver = true; | |||||
| if (res && res.data) { | |||||
| this.cpuInfo.noData = !res.data.step_total_num; | |||||
| this.cpuInfo.step = res.data.step_total_num; | |||||
| this.cpuInfo.stepArray = res.data.step_info; | |||||
| this.cpuInfo.stepTip = this.$t('profiling.cpuStepTip', {max: `${this.cpuInfo.step}`}); | |||||
| this.cpuInfo.cpuStepInputTip = this.$t('profiling.cpuStepInputTip', {max: `${this.cpuInfo.step}`}); | |||||
| this.samplingInterval = res.data.sampling_interval; | |||||
| this.deviceCpuChart.logicCores = res.data.cpu_processor_num; | |||||
| const deviceInfo = res.data.device_info; | |||||
| const processInfo = res.data.process_info; | |||||
| const opInfo = res.data.op_info; | |||||
| if (deviceInfo && processInfo && opInfo && this.samplingInterval) { | |||||
| this.initDeviceCpu(deviceInfo); | |||||
| this.initProcessCpu(processInfo); | |||||
| if (isInitGraph) { | |||||
| this.$nextTick(() => { | |||||
| this.initCPUGraph().then(() => { | |||||
| this.initOperatorCpu(opInfo, true); | |||||
| }); | |||||
| }); | |||||
| } else { | |||||
| this.$nextTick(() => { | |||||
| this.initOperatorCpu(opInfo, false); | |||||
| }); | |||||
| } | |||||
| } else { | |||||
| this.clearCpuChart(); | |||||
| } | |||||
| } else { | |||||
| this.clearCpuChart(); | |||||
| this.cpuInfo.noData = true; | |||||
| } | |||||
| }, | |||||
| () => { | |||||
| this.clearCpuChart(); | |||||
| this.cpuInfo.initOver = true; | |||||
| this.cpuInfo.noData = true; | |||||
| }, | |||||
| ); | |||||
| }, | |||||
| /** | |||||
| * clear cpu chart and graph | |||||
| */ | |||||
| clearCpuChart() { | |||||
| if (this.deviceCpuChart.chartDom) { | |||||
| this.deviceCpuChart.chartDom.clear(); | |||||
| } | |||||
| if (this.processCpuChart.chartDom) { | |||||
| this.processCpuChart.chartDom.clear(); | |||||
| } | |||||
| if (this.operatorCpuChart.chartDom) { | |||||
| this.operatorCpuChart.chartDom.clear(); | |||||
| } | |||||
| }, | |||||
| /** | |||||
| * filter step to view cpu info | |||||
| */ | |||||
| viewStepFilter() { | |||||
| if ( | |||||
| /^[0-9]*[1-9][0-9]*$/.test(this.cpuInfo.startStep.showStep) && | |||||
| /^[0-9]*[1-9][0-9]*$/.test(this.cpuInfo.endStep.showStep) && | |||||
| this.cpuInfo.startStep.showStep <= this.cpuInfo.endStep.showStep && | |||||
| this.cpuInfo.endStep.showStep <= this.cpuInfo.step | |||||
| ) { | |||||
| this.cpuInfo.startStep.step = this.cpuInfo.startStep.showStep; | |||||
| this.cpuInfo.endStep.step = this.cpuInfo.endStep.showStep; | |||||
| this.queryCpuInfo(true, false); | |||||
| } else if (this.cpuInfo.endStep.showStep === '' && | |||||
| /^[0-9]*[1-9][0-9]*$/.test(this.cpuInfo.startStep.showStep) && | |||||
| this.cpuInfo.startStep.showStep <= this.cpuInfo.step) { | |||||
| this.cpuInfo.startStep.step = this.cpuInfo.startStep.showStep; | |||||
| this.cpuInfo.endStep.step = this.cpuInfo.step; | |||||
| this.cpuInfo.endStep.showStep = this.cpuInfo.step; | |||||
| this.queryCpuInfo(true, false); | |||||
| } else if (this.cpuInfo.startStep.showStep === '' && | |||||
| /^[0-9]*[1-9][0-9]*$/.test(this.cpuInfo.endStep.showStep) && | |||||
| this.cpuInfo.endStep.showStep <= this.cpuInfo.step) { | |||||
| this.cpuInfo.startStep.step = 1; | |||||
| this.cpuInfo.startStep.showStep = 1; | |||||
| this.cpuInfo.endStep.step = this.cpuInfo.endStep.showStep; | |||||
| this.queryCpuInfo(true, false); | |||||
| } else if (this.cpuInfo.startStep.showStep === '' && | |||||
| this.cpuInfo.endStep.showStep === '') { | |||||
| this.resetStepFilter(); | |||||
| } else { | |||||
| this.cpuInfo.startStep.showStep = this.cpuInfo.startStep.step; | |||||
| this.cpuInfo.endStep.showStep = this.cpuInfo.endStep.step; | |||||
| this.$message.error(this.cpuInfo.cpuStepInputTip); | |||||
| } | |||||
| }, | |||||
| /** | |||||
| * reset to view all cpu info | |||||
| */ | |||||
| resetStepFilter() { | |||||
| this.cpuInfo.startStep.showStep = ''; | |||||
| this.cpuInfo.startStep.step = ''; | |||||
| this.cpuInfo.endStep.showStep = ''; | |||||
| this.cpuInfo.endStep.step = ''; | |||||
| this.queryCpuInfo(false, false); | |||||
| }, | |||||
| /** | |||||
| * format chart tip | |||||
| * @param {Object} params | |||||
| * @param {Array} stepArray | |||||
| * @return {String} | |||||
| */ | |||||
| formateCpuChartTip(params, stepArray) { | |||||
| const data = params; | |||||
| let str = ''; | |||||
| if (data && data.length) { | |||||
| const colorArray = [ | |||||
| '#c23531', | |||||
| '#2f4554', | |||||
| '#61a0a8', | |||||
| '#d48265', | |||||
| '#d48265', | |||||
| ]; | |||||
| const index = data[0].dataIndex; | |||||
| str += `step: ${stepArray[index]}`; | |||||
| data.forEach((item, index) => { | |||||
| str += `<br><span class="cpu-chart-tip" style="background-color:${colorArray[index]};"></span>` + | |||||
| `${item.seriesName}: ${item.data}`; | |||||
| }); | |||||
| str += `</div>`; | |||||
| } | |||||
| return str; | |||||
| }, | |||||
| /** | |||||
| * Init device cpu chart | |||||
| * @param {Object} deviceInfo | |||||
| */ | |||||
| initDeviceCpu(deviceInfo) { | |||||
| const series = []; | |||||
| const legend = []; | |||||
| Object.keys(this.cpuInfo.cpuInfoStr).forEach((val) => { | |||||
| const info = deviceInfo[val]; | |||||
| if (info && info.metrics) { | |||||
| const item = { | |||||
| type: 'line', | |||||
| name: this.cpuInfo.cpuInfoStr[val], | |||||
| data: info.metrics, | |||||
| showSymbol: false, | |||||
| }; | |||||
| series.push(item); | |||||
| legend.push(item.name); | |||||
| } | |||||
| }); | |||||
| this.deviceCpuChart.cpuAvgUser = deviceInfo.user_utilization.avg_value; | |||||
| this.deviceCpuChart.cpuAvgSystem = deviceInfo.sys_utilization.avg_value; | |||||
| this.deviceCpuChart.cpuAvgIO = deviceInfo.io_utilization.avg_value; | |||||
| this.deviceCpuChart.cpuAvgFree = deviceInfo.idle_utilization.avg_value; | |||||
| this.deviceCpuChart.cpuAvgProcess = deviceInfo.runable_processes.avg_value; | |||||
| this.deviceCpuChart.cpuAvgSwitch = deviceInfo.context_switch_count.avg_value; | |||||
| this.deviceCpuChart.option.series = series; | |||||
| this.deviceCpuChart.option.xAxis.name = `${this.$t('profiling.sampleInterval')}\n${ | |||||
| this.$t('symbols.leftbracket')}${this.samplingInterval}ms${this.$t('symbols.rightbracket')}`; | |||||
| this.deviceCpuChart.option.xAxis.data = deviceInfo[Object.keys(deviceInfo)[0]].metrics.map( | |||||
| (val, index) => index + 1, | |||||
| ); | |||||
| this.deviceCpuChart.option.legend.data = legend; | |||||
| this.deviceCpuChart.option.tooltip.formatter = (params) => { | |||||
| return this.formateCpuChartTip(params, this.cpuInfo.stepArray); | |||||
| }; | |||||
| this.$nextTick(() => { | |||||
| if (this.$refs.deviceCpuChart) { | |||||
| this.deviceCpuChart.chartDom = echarts.init(this.$refs.deviceCpuChart); | |||||
| } | |||||
| this.deviceCpuChart.chartDom.setOption(this.deviceCpuChart.option); | |||||
| }); | |||||
| }, | |||||
| /** | |||||
| * Init process cpu chart | |||||
| * @param {Object} processInfo | |||||
| */ | |||||
| initProcessCpu(processInfo) { | |||||
| const series = []; | |||||
| const legend = []; | |||||
| Object.keys(this.cpuInfo.cpuInfoStr).forEach((val) => { | |||||
| const info = processInfo[val]; | |||||
| if (info && info.metrics) { | |||||
| const item = { | |||||
| type: 'line', | |||||
| name: this.cpuInfo.cpuInfoStr[val], | |||||
| data: info.metrics, | |||||
| showSymbol: false, | |||||
| }; | |||||
| series.push(item); | |||||
| legend.push(item.name); | |||||
| } | |||||
| }); | |||||
| this.processCpuChart.cpuAvgUser = processInfo.user_utilization.avg_value; | |||||
| this.processCpuChart.cpuAvgSystem = processInfo.sys_utilization.avg_value; | |||||
| this.processCpuChart.option.series = series; | |||||
| this.processCpuChart.option.xAxis.name = `${this.$t('profiling.sampleInterval')}\n${ | |||||
| this.$t('symbols.leftbracket')}${this.samplingInterval}ms${this.$t('symbols.rightbracket')}`; | |||||
| this.processCpuChart.option.xAxis.data = processInfo[Object.keys(processInfo)[0]].metrics.map( | |||||
| (val, index) => index + 1, | |||||
| ); | |||||
| this.processCpuChart.option.legend.data = legend; | |||||
| this.processCpuChart.option.tooltip.formatter = (params) => { | |||||
| return this.formateCpuChartTip(params, this.cpuInfo.stepArray); | |||||
| }; | |||||
| this.$nextTick(() => { | |||||
| if (this.$refs.processCpuChart) { | |||||
| this.processCpuChart.chartDom = echarts.init(this.$refs.processCpuChart); | |||||
| } | |||||
| this.processCpuChart.chartDom.setOption(this.processCpuChart.option); | |||||
| }); | |||||
| }, | |||||
| /** | |||||
| * Init operator cpu chart | |||||
| * @param {Object} opInfo | |||||
| * @param {Boolean} isClickNode | |||||
| */ | |||||
| initOperatorCpu(opInfo, isClickNode) { | |||||
| this.operatorCpuChart.opList = {}; | |||||
| opInfo.op_list.forEach((data) => { | |||||
| this.operatorCpuChart.opList[data.op_id] = data; | |||||
| }); | |||||
| if (isClickNode) { | |||||
| // Select first node as default node, and keep it in right style when page mounted | |||||
| const node = document.getElementById(this.operatorCPUList[this.selIndex]); | |||||
| if (node) { | |||||
| this.clickEvent(node); | |||||
| }; | |||||
| } | |||||
| this.operatorCpuChart.cpuAvgTotalUser = opInfo.total_op_avg_value.user_utilization; | |||||
| this.operatorCpuChart.cpuAvgTotalSystem = opInfo.total_op_avg_value.sys_utilization; | |||||
| this.updateOperatorCpuChart(this.selIndex); | |||||
| }, | |||||
| /** | |||||
| * update cpu chart | |||||
| * @param {String} opId | |||||
| */ | |||||
| updateOperatorCpuChart(opId) { | |||||
| const series = []; | |||||
| const legend = []; | |||||
| if (this.operatorCpuChart.opList[opId]) { | |||||
| const currentOpInfo = this.operatorCpuChart.opList[opId].metrics; | |||||
| const numWorkers = this.operatorCpuChart.opList[opId].num_workers; | |||||
| if (currentOpInfo) { | |||||
| Object.keys(this.cpuInfo.cpuInfoStr).forEach((val) => { | |||||
| const info = currentOpInfo[val]; | |||||
| if (info && info.metrics) { | |||||
| const item = { | |||||
| type: 'line', | |||||
| name: this.cpuInfo.cpuInfoStr[val], | |||||
| data: info.metrics, | |||||
| showSymbol: false, | |||||
| }; | |||||
| series.push(item); | |||||
| legend.push(item.name); | |||||
| } | |||||
| }); | |||||
| this.operatorCpuChart.cpuAvgOpUser = currentOpInfo.user_utilization.avg_value; | |||||
| this.operatorCpuChart.cpuAvgOpSystem = currentOpInfo.sys_utilization.avg_value; | |||||
| this.operatorCpuChart.processNumber = numWorkers; | |||||
| this.operatorCpuChart.option.series = series; | |||||
| this.operatorCpuChart.option.xAxis.name = `${this.$t('profiling.sampleInterval')}\n${ | |||||
| this.$t('symbols.leftbracket')}${this.samplingInterval}ms${this.$t('symbols.rightbracket')}`; | |||||
| this.operatorCpuChart.option.xAxis.data = currentOpInfo[Object.keys(currentOpInfo)[0]].metrics.map( | |||||
| (val, index) => index + 1, | |||||
| ); | |||||
| this.operatorCpuChart.option.legend.data = legend; | |||||
| this.operatorCpuChart.option.tooltip.formatter = (params) => { | |||||
| return this.formateCpuChartTip(params, this.cpuInfo.stepArray); | |||||
| }; | |||||
| this.$nextTick(() => { | |||||
| if (this.$refs.operatorCpuChart) { | |||||
| if (!this.operatorCpuChart.chartDom) { | |||||
| this.operatorCpuChart.chartDom = echarts.init(this.$refs.operatorCpuChart); | |||||
| } | |||||
| } | |||||
| this.operatorCpuChart.chartDom.setOption(this.operatorCpuChart.option); | |||||
| }); | |||||
| } | |||||
| } | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| @@ -0,0 +1,215 @@ | |||||
| <!-- | |||||
| Copyright 2021 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Licensed 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. | |||||
| --> | |||||
| <script> | |||||
| export default { | |||||
| /** | |||||
| * The logic of transform object to string in 'dot' form | |||||
| * @param {Object} object | |||||
| * @return {String} | |||||
| */ | |||||
| objectToDot(object) { | |||||
| const keys = Object.keys(object); | |||||
| let attrTemp = ''; | |||||
| let nodesTemp = ''; | |||||
| let subTemp = ''; | |||||
| let arrowsTemp = ''; | |||||
| let mixTemp = ''; | |||||
| for (let i = 0; i < keys.length; i++) { | |||||
| switch (keys[i]) { | |||||
| case 'nodes': | |||||
| const tempArray = this.nodesToDot(object[keys[i]]); | |||||
| nodesTemp = tempArray[0]; | |||||
| arrowsTemp += tempArray[1]; | |||||
| break; | |||||
| case 'mix': | |||||
| const mixTempArray = this.mixToDot(object[keys[i]]); | |||||
| mixTemp = mixTempArray[0]; | |||||
| arrowsTemp += mixTempArray[1]; | |||||
| break; | |||||
| case 'subgraph': | |||||
| const subTempArray = this.subToDot(object[keys[i]]); | |||||
| subTemp = subTempArray[0]; | |||||
| arrowsTemp += subTempArray[1]; | |||||
| break; | |||||
| default: | |||||
| attrTemp += this.attrToDot(object[keys[i]], keys[i]); | |||||
| break; | |||||
| } | |||||
| } | |||||
| const dotTemp = `digraph {${attrTemp}${nodesTemp}${subTemp}${mixTemp}${arrowsTemp}}`; | |||||
| return dotTemp; | |||||
| }, | |||||
| /** | |||||
| * The logic of transform object.subgraph to string in 'dot' form | |||||
| * @param {Object} subgraph | |||||
| * @return {String} | |||||
| */ | |||||
| subToDot(subgraph) { | |||||
| let subTemp = ''; | |||||
| let arrowTemp = ''; | |||||
| for (let i = 0; i < subgraph.length; i++) { | |||||
| subTemp += `subgraph <${subgraph[i].name}>{`; | |||||
| const keys = Object.keys(subgraph[i]); | |||||
| for (let j = 0; j < keys.length; j++) { | |||||
| switch (keys[j]) { | |||||
| case 'name': | |||||
| break; | |||||
| case 'nodes': | |||||
| const tempArray = this.nodesToDot(subgraph[i].nodes); | |||||
| subTemp += tempArray[0]; | |||||
| arrowTemp += tempArray[1]; | |||||
| break; | |||||
| case 'next': | |||||
| arrowTemp += this.nextToDot(subgraph[i].next, subgraph[i].name); | |||||
| break; | |||||
| default: | |||||
| subTemp += `${keys[j]}="${subgraph[i][keys[j]]}";`; | |||||
| } | |||||
| } | |||||
| subTemp += '};'; | |||||
| } | |||||
| return [subTemp, arrowTemp]; | |||||
| }, | |||||
| /** | |||||
| * The logic of transform 'next' of single item in object.nodes to string in 'dot' form | |||||
| * @param {Object} object | |||||
| * @param {Object} start | |||||
| * @return {String} | |||||
| */ | |||||
| nextToDot(object, start) { | |||||
| let arrowTemp = ''; | |||||
| if (Array.isArray(object)) { | |||||
| for (let i = 0; i < object.length; i++) { | |||||
| const keys = Object.keys(object[i]); | |||||
| arrowTemp += `<${start}>-><${object[i].name}>[`; | |||||
| for (let j = 0; j < keys.length; j++) { | |||||
| if (keys[j] !== 'name') { | |||||
| if (object[i][keys[j]][0] === '<') { | |||||
| arrowTemp += `${keys[j]}=${object[i][keys[j]]};`; | |||||
| } else { | |||||
| arrowTemp += `${keys[j]}="${object[i][keys[j]]}";`; | |||||
| } | |||||
| } | |||||
| } | |||||
| arrowTemp += '];'; | |||||
| } | |||||
| } else { | |||||
| const keys = Object.keys(object); | |||||
| arrowTemp += `<${start}>-><${object.name}>[`; | |||||
| for (let i = 0; i < keys.length; i++) { | |||||
| if (keys[i] !== 'name') { | |||||
| if (object[keys[i]][0] === '<') { | |||||
| arrowTemp += `${keys[i]}=${object[keys[i]]};`; | |||||
| } else { | |||||
| arrowTemp += `${keys[i]}="${object[keys[i]]}";`; | |||||
| } | |||||
| } | |||||
| } | |||||
| arrowTemp += '];'; | |||||
| } | |||||
| return arrowTemp; | |||||
| }, | |||||
| /** | |||||
| * The logic of transform object.attr to string in 'dot' form | |||||
| * @param {Object} object | |||||
| * @param {String} title | |||||
| * @return {String} | |||||
| */ | |||||
| attrToDot(object, title) { | |||||
| const keys = Object.keys(object); | |||||
| if (keys.length === 0) { | |||||
| return; | |||||
| } | |||||
| if (title === 'total') { | |||||
| let nodeTemp = ''; | |||||
| for (let i = 0; i < keys.length; i++) { | |||||
| nodeTemp += `${keys[i]}="${object[keys[i]]}";`; | |||||
| } | |||||
| return nodeTemp; | |||||
| } else { | |||||
| let nodeTemp = `${title}[`; | |||||
| for (let i = 0; i < keys.length; i++) { | |||||
| nodeTemp += `${keys[i]}="${object[keys[i]]}";`; | |||||
| } | |||||
| return `${nodeTemp}];`; | |||||
| } | |||||
| }, | |||||
| /** | |||||
| * The logic of transform object.nodes to string in 'dot' form | |||||
| * @param {Array} nodes | |||||
| * @return {Array<string>} | |||||
| */ | |||||
| nodesToDot(nodes) { | |||||
| let nodesTemp = ''; | |||||
| let arrowsTemp = ''; | |||||
| for (let i = 0; i < nodes.length; i++) { | |||||
| const tempArray = this.nodeToDot(nodes[i]); | |||||
| nodesTemp += tempArray[0]; | |||||
| arrowsTemp += tempArray[1]; | |||||
| } | |||||
| return [nodesTemp, arrowsTemp]; | |||||
| }, | |||||
| /** | |||||
| * The logic of transform object.mix to string in 'dot' form | |||||
| * @param {Array} mix | |||||
| * @return {Array<string>} | |||||
| */ | |||||
| mixToDot(mix) { | |||||
| let nodesTemp = ''; | |||||
| let arrowsTemp = ''; | |||||
| for (let i = 0; i < mix.length; i++) { | |||||
| const keys = Object.keys(mix[i]); | |||||
| let attrTemp = ''; | |||||
| let nodeTemp = ''; | |||||
| for (let j = 0; j <keys.length; j++) { | |||||
| if (keys[j] === 'nodes') { | |||||
| const tempArray = this.nodesToDot(mix[i].nodes); | |||||
| nodeTemp += tempArray[0]; | |||||
| arrowsTemp += tempArray[1]; | |||||
| } else { | |||||
| attrTemp += `${keys[j]}="${mix[i][keys[j]]}";`; | |||||
| } | |||||
| } | |||||
| nodesTemp += `{${attrTemp}${nodeTemp}};`; | |||||
| } | |||||
| return [nodesTemp, arrowsTemp]; | |||||
| }, | |||||
| /** | |||||
| * The logic of transform single item in object.nodes to string in 'dot' form | |||||
| * @param {String} node | |||||
| * @return {Array<string>} | |||||
| */ | |||||
| nodeToDot(node) { | |||||
| let nodeTemp = `<${node.name}>[`; | |||||
| let arrowTemp = ''; | |||||
| const keys = Object.keys(node); | |||||
| for (let i = 0; i < keys.length; i++) { | |||||
| switch (keys[i]) { | |||||
| case 'name': | |||||
| break; | |||||
| case 'next': | |||||
| arrowTemp += this.nextToDot(node.next, node.name); | |||||
| break; | |||||
| default: | |||||
| nodeTemp += `${keys[i]}="${node[keys[i]]}";`; | |||||
| break; | |||||
| } | |||||
| } | |||||
| nodeTemp += '];'; | |||||
| return [nodeTemp, arrowTemp]; | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| @@ -461,6 +461,14 @@ export default { | |||||
| params: params, | params: params, | ||||
| }); | }); | ||||
| }, | }, | ||||
| getCpuUtilization(params) { | |||||
| return axios({ | |||||
| method: 'post', | |||||
| url: 'v1/mindinsight/profile/minddata-cpu-utilization-summary', | |||||
| params: params.params, | |||||
| data: params.body, | |||||
| }); | |||||
| }, | |||||
| setRecommendWatchPoints(params) { | setRecommendWatchPoints(params) { | ||||
| return axios({ | return axios({ | ||||
| method: 'post', | method: 'post', | ||||
| @@ -1,5 +1,5 @@ | |||||
| <!-- | <!-- | ||||
| Copyright 2020 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Copyright 2020-2021 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | you may not use this file except in compliance with the License. | ||||
| @@ -73,6 +73,7 @@ export default { | |||||
| 'minddata_pipeline-generator_op', | 'minddata_pipeline-generator_op', | ||||
| 'minddata_pipeline-map_op', | 'minddata_pipeline-map_op', | ||||
| 'minddata_pipeline-batch_op', | 'minddata_pipeline-batch_op', | ||||
| 'minddata_cpu_utilization', | |||||
| 'minddata_warning_op', | 'minddata_warning_op', | ||||
| ], | ], | ||||
| moreParameter: ['minddata_device_queue', 'minddata_get_next_queue'], | moreParameter: ['minddata_device_queue', 'minddata_get_next_queue'], | ||||
| @@ -1,5 +1,5 @@ | |||||
| <!-- | <!-- | ||||
| Copyright 2020 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Copyright 2020-2021 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | you may not use this file except in compliance with the License. | ||||
| @@ -302,29 +302,146 @@ limitations under the License. | |||||
| <p>{{initOver?$t("public.noData"):$t("public.dataLoading")}}</p> | <p>{{initOver?$t("public.noData"):$t("public.dataLoading")}}</p> | ||||
| </div> | </div> | ||||
| </el-tab-pane> | </el-tab-pane> | ||||
| <!-- CPU --> | |||||
| <el-tab-pane :label="$t('profiling.cpuUtilization')" | |||||
| name="cpuInfo"> | |||||
| <div class="cpu-info" | |||||
| v-if="!cpuInfo.noData"> | |||||
| <div class="step-filter"> | |||||
| <label>{{cpuInfo.stepTip}}</label> | |||||
| <label>{{$t('profiling.startStep')}}</label> | |||||
| <el-input class="step-input" | |||||
| v-model.number="cpuInfo.startStep.showStep"></el-input> | |||||
| <label>{{$t('profiling.endStep')}}</label> | |||||
| <el-input class="step-input" | |||||
| v-model.number="cpuInfo.endStep.showStep"></el-input> | |||||
| <el-button @click="viewStepFilter">{{$t('profiling.filterStep')}}</el-button> | |||||
| <el-button @click="resetStepFilter">{{$t('profiling.resetStep')}}</el-button> | |||||
| </div> | |||||
| <div class="cpu-detail"> | |||||
| <div class="cpu-detail-item"> | |||||
| <div class="detail-item-title">{{$t('profiling.structuralCpuUtil')}}</div> | |||||
| <div class="detail-item"> | |||||
| <div class="cpu-chart" | |||||
| id="deviceCpuChart" | |||||
| ref="deviceCpuChart"></div> | |||||
| <div class="cpu-chart-info"> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.logicCores')}}</span><span>{{deviceCpuChart.logicCores}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgUserUtilization')}}</span><span>{{deviceCpuChart.cpuAvgUser}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgSysUtilization')}}</span><span>{{deviceCpuChart.cpuAvgSystem}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgIOUtilization')}}</span><span>{{deviceCpuChart.cpuAvgIO}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgIdleUtilization')}}</span><span>{{deviceCpuChart.cpuAvgFree}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgWaitingProcess')}}</span><span>{{deviceCpuChart.cpuAvgProcess}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgSwitchCount')}}</span><span>{{deviceCpuChart.cpuAvgSwitch}}</span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="cpu-detail-item cpu-detail-item-top"> | |||||
| <div class="detail-item-title">{{$t('profiling.processCpuUtil')}}</div> | |||||
| <div class="detail-item"> | |||||
| <div class="cpu-chart" | |||||
| id="processCpuChart" | |||||
| ref="processCpuChart"> | |||||
| </div> | |||||
| <div class="cpu-chart-info"> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgUserUtilization')}}</span><span>{{processCpuChart.cpuAvgUser}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgSysUtilization')}}</span><span>{{processCpuChart.cpuAvgSystem}}</span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="cpu-detail-item cpu-detail-item-top"> | |||||
| <div class="detail-item-title">{{$t('profiling.operatorCpuUtil')}}</div> | |||||
| <div class="detail-item-graph" | |||||
| id="operator-graph"></div> | |||||
| <div class="detail-item"> | |||||
| <div class="cpu-chart" | |||||
| id="operatorCpuChart" | |||||
| ref="operatorCpuChart"> | |||||
| </div> | |||||
| <div class="cpu-chart-info"> | |||||
| <div class="info-title"> | |||||
| {{$t('profiling.allOperators')}} | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgUserUtilization')}}</span> | |||||
| <span>{{operatorCpuChart.cpuAvgTotalUser}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgSysUtilization')}}</span> | |||||
| <span>{{operatorCpuChart.cpuAvgTotalSystem}}</span> | |||||
| </div> | |||||
| <div class="info-title"> | |||||
| {{$t('profiling.currentOperator')}} | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgUserUtilization')}}</span> | |||||
| <span>{{operatorCpuChart.cpuAvgOpUser}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.avgSysUtilization')}}</span> | |||||
| <span>{{operatorCpuChart.cpuAvgOpSystem}}</span> | |||||
| </div> | |||||
| <div class="info-line"> | |||||
| <span>{{$t('profiling.workersNum')}}{{$t('symbols.colon')}}</span> | |||||
| <span>{{operatorCpuChart.processNumber}}</span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="image-noData" | |||||
| v-else> | |||||
| <div> | |||||
| <img :src="require('@/assets/images/nodata.png')" | |||||
| alt="" /> | |||||
| </div> | |||||
| <p>{{cpuInfo.initOver?$t("public.noData"):$t("public.dataLoading")}}</p> | |||||
| </div> | |||||
| </el-tab-pane> | |||||
| </el-tabs> | </el-tabs> | ||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| <script> | <script> | ||||
| import echarts from 'echarts'; | import echarts from 'echarts'; | ||||
| import RequestService from '../../services/request-service'; | import RequestService from '../../services/request-service'; | ||||
| import cpuUtilizaton from '../../mixins/cpu-utilization.vue'; | |||||
| import {select, selectAll, zoom} from 'd3'; | import {select, selectAll, zoom} from 'd3'; | ||||
| import {event as currentEvent} from 'd3-selection'; | import {event as currentEvent} from 'd3-selection'; | ||||
| import 'd3-graphviz'; | import 'd3-graphviz'; | ||||
| const d3 = {select, selectAll, zoom}; | const d3 = {select, selectAll, zoom}; | ||||
| export default { | export default { | ||||
| mixins: [cpuUtilizaton], | |||||
| props: {}, | props: {}, | ||||
| data() { | data() { | ||||
| return { | return { | ||||
| dir: '', // Profiler path | dir: '', // Profiler path | ||||
| currentCard: '', // Purrent card number | currentCard: '', // Purrent card number | ||||
| connectQueueChart: { | connectQueueChart: { | ||||
| // Ponnect queue chart object | |||||
| // Connect queue chart object | |||||
| id: 'connect-queue', | id: 'connect-queue', | ||||
| chartDom: null, | chartDom: null, | ||||
| data: [], | data: [], | ||||
| queueSummary: {}, | queueSummary: {}, | ||||
| advise: '', | |||||
| type: 0, | type: 0, | ||||
| params: 'device_queue', | params: 'device_queue', | ||||
| noData: true, | noData: true, | ||||
| @@ -338,7 +455,6 @@ export default { | |||||
| chartDom: null, | chartDom: null, | ||||
| data: [], | data: [], | ||||
| queueSummary: {}, | queueSummary: {}, | ||||
| advise: '', | |||||
| type: 0, | type: 0, | ||||
| params: 'get_next', | params: 'get_next', | ||||
| noData: true, | noData: true, | ||||
| @@ -424,10 +540,15 @@ export default { | |||||
| document.title = `${this.$t('profiling.mindData')}-MindInsight`; | document.title = `${this.$t('profiling.mindData')}-MindInsight`; | ||||
| } | } | ||||
| if (this.activeName === 'queueInfo') { | if (this.activeName === 'queueInfo') { | ||||
| this.initOver = false; | |||||
| this.init(); | this.init(); | ||||
| } else { | |||||
| } else if (this.activeName === 'pipeLine') { | |||||
| this.queryAverageRate(); | this.queryAverageRate(); | ||||
| } else { | |||||
| this.cpuInfo.startStep.showStep = ''; | |||||
| this.cpuInfo.startStep.step = ''; | |||||
| this.cpuInfo.endStep.showStep = ''; | |||||
| this.cpuInfo.endStep.step = ''; | |||||
| this.queryCpuInfo(false, true); | |||||
| } | } | ||||
| } | } | ||||
| if (this.activeName === 'queueInfo' && this.$parent.curDashboardInfo.initOver) { | if (this.activeName === 'queueInfo' && this.$parent.curDashboardInfo.initOver) { | ||||
| @@ -469,16 +590,19 @@ export default { | |||||
| * Tabs switch | * Tabs switch | ||||
| */ | */ | ||||
| handleClick() { | handleClick() { | ||||
| if ( | |||||
| this.activeName === 'pipeLine' && | |||||
| this.averageRateChart.deviceId !== this.currentCard | |||||
| ) { | |||||
| if (this.activeName === 'pipeLine' && this.averageRateChart.deviceId !== this.currentCard) { | |||||
| this.queryAverageRate(); | this.queryAverageRate(); | ||||
| } else if (this.activeName === 'queueInfo' && this.connectQueueChart.deviceId !== this.currentCard) { | |||||
| this.init(); | |||||
| } else if ( | } else if ( | ||||
| this.activeName === 'queueInfo' && | |||||
| this.connectQueueChart.deviceId !== this.currentCard | |||||
| this.activeName === 'cpuInfo' && | |||||
| this.cpuInfo.deviceId !== this.currentCard | |||||
| ) { | ) { | ||||
| this.init(); | |||||
| this.cpuInfo.startStep.showStep = ''; | |||||
| this.cpuInfo.startStep.step = ''; | |||||
| this.cpuInfo.endStep.showStep = ''; | |||||
| this.cpuInfo.endStep.step = ''; | |||||
| this.queryCpuInfo(false, true); | |||||
| } | } | ||||
| this.$nextTick(() => { | this.$nextTick(() => { | ||||
| this.resizeCallback(); | this.resizeCallback(); | ||||
| @@ -499,6 +623,9 @@ export default { | |||||
| 'getNextChart', | 'getNextChart', | ||||
| 'averageRateChart', | 'averageRateChart', | ||||
| 'queueDeepChart', | 'queueDeepChart', | ||||
| 'deviceCpuChart', | |||||
| 'processCpuChart', | |||||
| 'operatorCpuChart', | |||||
| ]; | ]; | ||||
| chartArr.forEach((val) => { | chartArr.forEach((val) => { | ||||
| if (this[val].chartDom) { | if (this[val].chartDom) { | ||||
| @@ -528,12 +655,9 @@ export default { | |||||
| if (result.summary) { | if (result.summary) { | ||||
| chart.timeSummary = result.summary.time_summary || {}; | chart.timeSummary = result.summary.time_summary || {}; | ||||
| Object.keys(chart.timeSummary).forEach((val) => { | Object.keys(chart.timeSummary).forEach((val) => { | ||||
| chart.timeSummary[val] = parseFloat( | |||||
| chart.timeSummary[val], | |||||
| ).toFixed(3); | |||||
| chart.timeSummary[val] = parseFloat(chart.timeSummary[val]).toFixed(3); | |||||
| }); | }); | ||||
| } | } | ||||
| chart.advise = result.advise; | |||||
| if (result.size > 0) { | if (result.size > 0) { | ||||
| chart.noData = false; | chart.noData = false; | ||||
| this.$nextTick(() => { | this.$nextTick(() => { | ||||
| @@ -576,7 +700,6 @@ export default { | |||||
| if (result.summary) { | if (result.summary) { | ||||
| chart.queueSummary = result.summary.queue_summary || {}; | chart.queueSummary = result.summary.queue_summary || {}; | ||||
| } | } | ||||
| chart.advise = result.advise; | |||||
| if (result.size > 0) { | if (result.size > 0) { | ||||
| chart.noData = false; | chart.noData = false; | ||||
| chart.size = result.size; | chart.size = result.size; | ||||
| @@ -1459,10 +1582,10 @@ export default { | |||||
| .data-process-wrap .data-process-bottom .queue-step-wrap .chart-content .chart-wrap { | .data-process-wrap .data-process-bottom .queue-step-wrap .chart-content .chart-wrap { | ||||
| float: left; | float: left; | ||||
| width: calc(50% - 12px); | width: calc(50% - 12px); | ||||
| height: calc(100% - 10px); | |||||
| height: calc(100% - 5px); | |||||
| border-radius: 4px; | border-radius: 4px; | ||||
| overflow-y: auto; | overflow-y: auto; | ||||
| border: 1px solid #eee; | |||||
| border: 1px solid #D9D9D9; | |||||
| } | } | ||||
| .data-process-wrap .data-process-bottom .queue-step-wrap .chart-content .chart-wrap:first-child { | .data-process-wrap .data-process-bottom .queue-step-wrap .chart-content .chart-wrap:first-child { | ||||
| margin-right: 20px; | margin-right: 20px; | ||||
| @@ -1607,4 +1730,89 @@ export default { | |||||
| font-size: 16px; | font-size: 16px; | ||||
| padding-top: 10px; | padding-top: 10px; | ||||
| } | } | ||||
| .data-process-wrap .el-button { | |||||
| border: 1px solid #00a5a7; | |||||
| border-radius: 2px; | |||||
| background-color: white; | |||||
| color: #00a5a7; | |||||
| padding: 7px 15px; | |||||
| } | |||||
| .data-process-wrap .el-button:hover { | |||||
| background: rgb(230, 246, 246); | |||||
| } | |||||
| .cpu-info { | |||||
| height: 100%; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| } | |||||
| .cpu-info .step-filter { | |||||
| min-height: 44px; | |||||
| } | |||||
| .cpu-info .step-filter .step-input { | |||||
| width: 100px; | |||||
| margin-right: 20px; | |||||
| } | |||||
| .cpu-info .step-filter:first-child label { | |||||
| margin-right: 10px; | |||||
| } | |||||
| .cpu-info .cpu-detail { | |||||
| flex-grow: 1; | |||||
| overflow-x: hidden; | |||||
| overflow-y: scroll; | |||||
| } | |||||
| .cpu-info .cpu-detail .cpu-detail-item { | |||||
| padding: 16px; | |||||
| border: 1px solid #d9d9d9; | |||||
| border-radius: 4px; | |||||
| margin-right: 8px; | |||||
| } | |||||
| .cpu-info .cpu-detail .cpu-detail-item-top { | |||||
| margin-top: 16px; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item-title { | |||||
| height: 20px; | |||||
| font-size: 15px; | |||||
| font-weight: bold; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item-graph { | |||||
| height: 120px; | |||||
| background-color: #f7faff; | |||||
| margin: 10px 0; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item { | |||||
| height: 400px; | |||||
| display: flex; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item:last-of-type { | |||||
| padding-bottom: 0; | |||||
| border-bottom: none; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item .cpu-chart { | |||||
| height: 100%; | |||||
| flex-grow: 1; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item .cpu-chart-info { | |||||
| height: 100%; | |||||
| width: 300px; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| justify-content: center; | |||||
| padding-left: 20px; | |||||
| background-color: #f1f1f1; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item .cpu-chart-info .info-title { | |||||
| font-size: 14px; | |||||
| font-weight: bold; | |||||
| line-height: 30px; | |||||
| } | |||||
| .cpu-info .cpu-detail .detail-item .cpu-chart-info .info-line { | |||||
| line-height: 30px; | |||||
| } | |||||
| .cpu-chart-tip { | |||||
| display: inline-block; | |||||
| margin-right: 5px; | |||||
| border-radius: 10px; | |||||
| width: 10px; | |||||
| height: 10px; | |||||
| } | |||||
| </style> | </style> | ||||
| @@ -1,5 +1,5 @@ | |||||
| <!-- | <!-- | ||||
| Copyright 2020 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Copyright 2020-2021 Huawei Technologies Co., Ltd.All Rights Reserved. | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | you may not use this file except in compliance with the License. | ||||
| @@ -80,6 +80,7 @@ export default { | |||||
| 'minddata_pipeline-generator_op', | 'minddata_pipeline-generator_op', | ||||
| 'minddata_pipeline-map_op', | 'minddata_pipeline-map_op', | ||||
| 'minddata_pipeline-batch_op', | 'minddata_pipeline-batch_op', | ||||
| 'minddata_cpu_utilization', | |||||
| 'minddata_warning_op', | 'minddata_warning_op', | ||||
| ], | ], | ||||
| moreParameter: ['minddata_device_queue', 'minddata_get_next_queue'], | moreParameter: ['minddata_device_queue', 'minddata_get_next_queue'], | ||||