• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../../../base-ui/BaseElement.js';
17import { SpSchedulingAnalysis } from './SpSchedulingAnalysis.js';
18import { DrawerCpuTabs } from './DrawerCpuTabs.js';
19import { LitChartPie } from '../../../base-ui/chart/pie/LitChartPie.js';
20import { LitDrawer } from '../../../base-ui/drawer/LitDrawer.js';
21import '../../../base-ui/drawer/LitDrawer.js';
22import './DrawerCpuTabs.js';
23import { procedurePool } from '../../database/Procedure.js';
24import { info } from '../../../log/Log.js';
25import { LitSelect } from '../../../base-ui/select/LitSelect';
26import '../../../base-ui/progress-bar/LitProgressBar.js';
27import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar.js';
28import { pieChartColors } from '../../../base-ui/chart/pie/LitChartPieData.js';
29import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil.js';
30
31@element('tab-cpu-analysis')
32export class TabCpuAnalysis extends BaseElement {
33  private cpuUsageGrid: HTMLDivElement | undefined;
34  private cpuUsageChart: HTMLDivElement | undefined;
35  private drawer: LitDrawer | undefined | null;
36  private cpuPieMap: Map<number, LitChartPie> = new Map<number, LitChartPie>();
37  private schedulingSelect: LitSelect | undefined | null;
38  private drawerCpuTabs: DrawerCpuTabs | undefined | null;
39  private progress: LitProgressBar | null | undefined;
40  private loadingUsage: boolean = false;
41  private loadingPieData: boolean = false;
42
43  initElements(): void {
44    this.progress = this.shadowRoot!.querySelector<LitProgressBar>('#loading');
45    this.cpuUsageGrid = this.shadowRoot?.querySelector('#cpu_usage_table') as HTMLDivElement;
46    this.cpuUsageChart = this.shadowRoot?.querySelector('#cpu_usage_chart') as HTMLDivElement;
47    this.schedulingSelect = this.shadowRoot?.querySelector<LitSelect>('#scheduling_select');
48    this.drawer = this.shadowRoot!.querySelector<LitDrawer>('#drawer-right');
49    this.drawerCpuTabs = this.shadowRoot?.querySelector<DrawerCpuTabs>('#drawer-cpu-tabs');
50    this.schedulingSelect!.onchange = (e) => {
51      this.loadingPieData = true;
52      this.progress!.loading = this.loadingUsage || this.loadingPieData;
53      this.queryPieChartDataByType((e as any).detail.text);
54    };
55    this.drawer!.onClose = (e: any) => {
56      this.drawerCpuTabs!.clearData();
57    };
58  }
59
60  init() {
61    this.cpuPieMap.clear();
62    this.cpuUsageGrid!.innerHTML = '';
63    this.cpuUsageChart!.innerHTML = '';
64    this.schedulingSelect!.value = '1';
65    this.cpuUsageGrid!.append(this.createUsageItem('usage', '%'));
66    for (let i = 0; i < SpSchedulingAnalysis.cpuCount; i++) {
67      let cpuPie = new LitChartPie();
68      cpuPie.className = 'pie-chart';
69      this.cpuPieMap.set(i, cpuPie);
70      this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${i}`, 0));
71      this.cpuUsageChart!.append(this.createUsageChartItem(i, cpuPie));
72    }
73    this.loadingUsage = true;
74    this.loadingPieData = true;
75    this.progress!.loading = this.loadingUsage || this.loadingPieData;
76    this.queryLogicWorker('scheduling-getCpuUsage', 'query Cpu Usage Time:', (res) => {
77      if (res && res.length > 0) {
78        this.cpuUsageGrid!.innerHTML = '';
79        this.cpuUsageGrid!.append(this.createUsageItem('usage', '%'));
80        if (res instanceof Array) {
81          for (let re of res) {
82            this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${re.cpu}`, ((re.usage || 0) * 100).toFixed(2)));
83          }
84        }
85      }
86      this.loadingUsage = false;
87      this.progress!.loading = this.loadingUsage || this.loadingPieData;
88    });
89    this.queryPieChartDataByType('CPU Idle');
90    SpStatisticsHttpUtil.addOrdinaryVisitAction({
91      event: 'CPU Data',
92      action: 'trace_tab',
93    });
94  }
95
96  queryPieChartDataByType(type: string) {
97    SpStatisticsHttpUtil.addOrdinaryVisitAction({
98      event: 'Analysis ' + type,
99      action: 'scheduling_analysis',
100    });
101    let tip = '';
102    if (type === 'CPU Frequency') {
103      tip = 'freq:';
104    } else if (type === 'CPU Idle') {
105      tip = 'idle:';
106    } else {
107      tip = 'irq:';
108    }
109    this.queryLogicWorker(`scheduling-${type}`, `query ${type} Analysis Time:`, (res) => {
110      for (let key of this.cpuPieMap.keys()) {
111        this.cpuPieMap.get(key)!.config = {
112          appendPadding: 10,
113          data: res.get(key) || [],
114          angleField: 'sum',
115          colorField: 'value',
116          radius: 0.8,
117          tip: (obj) => {
118            return `<div>
119                                    <div>${tip}${obj.obj.value}</div>
120                                    <div>ratio:${obj.obj.ratio}%</div>
121                                </div>
122                                `;
123          },
124          label: {
125            type: 'outer',
126            color:
127              type !== 'CPU Idle'
128                ? undefined
129                : (it) => {
130                    return pieChartColors[(it as any).value];
131                  },
132          },
133          interactions: [
134            {
135              type: 'element-active',
136            },
137          ],
138        };
139      }
140      this.loadingPieData = false;
141      this.progress!.loading = this.loadingUsage || this.loadingPieData;
142    });
143  }
144
145  queryLogicWorker(cpuAnalysisType: string, log: string, handler: (res: any) => void) {
146    let cpuAnalysisTime = new Date().getTime();
147    procedurePool.submitWithName(
148      'logic1',
149      cpuAnalysisType,
150      {
151        endTs: SpSchedulingAnalysis.endTs,
152        total: SpSchedulingAnalysis.totalDur,
153      },
154      undefined,
155      handler
156    );
157    let durTime = new Date().getTime() - cpuAnalysisTime;
158    info(log, durTime);
159  }
160
161  createUsageItem(name: string, value: any) {
162    let div = document.createElement('div');
163    div.className = 'usage_item_box';
164    div.innerHTML = `<div class="usage_item">${name}</div><div class="usage_item">${value}</div>`;
165    return div;
166  }
167
168  createUsageChartItem(cpu: number, pie: LitChartPie) {
169    let div = document.createElement('div');
170    div.className = 'usage_chart';
171    div.style.cursor = 'pointer';
172    div.innerHTML = `
173            <div style="height: 40px;line-height: 40px;margin-left: 10px">CPU: ${cpu}</div>
174        `;
175    div.append(pie);
176    div.addEventListener('click', (event) => {
177      if (this.loadingUsage || this.loadingPieData) {
178        return;
179      }
180      this.drawer!.title = `CPU: ${cpu}`;
181      this.drawer!.visible = true;
182      this.drawerCpuTabs!.init(cpu, this.schedulingSelect!.value);
183    });
184    return div;
185  }
186
187  initHtml(): string {
188    return `
189        <style>
190        :host {
191            width: 100%;
192            height: 100%;
193            background-color: var(--dark-background,#FFFFFF);
194        }
195        .cpu_usage{
196            display: flex;
197            flex-direction: row;
198            box-sizing: border-box;
199            padding: 15px;
200            background-color: var(--dark-background,#FFFFFF);
201        }
202        .usage_item{
203            height: 50px;
204            line-height: 50px;
205            text-align: center;
206            border: solid 1px var(--dark-border1,#f0f0f0);
207        }
208        .usage_item_box{
209            border: solid 1px var(--dark-border1,#f0f0f0);
210            flex: 1;
211        }
212        .usage_chart{
213            height: 360px;
214            color: var(--dark-color1,#252525);
215            background-color: var(--dark-background,#FFFFFF);
216        }
217        .pie-chart{
218            display: flex;
219            box-sizing: border-box;
220            height: 300px;
221        }
222        .grid_usage{
223            display: grid;
224            width: 100%;
225            box-sizing: border-box;
226            grid-template-columns: repeat(4,calc((100% - 30px) / 4));
227            grid-column-gap: 10px;
228            grid-row-gap: 10px;
229            padding: 10px;
230            background-color: var(--dark-background5,#F6F6F6);
231        }
232        .cpu-statistics{
233            height: 50px;
234            display: flex;
235            flex-direction: row;
236            justify-content: space-between;
237            align-items: center;
238            padding:0px 15px;
239            background-color: var(--dark-background,#FFFFFF);
240        }
241        </style>
242        <div style="display: flex;flex-direction: column;overflow-x: hidden;overflow-y: auto;height: 100%">
243            <lit-progress-bar id="loading" style="height: 1px;width: 100%"></lit-progress-bar>
244            <div class="cpu_usage" id="cpu_usage_table"></div>
245            <div class="cpu-statistics">
246                <div>CPU Statistics By Duration</div>
247                <lit-select default-value="1" id="scheduling_select">
248                    <lit-select-option value="1">CPU Idle</lit-select-option>
249                    <lit-select-option value="2">CPU Frequency</lit-select-option>
250                    <lit-select-option value="3">CPU Irq</lit-select-option>
251                </lit-select>
252            </div>
253            <div class="grid_usage" id="cpu_usage_chart"></div>
254        </div>
255        <lit-drawer id="drawer-right" title="CPU:0" content-width="65vw" placement="right" style="position: fixed" fixed mask mask-closeable closeable content-padding="0">
256            <drawer-cpu-tabs id="drawer-cpu-tabs"></drawer-cpu-tabs>
257        </lit-drawer>
258        `;
259  }
260}
261