/* * Copyright (C) 2022 Huawei Device Co., Ltd. * 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. */ import { BaseElement, element } from '../../../base-ui/BaseElement.js'; import { SpSchedulingAnalysis } from './SpSchedulingAnalysis.js'; import { DrawerCpuTabs } from './DrawerCpuTabs.js'; import { LitChartPie } from '../../../base-ui/chart/pie/LitChartPie.js'; import { LitDrawer } from '../../../base-ui/drawer/LitDrawer.js'; import '../../../base-ui/drawer/LitDrawer.js'; import './DrawerCpuTabs.js'; import { procedurePool } from '../../database/Procedure.js'; import { info } from '../../../log/Log.js'; import { LitSelect } from '../../../base-ui/select/LitSelect'; import '../../../base-ui/progress-bar/LitProgressBar.js'; import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar.js'; import { pieChartColors } from '../../../base-ui/chart/pie/LitChartPieData.js'; import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil.js'; @element('tab-cpu-analysis') export class TabCpuAnalysis extends BaseElement { private cpuUsageGrid: HTMLDivElement | undefined; private cpuUsageChart: HTMLDivElement | undefined; private drawer: LitDrawer | undefined | null; private cpuPieMap: Map = new Map(); private schedulingSelect: LitSelect | undefined | null; private drawerCpuTabs: DrawerCpuTabs | undefined | null; private progress: LitProgressBar | null | undefined; private loadingUsage: boolean = false; private loadingPieData: boolean = false; initElements(): void { this.progress = this.shadowRoot!.querySelector('#loading'); this.cpuUsageGrid = this.shadowRoot?.querySelector('#cpu_usage_table') as HTMLDivElement; this.cpuUsageChart = this.shadowRoot?.querySelector('#cpu_usage_chart') as HTMLDivElement; this.schedulingSelect = this.shadowRoot?.querySelector('#scheduling_select'); this.drawer = this.shadowRoot!.querySelector('#drawer-right'); this.drawerCpuTabs = this.shadowRoot?.querySelector('#drawer-cpu-tabs'); this.schedulingSelect!.onchange = (e) => { this.loadingPieData = true; this.progress!.loading = this.loadingUsage || this.loadingPieData; this.queryPieChartDataByType((e as any).detail.text); }; this.drawer!.onClose = (e: any) => { this.drawerCpuTabs!.clearData(); }; } init() { this.cpuPieMap.clear(); this.cpuUsageGrid!.innerHTML = ''; this.cpuUsageChart!.innerHTML = ''; this.schedulingSelect!.value = '1'; this.cpuUsageGrid!.append(this.createUsageItem('usage', '%')); for (let i = 0; i < SpSchedulingAnalysis.cpuCount; i++) { let cpuPie = new LitChartPie(); cpuPie.className = 'pie-chart'; this.cpuPieMap.set(i, cpuPie); this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${i}`, 0)); this.cpuUsageChart!.append(this.createUsageChartItem(i, cpuPie)); } this.loadingUsage = true; this.loadingPieData = true; this.progress!.loading = this.loadingUsage || this.loadingPieData; this.queryLogicWorker('scheduling-getCpuUsage', 'query Cpu Usage Time:', (res) => { if (res && res.length > 0) { this.cpuUsageGrid!.innerHTML = ''; this.cpuUsageGrid!.append(this.createUsageItem('usage', '%')); if (res instanceof Array) { for (let re of res) { this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${re.cpu}`, ((re.usage || 0) * 100).toFixed(2))); } } } this.loadingUsage = false; this.progress!.loading = this.loadingUsage || this.loadingPieData; }); this.queryPieChartDataByType('CPU Idle'); SpStatisticsHttpUtil.addOrdinaryVisitAction({ event: 'CPU Data', action: 'trace_tab', }); } queryPieChartDataByType(type: string) { SpStatisticsHttpUtil.addOrdinaryVisitAction({ event: 'Analysis ' + type, action: 'scheduling_analysis', }); let tip = ''; if (type === 'CPU Frequency') { tip = 'freq:'; } else if (type === 'CPU Idle') { tip = 'idle:'; } else { tip = 'irq:'; } this.queryLogicWorker(`scheduling-${type}`, `query ${type} Analysis Time:`, (res) => { for (let key of this.cpuPieMap.keys()) { this.cpuPieMap.get(key)!.config = { appendPadding: 10, data: res.get(key) || [], angleField: 'sum', colorField: 'value', radius: 0.8, tip: (obj) => { return `
${tip}${obj.obj.value}
ratio:${obj.obj.ratio}%
`; }, label: { type: 'outer', color: type !== 'CPU Idle' ? undefined : (it) => { return pieChartColors[(it as any).value]; }, }, interactions: [ { type: 'element-active', }, ], }; } this.loadingPieData = false; this.progress!.loading = this.loadingUsage || this.loadingPieData; }); } queryLogicWorker(option: string, log: string, handler: (res: any) => void) { let cpuAnalysisTime = new Date().getTime(); procedurePool.submitWithName( 'logic1', option, { endTs: SpSchedulingAnalysis.endTs, total: SpSchedulingAnalysis.totalDur, }, undefined, handler ); let durTime = new Date().getTime() - cpuAnalysisTime; info(log, durTime); } createUsageItem(name: string, value: any) { let div = document.createElement('div'); div.className = 'usage_item_box'; div.innerHTML = `
${name}
${value}
`; return div; } createUsageChartItem(cpu: number, pie: LitChartPie) { let div = document.createElement('div'); div.className = 'usage_chart'; div.style.cursor = 'pointer'; div.innerHTML = `
CPU: ${cpu}
`; div.append(pie); div.addEventListener('click', (event) => { if (this.loadingUsage || this.loadingPieData) { return; } this.drawer!.title = `CPU: ${cpu}`; this.drawer!.visible = true; this.drawerCpuTabs!.init(cpu, this.schedulingSelect!.value); }); return div; } initHtml(): string { return `
CPU Statistics By Duration
CPU Idle CPU Frequency CPU Irq
`; } }