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 {LitTable} from "../../../../../base-ui/table/lit-table.js"; 18import {SelectionData, SelectionParam} from "../../../../bean/BoxSelection.js"; 19import {getTabSdkCounterData, getTabSdkCounterLeftData, queryStartTime} from "../../../../database/SqlLite.js"; 20import "../../../SpFilter.js"; 21import {LitTableColumn} from "../../../../../base-ui/table/lit-table-column"; 22import {Utils} from "../../base/Utils.js"; 23import {SpSystemTrace} from "../../../SpSystemTrace.js"; 24 25@element('tabpane-sdk-counter') 26export class TabPaneSdkCounter extends BaseElement { 27 private tbl: LitTable | null | undefined; 28 private range: HTMLLabelElement | null | undefined; 29 private keyList: Array<string> | undefined; 30 private statDataArray: any = [] 31 private columnMap: any = {} 32 private sqlMap: any = {} 33 34 set data(val: SelectionParam | any) { 35 this.queryDataByDB(val) 36 } 37 38 initElements(): void { 39 this.tbl = this.shadowRoot?.querySelector<LitTable>('#tb-counter'); 40 this.range = this.shadowRoot?.querySelector('#time-range'); 41 this.tbl!.addEventListener('column-click', (evt) => { 42 // @ts-ignore 43 this.sortByColumn(evt.detail) 44 }); 45 } 46 47 connectedCallback() { 48 super.connectedCallback(); 49 new ResizeObserver((entries) => { 50 if (this.parentElement?.clientHeight != 0) { 51 // @ts-ignore 52 this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" 53 this.tbl?.reMeauseHeight() 54 } 55 }).observe(this.parentElement!); 56 } 57 58 queryDataByDB(val: SelectionParam | any) { 59 queryStartTime().then(res => { 60 let startTime = res[0].start_ts; 61 this.parseJson(SpSystemTrace.SDK_CONFIG_MAP); 62 let counters: Array<string> = [] 63 let componentId: number = 0 64 for (let index = 0; index < val.sdkCounterIds.length; index++) { 65 let values = val.sdkCounterIds[index].split("-") 66 let value = values[0]; 67 componentId = values[1]; 68 counters.push(value) 69 } 70 let sql = this.sqlMap.TabCounterLeftData 71 getTabSdkCounterLeftData(sql, val.leftNs + startTime, counters, componentId).then(res => { 72 let leftTime = res[res.length - 1].max_value - startTime 73 let sql = this.sqlMap.TabCounterData 74 getTabSdkCounterData(sql, startTime, leftTime, val.rightNs, counters, componentId).then(item => { 75 this.keyList = []; 76 this.tbl!.innerHTML = '' 77 this.statDataArray = [] 78 if (item.length != null && item.length > 0) { 79 for (let index = 0; index < item.length; index++) { 80 const dataResult = item[index]; 81 let keys = Object.keys(dataResult); 82 let values = Object.values(dataResult); 83 let jsonText = '{'; 84 for (let keyIndex = 0; keyIndex < keys.length; keyIndex++) { 85 let key = keys[keyIndex]; 86 if (this.keyList.indexOf(key) <= -1) { 87 this.keyList.push(key) 88 } 89 let value = values[keyIndex]; 90 if (this.columnMap[key] == 'TimeStamp') { 91 value = Utils.getTimeString(Number(value)) 92 } else if (this.columnMap[key] == 'ClockTime') { 93 value = Utils.getTimeStampHMS(Number(value)) 94 } else if (this.columnMap[key] == 'RangTime') { 95 value = Utils.getDurString(Number(value)) 96 } else if (this.columnMap[key] == 'PercentType') { 97 value = value + "%" 98 } else if (this.columnMap[key] == 'CurrencyType') { 99 // @ts-ignore 100 value = value.toString().replace(/\B(?=(\d{3})+$)/g, ",") 101 } 102 if (typeof value == "string") { 103 value = value.replace(/</gi, "<").replace(/>/gi, ">") 104 } 105 jsonText += '"' + key + '"' + ': ' + '"' + value + '"'; 106 if (keyIndex != keys.length - 1) { 107 jsonText += ',' 108 } else { 109 jsonText += '}'; 110 } 111 } 112 this.statDataArray.push(JSON.parse(jsonText)) 113 } 114 this.tbl!.recycleDataSource = this.statDataArray; 115 } else { 116 this.tbl!.recycleDataSource = []; 117 } 118 this.initDataElement() 119 120 setTimeout(() => { 121 this.tbl!.recycleDataSource = this.statDataArray; 122 new ResizeObserver(() => { 123 if (this.parentElement?.clientHeight != 0) { 124 this.tbl!.style.height = '100%' 125 this.tbl!.reMeauseHeight() 126 } 127 }).observe(this.parentElement!) 128 }, 200) 129 }) 130 131 }) 132 }); 133 } 134 135 parseJson(map: Map<number, string>): string { 136 let tablesMap = new Map(); 137 let keys = map.keys(); 138 for (let key of keys) { 139 let configStr = map.get(key); 140 if (configStr != undefined) { 141 let json = JSON.parse(configStr); 142 let tableConfig = json.tableConfig 143 if (tableConfig != null) { 144 let showTypes = tableConfig.showType; 145 for (let i = 0; i < showTypes.length; i++) { 146 let showType = showTypes[i]; 147 let type = this.getTableType(showType); 148 if (type == "counter") { 149 let selectSql = "select "; 150 for (let j = 0; j < showType.columns.length; j++) { 151 this.columnMap[showType.columns[j].column] = showType.columns[j].displayName 152 if (showType.columns[j].showType.indexOf(3) > -1) { 153 selectSql += showType.columns[j].column + "," 154 } 155 } 156 let leftSql = "select max(ts) as max_value,counter_id from " + showType.tableName + " where ts <= $leftNs and counter_id in" + 157 " ($counters) group by counter_id order by max_value desc"; 158 this.sqlMap["TabCounterData"] = selectSql.substring(0, selectSql.length - 1) + " from " + showType.tableName + 159 " where counter_id in ($counters) and (ts - $startTime) between $leftNs and $rightNs"; 160 this.sqlMap["TabCounterLeftData"] = leftSql 161 } 162 } 163 } 164 } 165 } 166 return ""; 167 } 168 169 private getTableType(showType: any) { 170 let columns = showType.columns; 171 for (let i = 0; i < columns.length; i++) { 172 let column = columns[i]; 173 let showType = column.showType 174 if (showType != null) { 175 if (showType.indexOf(1) != -1) { 176 return "counter" 177 } 178 if (showType.indexOf(2) != -1) { 179 return "slice" 180 } 181 } 182 } 183 return "" 184 } 185 186 initDataElement() { 187 if (this.keyList) { 188 this.keyList.forEach((item) => { 189 let htmlElement = document.createElement('lit-table-column') as LitTableColumn; 190 htmlElement.setAttribute('title', item); 191 htmlElement.setAttribute('data-index', item); 192 htmlElement.setAttribute('key', item); 193 htmlElement.setAttribute('align', 'flex-start'); 194 htmlElement.setAttribute("width", "1fr"); 195 htmlElement.setAttribute("order", ""); 196 this.tbl!.appendChild(htmlElement); 197 }) 198 } 199 } 200 201 initHtml(): string { 202 return ` 203<style> 204:host{ 205 display: flex; 206 flex-direction: column; 207 padding: 10px 10px; 208} 209</style> 210<div style="display: flex;height: 20px;align-items: center;flex-direction: row;margin-bottom: 5px"> 211 <stack-bar id="stack-bar" style="flex: 1"></stack-bar> 212 <label id="time-range" style="width: auto;text-align: end;font-size: 10pt;">Selected range:0.0 ms</label> 213 </div> 214<lit-table id="tb-counter" style="height: auto"> 215</lit-table> 216 `; 217 } 218 219 sortByColumn(detail: any) { 220 // @ts-ignore 221 function compare(property, sort) { 222 return function (a: SelectionData, b: SelectionData) { 223 if (a.process == " " || b.process == " ") { 224 return 0; 225 } 226 // @ts-ignore 227 if (b[property] > a[property]) { 228 return sort === 2 ? 1 : -1; 229 } else { // @ts-ignore 230 if (b[property] == a[property]) { 231 return 0; 232 } else { 233 return sort === 2 ? -1 : 1; 234 } 235 } 236 } 237 } 238 239 // @ts-ignore 240 this.statDataArray.sort(compare(detail.key, detail.sort)) 241 this.tbl!.recycleDataSource = this.statDataArray; 242 } 243}