• 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';
17import { LitTable } from '../../../../../base-ui/table/lit-table';
18import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection';
19import { LitTableColumn } from '../../../../../base-ui/table/lit-table-column';
20import { Utils } from '../../base/Utils';
21import { SpSystemTrace } from '../../../SpSystemTrace';
22import { TabUtil } from './TabUtil';
23import { resizeObserver } from '../SheetUtils';
24import { getTabSdkSliceData } from '../../../../database/sql/Sdk.sql';
25import { queryTotalTime } from '../../../../database/sql/SqlLite.sql';
26import { SdkSliceSummary } from '../../../../bean/SdkSummary';
27
28@element('tabpane-sdk-slice')
29export class TabPaneSdkSlice extends BaseElement {
30  private tblSdkSlice: LitTable | null | undefined;
31  private sdkSliceRange: HTMLLabelElement | null | undefined;
32  private keyList: Array<string> | undefined;
33  private statDataArray: unknown = [];
34  private columnMap: unknown = {};
35  private sqlMap: Map<number, string> = new Map<number, string>();
36
37  set data(valSdkSlice: SelectionParam | unknown) {
38    let millisecond = 1000_000;
39    this.sdkSliceRange!.textContent = //@ts-ignore
40      'Selected range: ' + ((valSdkSlice.rightNs - valSdkSlice.leftNs) / millisecond).toFixed(5) + ' ms';
41    this.queryDataByDB(valSdkSlice);
42  }
43
44  initElements(): void {
45    this.tblSdkSlice = this.shadowRoot?.querySelector<LitTable>('#tb-sdk-slice');
46    this.sdkSliceRange = this.shadowRoot?.querySelector('#sdk-slice-time-range');
47    this.tblSdkSlice!.addEventListener('column-click', (evt) => {
48      // @ts-ignore
49      this.sortByColumn(evt.detail);
50    });
51  }
52
53  connectedCallback(): void {
54    super.connectedCallback();
55    resizeObserver(this.parentElement!, this.tblSdkSlice!);
56  }
57
58  queryDataByDB(sdkSliceVal: SelectionParam | unknown): void {
59    queryTotalTime().then((res) => {
60      let startTime = res[0].recordStartNS;
61      let totalTime = res[0].total;
62      let componentId: number = -1;
63      let slices: Array<string> = []; //@ts-ignore
64      for (let index = 0; index < sdkSliceVal.sdkSliceIds.length; index++) {
65        //@ts-ignore
66        let values = sdkSliceVal.sdkSliceIds[index].split('-');
67        let value = values[0];
68        componentId = Number(values[1]);
69        slices.push(value);
70      } // @ts-ignore
71      this.parseJson(SpSystemTrace.SDK_CONFIG_MAP);
72      let sql = this.sqlMap.get(componentId);
73      if (sql === undefined) {
74        return;
75      } //@ts-ignore
76      getTabSdkSliceData(sql, startTime, sdkSliceVal.leftNs, sdkSliceVal.rightNs, slices, componentId).then(
77        (sliceItem) => {
78          this.keyList = [];
79          this.tblSdkSlice!.innerHTML = '';
80          this.statDataArray = [];
81          if (sliceItem.length !== null && sliceItem.length > 0) {
82            this.initSdkSliceData(sliceItem, totalTime, sdkSliceVal);
83          } else {
84            this.tblSdkSlice!.recycleDataSource = [];
85          }
86          this.initDataElement();
87
88          setTimeout(() => {
89            //@ts-ignore
90            this.tblSdkSlice!.recycleDataSource = this.statDataArray;
91            new ResizeObserver(() => {
92              if (this.parentElement?.clientHeight !== 0) {
93                this.tblSdkSlice!.style.height = '100%';
94                this.tblSdkSlice!.reMeauseHeight();
95              }
96            }).observe(this.parentElement!);
97          }, 200);
98        }
99      );
100    });
101  }
102
103  initSdkSliceData(sliceItem: SdkSliceSummary[], totalTime: number, sdkSliceVal: SelectionParam | unknown): void {
104    for (let sliceItemIndex = 0; sliceItemIndex < sliceItem.length; sliceItemIndex++) {
105      const dataResult = sliceItem[sliceItemIndex];
106      let keys = Object.keys(dataResult);
107      // @ts-ignore
108      let values = Object.values(dataResult);
109      let sliceJsonText = '{';
110      for (let sliceKeyIndex = 0; sliceKeyIndex < keys.length; sliceKeyIndex++) {
111        let sliceKey = keys[sliceKeyIndex];
112        if (this.keyList!.indexOf(sliceKey) <= -1) {
113          this.keyList!.push(sliceKey);
114        }
115        let sliceValue = values[sliceKeyIndex]; //@ts-ignore
116        if (this.columnMap[sliceKey] === 'TimeStamp') {
117          sliceValue = Utils.getTimeString(Number(sliceValue)); //@ts-ignore
118        } else if (this.columnMap[sliceKey] === 'ClockTime') {
119          sliceValue = Utils.getTimeStampHMS(Number(sliceValue)); //@ts-ignore
120        } else if (this.columnMap[sliceKey] === 'RangTime') {
121          sliceValue = Utils.getDurString(Number(sliceValue)); //@ts-ignore
122        } else if (this.columnMap[sliceKey] === 'PercentType') {
123          sliceValue = sliceValue + '%'; //@ts-ignore
124        } else if (this.columnMap[sliceKey] === 'CurrencyType') {
125          sliceValue = sliceValue.toString().replace(/\B(?=(\d{3})+$)/g, ','); //@ts-ignore
126        } else if (this.columnMap[sliceKey] === 'FIXED') {
127          sliceValue = sliceValue.toFixed(2);
128        }
129        if (typeof sliceValue === 'string') {
130          sliceValue = sliceValue.replace(/</gi, '&lt;').replace(/>/gi, '&gt;');
131        }
132        sliceJsonText += '"' + sliceKey + '"' + ': ' + '"' + sliceValue + '"';
133        if (sliceKeyIndex !== keys.length - 1) {
134          sliceJsonText += ',';
135        } else {
136          sliceJsonText += '}';
137        }
138      }
139      let sliceParseData = JSON.parse(sliceJsonText);
140      if (
141        sliceParseData.start_ts !== null &&
142        sliceParseData.end_ts !== null &&
143        sliceParseData.start_ts > sliceParseData.end_ts &&
144        sliceParseData.end_ts === 0
145      ) {
146        sliceParseData.end_ts = totalTime;
147      }
148      if (
149        //@ts-ignore
150        this.isDateIntersection(sdkSliceVal.leftNs, sdkSliceVal.rightNs, sliceParseData.start_ts, sliceParseData.end_ts)
151      ) {
152        //@ts-ignore
153        this.statDataArray.push(sliceParseData);
154      }
155    } //@ts-ignore
156    this.tblSdkSlice!.recycleDataSource = this.statDataArray;
157  }
158
159  private isDateIntersection(
160    selectStartTime: number,
161    selectEndTime: number,
162    startTime: number,
163    endTime: number
164  ): boolean {
165    if (selectStartTime > startTime && selectStartTime < endTime) {
166      return true;
167    }
168    if (selectEndTime > startTime && selectEndTime < endTime) {
169      return true;
170    }
171    if (selectStartTime < startTime && selectEndTime > endTime) {
172      return true;
173    }
174    return false;
175  }
176
177  parseJson(map: Map<number, string>): string {
178    for (let [key, value] of map) {
179      let sliceConfigObj: unknown = value;
180      if (sliceConfigObj !== undefined) {
181        //@ts-ignore
182        let { jsonConfig } = sliceConfigObj;
183        let { tableConfig } = JSON.parse(jsonConfig);
184        if (tableConfig) {
185          for (let showType of tableConfig.showType) {
186            let innerTableName = this.getInnerTableName(showType);
187            let type = TabUtil.getTableType(showType);
188            if (type === 'slice') {
189              let sliceSelectSql = 'select ';
190              for (let { column, displayName, showType: columnShowType } of showType.columns) {
191                //@ts-ignore
192                this.columnMap[column] = displayName;
193                if (columnShowType.includes(3)) {
194                  switch (column) {
195                    case 'slice_id':
196                      sliceSelectSql += 'a.slice_id,b.slice_name,';
197                      break;
198                    case 'start_ts':
199                    case 'end_ts':
200                      sliceSelectSql += `(a.${column} - $startTime) as ${column},`;
201                      break;
202                    default:
203                      sliceSelectSql += `a.${column},`;
204                      break;
205                  }
206                }
207              }
208              let sliceSql = `${sliceSelectSql.slice(0, -1)} from ${showType.tableName} as a,${innerTableName} as b
209                           where a.slice_id in ($slices)
210                           and a.slice_id = b.slice_id
211                           and ((a.start_ts - $startTime) >= $leftNs and (a.end_ts - $startTime) <= $rightNs
212                           or (a.start_ts - $startTime) <= $leftNs and $leftNs <= (a.end_ts - $startTime)
213                           or (a.start_ts - $startTime) <= $rightNs and $rightNs <= (a.end_ts - $startTime))`;
214              this.sqlMap.set(key, sliceSql);
215            }
216          }
217        }
218      }
219    }
220    return '';
221  }
222
223  initDataElement(): void {
224    if (this.keyList) {
225      this.keyList.forEach((sdkSliceItemKey) => {
226        let sdkSliceEl = document.createElement('lit-table-column') as LitTableColumn;
227        sdkSliceEl.setAttribute('title', sdkSliceItemKey);
228        sdkSliceEl.setAttribute('data-index', sdkSliceItemKey);
229        sdkSliceEl.setAttribute('key', sdkSliceItemKey);
230        sdkSliceEl.setAttribute('align', 'flex-start');
231        if (sdkSliceItemKey === 'slice_id') {
232          sdkSliceEl.setAttribute('width', '0.5fr');
233        } else {
234          sdkSliceEl.setAttribute('width', '1fr');
235        }
236        sdkSliceEl.setAttribute('order', '');
237        this.tblSdkSlice!.appendChild(sdkSliceEl);
238      });
239    }
240  }
241
242  initHtml(): string {
243    return `
244<style>
245.sdk-slice-table{
246    height: 20px;
247    margin-bottom: 5px;
248}
249:host{
250    padding: 10px 10px;
251    flex-direction: column;
252    display: flex;
253}
254</style>
255<div class="sdk-slice-content" class="sdk-slice-table" style="display: flex;align-items: center;flex-direction: row;">
256            <stack-bar id="sdk-slice-stack-bar" style="flex: 1"></stack-bar>
257            <label id="sdk-slice-time-range"  style="width: auto;text-align: end;font-size: 10pt;">Selected range:0.0 ms</label>
258        </div>
259<lit-table id="tb-sdk-slice" class="sdk-slice-tbl" style="height: auto">
260</lit-table>
261        `;
262  }
263
264  sortByColumn(sliceDetail: unknown): void {
265    // @ts-ignore
266    function compare(property, sliceSort, type) {
267      return function (aSdkSlice: SelectionData, bSdkSlice: SelectionData) {
268        if (aSdkSlice.process === ' ' || bSdkSlice.process === ' ') {
269          return 0;
270        }
271        if (type === 'number') {
272          return sliceSort === 2
273            ? // @ts-ignore
274            parseFloat(bSdkSlice[property]) - parseFloat(aSdkSlice[property])
275            : // @ts-ignore
276            parseFloat(aSdkSlice[property]) - parseFloat(bSdkSlice[property]);
277        }
278        // @ts-ignore
279        if (bSdkSlice[property] > aSdkSlice[property]) {
280          return sliceSort === 2 ? 1 : -1;
281        } else {
282          // @ts-ignore
283          if (bSdkSlice[property] === aSdkSlice[property]) {
284            return 0;
285          } else {
286            return sliceSort === 2 ? -1 : 1;
287          }
288        }
289      };
290    }
291    //@ts-ignore
292    if (sliceDetail.key.indexOf('name') !== -1) {
293      //@ts-ignore
294      this.statDataArray.sort(compare(sliceDetail.key, sliceDetail.sort, 'string'));
295    } else {
296      //@ts-ignore
297      this.statDataArray.sort(compare(sliceDetail.key, sliceDetail.sort, 'number'));
298    } //@ts-ignore
299    this.tblSdkSlice!.recycleDataSource = this.statDataArray;
300  }
301
302  private getInnerTableName(showType: unknown): string {
303    //@ts-ignore
304    let inner = showType.inner;
305    if (inner !== null) {
306      return inner.tableName;
307    }
308    return '';
309  }
310
311  filterSliceItem(sliceItem: Array<SdkSliceSummary>, totalTime: number, sdkSliceVal: unknown): void {
312    this.tblSdkSlice!.innerHTML = '';
313    this.statDataArray = [];
314    if (sliceItem.length > 0) {
315      sliceItem.forEach((dataResult) => {
316        let keys = Object.keys(dataResult);
317        let values = Object.values(dataResult);
318        let sliceJsonText = '{';
319        keys.forEach((sliceKey, sliceKeyIndex) => {
320          this.keyList = [];
321          if (this.keyList.indexOf(sliceKey) <= -1) {
322            this.keyList.push(sliceKey);
323          }
324          let sliceValue = values[sliceKeyIndex];
325          sliceValue = this.getFormattedSliceValue(sliceKey, sliceValue);
326          sliceJsonText += `"${sliceKey}": "${sliceValue}"`;
327          if (sliceKeyIndex !== keys.length - 1) {
328            sliceJsonText += ',';
329          } else {
330            sliceJsonText += '}';
331          }
332        });
333        let sliceParseData = JSON.parse(sliceJsonText);
334        if (
335          sliceParseData.start_ts !== null &&
336          sliceParseData.end_ts !== null &&
337          sliceParseData.start_ts > sliceParseData.end_ts &&
338          sliceParseData.end_ts === 0
339        ) {
340          sliceParseData.end_ts = totalTime;
341        }
342        if (
343          this.isDateIntersection(
344            //@ts-ignore
345            sdkSliceVal.leftNs, //@ts-ignore
346            sdkSliceVal.rightNs,
347            sliceParseData.start_ts,
348            sliceParseData.end_ts
349          )
350        ) {
351          //@ts-ignore
352          this.statDataArray.push(sliceParseData);
353        }
354      }); //@ts-ignore
355      this.tblSdkSlice!.recycleDataSource = this.statDataArray;
356    } else {
357      this.tblSdkSlice!.recycleDataSource = [];
358    }
359  }
360
361  getFormattedSliceValue(sliceKey: string, sliceValue: unknown): unknown {
362    let result: string = '';
363    //@ts-ignore
364    switch (this.columnMap[sliceKey]) {
365      case 'TimeStamp':
366        result = Utils.getTimeString(Number(sliceValue));
367        break;
368      case 'ClockTime':
369        result = Utils.getTimeStampHMS(Number(sliceValue));
370        break;
371      case 'RangTime':
372        result = Utils.getDurString(Number(sliceValue));
373        break;
374      case 'PercentType':
375        result = `${sliceValue}%`;
376        break;
377      case 'CurrencyType': //@ts-ignore
378        result = sliceValue.toString().replace(/\B(?=(\d{3})+$)/g, ',');
379        break;
380      case 'FIXED': //@ts-ignore
381        result = sliceValue.toFixed(2);
382        break;
383      default:
384        if (typeof sliceValue === 'string') {
385          result = sliceValue.replace(/</gi, '&lt;').replace(/>/gi, '&gt;');
386          break;
387        }
388    }
389    return result;
390  }
391}
392