1/* 2 * Copyright (C) 2023 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 { SpSystemTrace } from '../SpSystemTrace'; 17import { TraceRow } from '../trace/base/TraceRow'; 18import { renders } from '../../database/ui-worker/ProcedureWorker'; 19import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; 20import { BaseStruct } from '../../bean/BaseStruct'; 21import { folderSupplier, rowThreadHandler } from './SpChartManager'; 22import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; 23import { TraceRowConfig } from '../trace/base/TraceRowConfig'; 24import { ProcessMemStruct } from '../../bean/ProcessMemStruct'; 25import { MemRender } from '../../database/ui-worker/ProcedureWorkerMem'; 26import { FuncRender, FuncStruct } from '../../database/ui-worker/ProcedureWorkerFunc'; 27import { ThreadRender } from '../../database/ui-worker/ProcedureWorkerThread'; 28import { promises } from 'dns'; 29const FOLD_HEIGHT = 24; 30export class SpImportUserPluginsChart { 31 private trace: SpSystemTrace; 32 static userPluginData: []; 33 private traceId?: string | undefined; 34 35 constructor(trace: SpSystemTrace) { 36 this.trace = trace; 37 } 38 39 async init(traceId?: string): Promise<void> { 40 this.traceId = traceId; 41 //@ts-ignore 42 let folderRow = this.createFolderRow(this.traceId); 43 folderRow.rowId = 'UserPluginsRows'; 44 folderRow.rowType = TraceRow.ROW_TYPE_IMPORT; 45 folderRow.name = 'UserPluginsRows'; 46 folderRow.selectChangeHandler = this.trace.selectChangeHandler; 47 this.trace.rowsEL?.appendChild(folderRow); 48 } 49 50 createFolderRow(traceId?: string): TraceRow<BaseStruct> { 51 let folder = TraceRow.skeleton<BaseStruct>(traceId); 52 folder.rowParentId = ''; 53 folder.folder = true; 54 folder.style.height = '40px'; 55 folder.rowHidden = folder.expansion; 56 folder.summaryProtoPid = []; 57 folder.setAttribute('children', ''); 58 folder.supplier = folderSupplier(); 59 folder.onThreadHandler = folderThreadHandler(folder, this.trace); 60 folder.addRowSampleUpload(); 61 this.addTraceRowEventListener(folder); 62 return folder; 63 } 64 65 /** 66 * 监听文件上传事件 67 * @param row 68 * @param start_ts 69 */ 70 addTraceRowEventListener(row: TraceRow<BaseStruct>): void { 71 row.uploadEl?.addEventListener('sample-file-change', (e: unknown) => { 72 this.getJsonData(e).then((res: unknown) => { 73 if (row.childrenList.length) { this.handleDynamicRowList(row); } 74 //@ts-ignore 75 if (res && res.data) { 76 let len = TraceRowConfig.allTraceRowList.length; 77 //@ts-ignore 78 res.data.forEach(item => { 79 //支持mem,thread, func 80 if (![TraceRow.ROW_TYPE_MEM, TraceRow.ROW_TYPE_THREAD, TraceRow.ROW_TYPE_FUNC].includes(item.rowType)) { 81 return; 82 } 83 for (let index = 0; index < len - 1; index++) { 84 const element = TraceRowConfig.allTraceRowList[index]; 85 if (element.rowType === item.rowType && element.name === item.threadName) { 86 //@ts-ignore 87 let parentRows = this.trace.shadowRoot?.querySelectorAll<TraceRow<unknown>>(`trace-row[row-id='${element.rowParentId}']`); 88 let childRow = TraceRow.skeleton<BaseStruct>(); 89 //@ts-ignore 90 childRow.rowId = element.rowId; 91 childRow.rowType = element.rowType; 92 childRow.protoParentId = parentRows?.[0].name; 93 childRow.protoPid = element.rowParentId!; 94 childRow.rowParentId = 'UserPluginsRows'; 95 childRow.rowHidden = element.rowHidden; 96 childRow.style.width = childRow.style.width; 97 childRow.style.height = element.style.height; 98 childRow.enableCollapseChart(FOLD_HEIGHT, this.trace); 99 //@ts-ignore 100 childRow.name = element.name; 101 childRow.setAttribute('children', ''); 102 childRow.needRefresh = true; 103 childRow.favoriteChangeHandler = element.favoriteChangeHandler; 104 childRow.selectChangeHandler = element.selectChangeHandler; 105 this.addDrawAttributes(item, childRow, element); 106 row.summaryProtoPid!.push(childRow.protoPid); 107 row.addChildTraceRow(childRow); 108 }; 109 }; 110 }); 111 row.expansion = true; 112 }; 113 this.trace.refreshCanvas(false); 114 }); 115 }); 116 } 117 //清空row-parent-id='UserPluginsRows'动态添加的子Row的list数据 118 handleDynamicRowList(row: TraceRow<BaseStruct>): void { 119 row.summaryProtoPid = []; 120 // 使用querySelectorAll找到所有row-parent-id='UserPluginsRows'的div元素 121 //@ts-ignore 122 let childRows: Array<TraceRow<unknown>> = [ 123 //@ts-ignore 124 ...this.trace.shadowRoot!.querySelectorAll<TraceRow<unknown>>(`trace-row[row-parent-id='UserPluginsRows']`), 125 ]; 126 // 遍历这些元素 127 childRows.forEach((div) => { 128 // 如果等于,则从父节点中删除该元素 129 if (div.parentNode) { 130 div.parentNode.removeChild(div); 131 } 132 }); 133 //删除上一次导入file添加的row 134 TraceRowConfig.allTraceRowList = TraceRowConfig.allTraceRowList.filter(item => item.rowParentId !== 'UserPluginsRows'); 135 row.expansion = false; 136 row.childrenList = []; 137 } 138 139 addDrawAttributes(item: { rowType: string, threadName: string }, childRow: TraceRow<BaseStruct>, element: unknown): void { 140 //@ts-ignore 141 if (element.supplier) { 142 //@ts-ignore 143 childRow.supplier = async (): Promise<unknown> => { 144 //@ts-ignore 145 let res = await element.supplier!(); 146 return res; 147 }; 148 //@ts-ignore 149 } else if (element.supplierFrame) { 150 //@ts-ignore 151 childRow.supplierFrame = async (): Promise<unknown> => { 152 //@ts-ignore 153 let res = await element.supplierFrame!(); 154 return res; 155 }; 156 } 157 if (item.rowType === TraceRow.ROW_TYPE_MEM) {//处理mem 158 childRow.findHoverStruct = (): void => { 159 //@ts-ignore 160 ProcessMemStruct.hoverProcessMemStruct = childRow.getHoverStruct(false); 161 }; 162 childRow.focusHandler = (): void => { 163 if (childRow.hoverY <= 5 || childRow.hoverY >= 35) { 164 ProcessMemStruct.hoverProcessMemStruct = undefined; 165 } 166 this.trace.displayTip( 167 childRow, 168 ProcessMemStruct.hoverProcessMemStruct, 169 `<span>${ProcessMemStruct.hoverProcessMemStruct?.value || '0'}</span>` 170 ); 171 }; 172 childRow.onThreadHandler = rowThreadHandler<MemRender>('mem', 'context', 173 //@ts-ignore 174 { type: `mem ${element.rowId} ${element.name}` }, childRow, this.trace); 175 } else if (item.rowType === TraceRow.ROW_TYPE_FUNC) { 176 //处理func 177 //@ts-ignore 178 if (element.asyncFuncName) { 179 //@ts-ignore 180 childRow.asyncFuncName = element.asyncFuncName; 181 //@ts-ignore 182 childRow.asyncFuncNamePID = element.asyncFuncNamePID; 183 //@ts-ignore 184 childRow.asyncFuncStartTID = element.asyncFuncStartTID; 185 } 186 //@ts-ignore 187 if (element.asyncFuncThreadName) { 188 //@ts-ignore 189 childRow.asyncFuncThreadName = element.asyncFuncThreadName; 190 //@ts-ignore 191 childRow.asyncFuncNamePID = element.asyncFuncNamePID; 192 } 193 childRow.findHoverStruct = (): void => { 194 //@ts-ignore 195 FuncStruct.hoverFuncStruct = childRow.getHoverStruct(); 196 }; 197 childRow.onThreadHandler = rowThreadHandler<FuncRender>('func', 'context', 198 //@ts-ignore 199 { type: '' }, childRow, this.trace); 200 } else if (item.rowType === TraceRow.ROW_TYPE_THREAD) { 201 //处理thread 202 childRow.onThreadHandler = rowThreadHandler<ThreadRender>('thread', 'context', 203 { type: '', translateY: childRow.translateY }, childRow, this.trace); 204 } 205 } 206 /** 207 * 获取上传的文件内容 转为json格式 208 * @param file 209 * @returns 210 */ 211 getJsonData(file: unknown): Promise<unknown> { 212 return new Promise((resolve, reject) => { 213 let reader = new FileReader(); 214 //@ts-ignore 215 reader.readAsText(file.detail || file); 216 reader.onloadend = (e: unknown): void => { 217 //@ts-ignore 218 const fileContent = e.target?.result; 219 try { 220 resolve(JSON.parse(fileContent)); 221 document.dispatchEvent( 222 new CustomEvent('file-correct') 223 ); 224 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 225 event: 'seach-row', 226 action: 'seach-row', 227 }); 228 } catch (error) { 229 document.dispatchEvent( 230 new CustomEvent('file-error') 231 ); 232 } 233 }; 234 }); 235 } 236} 237export const folderThreadHandler = (row: TraceRow<BaseStruct>, trace: SpSystemTrace) => { 238 return (useCache: boolean): void => { 239 row.canvasSave(trace.canvasPanelCtx!); 240 if (row.expansion) { 241 // @ts-ignore 242 trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); 243 } else { 244 (renders.empty as EmptyRender).renderMainThread( 245 { 246 context: trace.canvasPanelCtx, 247 useCache: useCache, 248 type: '', 249 }, 250 row 251 ); 252 } 253 row.canvasRestore(trace.canvasPanelCtx!, trace); 254 }; 255}; 256 257