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 { type LitTabs } from '../../../../base-ui/tabs/lit-tabs'; 18import { LitTabpane } from '../../../../base-ui/tabs/lit-tabpane'; 19import { BoxJumpParam, SelectionParam, SliceBoxJumpParam } from '../../../bean/BoxSelection'; 20import { type TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection'; 21import { type TabPaneFlag } from '../timer-shaft/TabPaneFlag'; 22import { type Flag } from '../timer-shaft/Flag'; 23import { type WakeupBean } from '../../../bean/WakeupBean'; 24import { type LitIcon } from '../../../../base-ui/icon/LitIcon'; 25import { tabConfig } from './TraceSheetConfig'; 26import { type TabPaneBoxChild } from '../sheet/cpu/TabPaneBoxChild'; 27import { type CpuStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCPU'; 28import { CpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerFreq'; 29import { CpuFreqLimitsStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; 30import { type ThreadStruct } from '../../../database/ui-worker/ProcedureWorkerThread'; 31import { type FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc'; 32import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem'; 33import { CpuStateStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuState'; 34import { type HangStruct } from '../../../database/ui-worker/ProcedureWorkerHang'; 35import { type ClockStruct } from '../../../database/ui-worker/ProcedureWorkerClock'; 36import { type DmaFenceStruct } from '../../../database/ui-worker/ProcedureWorkerDmaFence'; 37import { type IrqStruct } from '../../../database/ui-worker/ProcedureWorkerIrq'; 38import { type JankStruct } from '../../../database/ui-worker/ProcedureWorkerJank'; 39import { type HeapStruct } from '../../../database/ui-worker/ProcedureWorkerHeap'; 40import { type LitTable } from '../../../../base-ui/table/lit-table'; 41import { threadPool } from '../../../database/SqlLite'; 42import { type HeapSnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerHeapSnapshot'; 43import { type TabPaneNMStatisticAnalysis } from '../sheet/native-memory/TabPaneNMStatisticAnalysis'; 44import { type TabPaneCurrent } from '../sheet/TabPaneCurrent'; 45import { type SlicesTime } from '../timer-shaft/SportRuler'; 46import { type AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup'; 47import { type AllAppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAllAppStartup'; 48import { type SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit'; 49import { type FrameAnimationStruct } from '../../../database/ui-worker/ProcedureWorkerFrameAnimation'; 50import { type TraceRow } from './TraceRow'; 51import { type FrameDynamicStruct } from '../../../database/ui-worker/ProcedureWorkerFrameDynamic'; 52import { type TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic'; 53import { type FrameSpacingStruct } from '../../../database/ui-worker/ProcedureWorkerFrameSpacing'; 54import { type TabFrameSpacing } from '../sheet/frame/TabFrameSpacing'; 55import { type JsCpuProfilerChartFrame } from '../../../bean/JsStruct'; 56import { type TabPaneComparison } from '../sheet/ark-ts/TabPaneComparison'; 57import { type TabPaneSummary } from '../sheet/ark-ts/TabPaneSummary'; 58import { type TabPaneGpuClickSelect } from '../sheet/gpu/TabPaneGpuClickSelect'; 59import { type TabPanePurgTotalSelection } from '../sheet/ability/TabPanePurgTotalSelection'; 60import { type TabPanePurgPinSelection } from '../sheet/ability/TabPanePurgPinSelection'; 61import { type TabPaneVmTrackerShmSelection } from '../sheet/vmtracker/TabPaneVmTrackerShmSelection'; 62import { type TabPaneSmapsStatistics } from '../sheet/smaps/TabPaneSmapsStatistics'; 63import { type TabPaneSmapsComparison } from '../sheet/smaps/TabPaneSmapsComparison'; 64import { type SnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerSnapshot'; 65import { type TabPaneDmaSelectAbility } from '../sheet/ability/TabPaneDmaSelectAbility'; 66import { type TabPaneGpuMemorySelectAbility } from '../sheet/ability/TabPaneGpuMemorySelectAbility'; 67import { type TabPaneDmaSelectVmTracker } from '../sheet/vmtracker/TabPaneDmaSelectVmTracker'; 68import { type TabPanePurgTotalComparisonAbility } from '../sheet/ability/TabPanePurgTotalComparisonAbility'; 69import { type TabPanePurgPinComparisonAbility } from '../sheet/ability/TabPanePurgPinComparisonAbility'; 70import { type TabPanePurgTotalComparisonVM } from '../sheet/vmtracker/TabPanePurgTotalComparisonVM'; 71import { type TabPanePurgPinComparisonVM } from '../sheet/vmtracker/TabPanePurgPinComparisonVM'; 72import { type TabPaneDmaAbilityComparison } from '../sheet/ability/TabPaneDmaAbilityComparison'; 73import { type TabPaneGpuMemoryComparison } from '../sheet/ability/TabPaneGpuMemoryComparison'; 74import { type TabPaneDmaVmTrackerComparison } from '../sheet/vmtracker/TabPaneDmaVmTrackerComparison'; 75import { type TabPaneGpuMemorySelectVmTracker } from '../sheet/vmtracker/TabPaneGpuMemorySelectVmTracker'; 76import { type TabPaneGpuMemoryVmTrackerComparison } from '../sheet/vmtracker/TabPaneGpuMemoryVmTrackerComparison'; 77import { type TabPaneVmTrackerShmComparison } from '../sheet/vmtracker/TabPaneVmTrackerShmComparison'; 78import { type TabPaneJsCpuStatistics } from '../sheet/ark-ts/TabPaneJsCpuStatistics'; 79import { type TabPaneGpuClickSelectComparison } from '../sheet/gpu/TabPaneGpuClickSelectComparison'; 80import { Utils } from './Utils'; 81import { TabPaneHiLogs } from '../sheet/hilog/TabPaneHiLogs'; 82import { TabPaneGpuResourceVmTracker } from '../sheet/vmtracker/TabPaneGpuResourceVmTracker'; 83import { type LitPageTable } from '../../../../base-ui/table/LitPageTable'; 84import '../../../../base-ui/popover/LitPopoverV'; 85import { LitPopover } from '../../../../base-ui/popover/LitPopoverV'; 86import { LitTree, TreeItemData } from '../../../../base-ui/tree/LitTree'; 87import { SampleStruct } from '../../../database/ui-worker/ProcedureWorkerBpftrace'; 88import { TabPaneUserPlugin } from '../sheet/userPlugin/TabPaneUserPlugin'; 89import { TabPaneSampleInstruction } from '../sheet/bpftrace/TabPaneSampleInstruction'; 90import { TabPaneFreqStatesDataCut } from '../sheet/states/TabPaneFreqStatesDataCut'; 91import { TabPaneDataCut } from '../sheet/TabPaneDataCut'; 92import { SpSystemTrace } from '../../SpSystemTrace'; 93import { PerfToolStruct } from '../../../database/ui-worker/ProcedureWorkerPerfTool'; 94import { GpuCounterStruct } from '../../../database/ui-worker/ProcedureWorkerGpuCounter'; 95import { TabPaneGpuCounter } from '../sheet/gpu-counter/TabPaneGpuCounter'; 96import { TabPaneSliceChild } from '../sheet/process/TabPaneSliceChild'; 97 98@element('trace-sheet') 99export class TraceSheet extends BaseElement { 100 systemLogFlag: Flag | undefined | null; 101 private litTabs: LitTabs | undefined | null; 102 private switchDiv: LitPopover | undefined | null; 103 private processTree: LitTree | undefined | null; 104 private importDiv: HTMLDivElement | undefined | null; 105 private exportBt: LitIcon | undefined | null; 106 private nav: HTMLDivElement | undefined | null; 107 private tabs: HTMLDivElement | undefined | null; 108 private navRoot: HTMLDivElement | null | undefined; 109 private search: HTMLDivElement | undefined | null; 110 private timerShaft: HTMLDivElement | undefined | null; 111 private spacer: HTMLDivElement | undefined | null; 112 private rowsPaneEL: HTMLDivElement | undefined | null; 113 private selection: SelectionParam | undefined | null; 114 private currentPaneID: string = 'current-selection'; 115 private fragment: DocumentFragment | undefined; 116 private lastSelectIPid: number = -1; 117 private lastProcessSet: Set<number> = new Set<number>(); 118 private optionsDiv: LitPopover | undefined | null; 119 private optionsSettingTree: LitTree | undefined | null; 120 private tabPaneHeight: string = ''; 121 122 static get observedAttributes(): string[] { 123 return ['mode']; 124 } 125 126 buildTabs(litTabs: LitTabs | undefined | null): void { 127 this.fragment = document.createDocumentFragment(); // @ts-ignore 128 Reflect.ownKeys(tabConfig).forEach((key, index): void => { 129 let pane = new LitTabpane(); 130 pane.id = key.toString(); 131 pane.className = 'tabHeight'; // @ts-ignore 132 pane.tab = tabConfig[key].title; 133 pane.hidden = true; // @ts-ignore 134 pane.key = `${tabConfig[key].key || index}`; // @ts-ignore 135 let cls = tabConfig[key].type; 136 // @ts-ignore 137 let node = new cls(); 138 pane.append(node); 139 this.fragment?.appendChild(pane); 140 }); 141 litTabs!.appendChild(this.fragment); 142 } 143 144 displayTab<T>(...names: string[]): T { 145 this.setMode('max'); 146 if (names.includes('box-flag') || names.includes('tabpane-current')) { 147 this.showUploadSoBt(this.selection); 148 this.showSwitchProcessBt(this.selection); 149 } else { 150 this.showOptionsBt(null); 151 this.showUploadSoBt(null); 152 this.showSwitchProcessBt(null); 153 } 154 this.shadowRoot 155 ?.querySelectorAll<LitTabpane>('#tabs lit-tabpane') 156 .forEach((it) => (it.hidden = !names.some((k) => k === it.id))); 157 let litTabpane = this.shadowRoot?.querySelector<LitTabpane>(`#tabs lit-tabpane[id='${names[0]}']`); 158 if (names[0] === 'current-selection') { 159 this.exportBt!.style.display = 'none'; 160 } else { 161 this.exportBt!.style.display = 'flex'; 162 } 163 this.shadowRoot?.querySelector<LitTabs>('#tabs')?.activePane(litTabpane!.key); 164 return litTabpane!.children.item(0) as unknown as T; 165 } 166 167 getComponentByID<T>(id: string): T { 168 return this.getPaneByID(id)?.children.item(0) as unknown as T; 169 } 170 171 getPaneByID(id: string): LitTabpane { 172 return this.shadowRoot!.querySelector(`#${id}`)!; 173 } 174 175 initElements(): void { 176 this.litTabs = this.shadowRoot?.querySelector('#tabs'); 177 this.litTabs!.addEventListener('contextmenu', (e): void => { 178 e.preventDefault(); 179 }); 180 this.importDiv = this.shadowRoot?.querySelector('#import_div'); 181 this.switchDiv = this.shadowRoot?.querySelector('#select-process'); 182 this.processTree = this.shadowRoot?.querySelector('#processTree'); 183 this.optionsDiv = this.shadowRoot?.querySelector('#options'); 184 this.optionsSettingTree = this.shadowRoot?.querySelector('#optionsSettingTree'); 185 this.optionsSettingTree!.onChange = (e: unknown): void => { 186 const select = this.optionsSettingTree!.getCheckdKeys(); 187 document.dispatchEvent( 188 new CustomEvent('sample-popver-change', { 189 detail: { 190 select: select[0], 191 }, 192 }) 193 ); 194 }; 195 this.processTree!.onChange = (e: unknown): void => { 196 const select = this.processTree!.getCheckdKeys(); 197 const selectIPid = Number(select[0]); 198 this.switchDiv!.visible = 'false'; 199 this.updateRangeSelect(selectIPid); 200 this.lastSelectIPid = selectIPid; 201 }; 202 this.buildTabs(this.litTabs); // @ts-ignore 203 this.litTabs!.onTabClick = (e: unknown): void => this.loadTabPaneData(e.detail.key); 204 this.tableCloseHandler(); 205 this.rowClickEvent(); 206 this.tdClickEvent(); 207 } 208 private rowClickEvent(): void { 209 // @ts-ignore 210 this.getComponentByID<unknown>('box-perf-analysis')?.addEventListener('row-click', (evt: MouseEvent) => { 211 this.perfAnalysisListener(evt); 212 }); 213 // @ts-ignore 214 this.getComponentByID<unknown>('box-native-statistic-analysis')?.addEventListener('row-click', (e: MouseEvent) => { 215 this.nativeAnalysisListener(e); 216 }); 217 // @ts-ignore 218 this.getComponentByID<unknown>('box-io-tier-statistics-analysis')?.addEventListener('row-click', (evt: MouseEvent) => { 219 // @ts-ignore 220 if (evt.detail.button === 2 && evt.detail.tableName) { 221 let pane = this.getPaneByID('box-io-calltree'); 222 this.litTabs!.activeByKey(pane.key); 223 } 224 }); 225 // @ts-ignore 226 this.getComponentByID<unknown>('box-virtual-memory-statistics-analysis')?.addEventListener( 227 'row-click', 228 (evt: MouseEvent) => { 229 // @ts-ignore 230 if (evt.detail.button === 2 && evt.detail.tableName) { 231 let pane = this.getPaneByID('box-vm-calltree'); 232 this.litTabs!.activeByKey(pane.key); 233 } 234 } 235 ); 236 // @ts-ignore 237 this.getComponentByID<unknown>('box-file-system-statistics-analysis')?.addEventListener( 238 'row-click', 239 (evt: MouseEvent) => { 240 // @ts-ignore 241 if (evt.detail.button === 2 && evt.detail.tableName) { 242 let pane = this.getPaneByID('box-file-system-calltree'); 243 this.litTabs!.activeByKey(pane.key); 244 } 245 } 246 ); 247 // @ts-ignore 248 this.getComponentByID<unknown>('box-native-statstics')?.addEventListener('row-click', (e: unknown) => { 249 this.nativeStatsticsListener(e); 250 }); 251 // @ts-ignore 252 this.getComponentByID<unknown>('box-virtual-memory-statistics')?.addEventListener('row-click', (e: unknown) => { 253 this.virtualMemoryListener(e); 254 }); 255 // @ts-ignore 256 this.getComponentByID<unknown>('box-io-tier-statistics')?.addEventListener('row-click', (e: unknown) => { 257 this.ioTierListener(e); 258 }); 259 // @ts-ignore 260 this.getComponentByID<unknown>('box-file-system-statistics')?.addEventListener('row-click', (e: unknown) => { 261 this.fileSystemListener(e); 262 }); 263 } 264 265 private tdClickEvent(): void { 266 // @ts-ignore 267 this.getComponentByID<unknown>('box-spt')?.addEventListener('td-click', (evt: unknown) => { 268 this.tdClickHandler(evt); 269 }); 270 // @ts-ignore 271 this.getComponentByID<unknown>('box-pts')?.addEventListener('td-click', (evt: unknown) => { 272 this.tdClickHandler(evt); 273 }); 274 // @ts-ignore 275 this.getComponentByID<unknown>('box-thread-states')?.addEventListener('td-click', (evt: unknown) => { 276 this.tdClickHandler(evt); 277 }); 278 // @ts-ignore 279 this.getComponentByID<unknown>('box-slices')?.addEventListener('td-click', (evt: unknown) => { 280 this.tdSliceClickHandler(evt); 281 }); 282 } 283 284 private perfAnalysisListener(evt: MouseEvent): void { 285 // @ts-ignore 286 if (evt.detail.button === 2 && evt.detail.pid) { 287 let pane = this.getPaneByID('box-perf-profile'); 288 this.litTabs!.activeByKey(pane.key); 289 } 290 } 291 292 private nativeAnalysisListener(e: MouseEvent): void { 293 //@ts-ignore 294 if (e.detail.button === 2 && e.detail.tableName) { 295 let pane = this.getPaneByID('box-native-calltree'); 296 pane.hidden = false; 297 this.litTabs!.activeByKey(pane.key); 298 } 299 } 300 301 private nativeStatsticsListener(e: unknown): void { 302 // @ts-ignore 303 if (e.detail.button === 0) { 304 // @ts-ignore 305 this.selection!.statisticsSelectData = e.detail; 306 let pane = this.getPaneByID('box-native-memory'); 307 this.litTabs?.activeByKey(pane.key); 308 // @ts-ignore 309 (pane.children.item(0) as unknown)!.fromStastics(this.selection); 310 } 311 } 312 313 private virtualMemoryListener(e: unknown): void { 314 // @ts-ignore 315 if (e.detail.button === 0) { 316 // @ts-ignore 317 this.selection!.fileSystemVMData = { path: e.detail.path }; 318 let pane = this.getPaneByID('box-vm-events'); 319 this.litTabs?.activeByKey(pane.key); 320 // @ts-ignore 321 if (e.detail.path) { 322 // @ts-ignore 323 (pane.children.item(0) as unknown)!.fromStastics(this.selection); 324 } 325 } 326 } 327 328 private ioTierListener(e: unknown): void { 329 // @ts-ignore 330 if (e.detail.button === 0) { 331 // @ts-ignore 332 this.selection!.fileSystemIoData = { path: e.detail.path }; 333 let pane = this.getPaneByID('box-io-events'); 334 this.litTabs?.activeByKey(pane.key); 335 // @ts-ignore 336 if (e.detail.path) { 337 // @ts-ignore 338 (pane.children.item(0) as unknown)!.fromStastics(this.selection); 339 } 340 } 341 } 342 343 private fileSystemListener(e: unknown): void { 344 // @ts-ignore 345 if (e.detail.button === 0) { 346 // @ts-ignore 347 this.selection!.fileSystemFsData = e.detail.data; 348 let pane = this.getPaneByID('box-file-system-event'); 349 this.litTabs?.activeByKey(pane.key); 350 // @ts-ignore 351 if (e.detail.data) { 352 // @ts-ignore 353 (pane.children.item(0) as unknown)!.fromStastics(this.selection); 354 } 355 } 356 } 357 358 private tableCloseHandler(): void { 359 this.litTabs!.addEventListener('close-handler', () => { 360 // @ts-ignore 361 Reflect.ownKeys(tabConfig) 362 .reverse() 363 .forEach((id) => { 364 // @ts-ignore 365 let element = tabConfig[id]; 366 let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`); 367 if (element.require) { 368 pane!.hidden = !element.require(this.selection!); 369 } else { 370 pane!.hidden = true; 371 } 372 }); 373 this.litTabs?.activeByKey(`${this.getPaneByID(this.currentPaneID).key}`); 374 }); 375 } 376 377 connectedCallback(): void { 378 this.nav = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.tab-nav-vessel'); 379 this.tabs = this.shadowRoot?.querySelector('#tabs'); 380 this.navRoot = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.nav-root'); 381 this.search = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('div > div.search-vessel'); 382 this.timerShaft = this.parentElement?.querySelector('.timer-shaft'); 383 this.spacer = this.parentElement?.querySelector('.spacer'); 384 this.rowsPaneEL = this.parentElement?.querySelector('.rows-pane'); 385 let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#max-btn'); 386 let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#min-btn'); 387 let borderTop: number = 1; 388 let initialHeight = { tabs: 'calc(30vh + 39px)', node: '30vh' }; 389 this.initNavElements(tabsPackUp!, borderTop, initialHeight); 390 this.exportBt = this.shadowRoot?.querySelector<LitIcon>('#export-btn'); 391 tabsOpenUp!.onclick = (): void => { 392 this.tabs!.style.height = `${window.innerHeight - this.search!.offsetHeight - this.timerShaft!.offsetHeight - borderTop 393 }px`; 394 let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = 395 this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane'); 396 litTabpane!.forEach((node: HTMLDivElement): void => { 397 node!.style.height = `${window.innerHeight - 398 this.search!.offsetHeight - 399 this.timerShaft!.offsetHeight - 400 this.navRoot!.offsetHeight - 401 borderTop 402 }px`; 403 initialHeight.node = node!.style.height; 404 }); 405 initialHeight.tabs = this.tabs!.style.height; 406 tabsPackUp!.name = 'down'; 407 }; 408 tabsPackUp!.onclick = (): void => { 409 let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = 410 this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane'); 411 if (tabsPackUp!.name === 'down') { 412 let beforeHeight = this.clientHeight; 413 this.tabs!.style.height = `${this.navRoot!.offsetHeight}px`; 414 window.publish(window.SmartEvent.UI.ShowBottomTab, { show: 2, delta: beforeHeight - this.clientHeight }); 415 litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = '0px')); 416 tabsPackUp!.name = 'up'; 417 tabsPackUp!.title = 'Reset Tab'; // @ts-ignore 418 (window as unknown).isPackUpTable = true; 419 } else { 420 tabsPackUp!.name = 'down'; 421 tabsPackUp!.title = 'Minimize Tab'; 422 this.tabs!.style.height = initialHeight.tabs; 423 litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = initialHeight.node)); 424 } 425 }; 426 this.importClickEvent(); 427 this.exportClickEvent(); 428 } 429 430 private initNavElements(tabsPackUp: LitIcon, borderTop: number, initialHeight: { node: string; tabs: string }): void { 431 let that = this; 432 // 节点挂载时给Tab面板绑定鼠标按下事件 433 this.nav!.onmousedown = (event): void => { 434 if (SpSystemTrace.isKeyUp === false) { 435 return; 436 } 437 // @ts-ignore 438 (window as unknown).isSheetMove = true; 439 // 获取所有标签页的节点数组 440 let litTabpane: NodeListOf<HTMLDivElement> | undefined | null = 441 this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane'); 442 // 获取当前选中面板的key值,后续用来确定当前面板是哪一个。 对于用户来说,直观看到的只有当前面板,其他面板可以在拖动完成后一次性设置好新的高度 443 // @ts-ignore 444 let litTabNavKey: string = this.nav!.querySelector('.nav-item[data-selected=true]').dataset.key; 445 let currentPane: HTMLDivElement = this.shadowRoot?.querySelector(`#tabs > lit-tabpane[key="${litTabNavKey}"]`)!; 446 // 原函数 绑定鼠标移动事件,动态获取鼠标位置信息 447 this.navMouseMove(event, currentPane!, that, tabsPackUp, borderTop); 448 document.onmouseup = function (): void { 449 setTimeout(() => { 450 // @ts-ignore 451 (window as unknown).isSheetMove = false; 452 }, 100); 453 litTabpane!.forEach((node: HTMLDivElement): void => { 454 node!.style.height = that.tabPaneHeight; 455 }); 456 if (that.tabPaneHeight !== '0px' && that.tabs!.style.height !== '') { 457 // 每次都会重新记录上次拖动完成后的面板高度,下次重新显示tab页时,会以上次拖动后的高度显示 458 initialHeight.node = that.tabPaneHeight; 459 initialHeight.tabs = that.tabs!.style.height; 460 } 461 // 将绑定的事件置空,需要时重新绑定 462 this.onmousemove = null; 463 this.onmouseup = null; 464 }; 465 }; 466 } 467 468 private navMouseMove( 469 event: MouseEvent, 470 litTabpane: HTMLDivElement, 471 that: this, 472 tabsPackUp: LitIcon, 473 borderTop: number 474 ): void { 475 // 鼠标移动前记录此时的鼠标位置信息,后续根据新值与前次值作比对 476 let preY = event.pageY; 477 // 获取此时tab组件的偏移高度 需要包含水平滚动条的高度等 478 let preHeight = this.tabs!.offsetHeight; 479 // 获取此时整个滚动区域高度 480 let scrollH = that.rowsPaneEL!.scrollHeight; 481 // 获取此时滚动区域上方被隐藏的高度 482 let scrollT = that.rowsPaneEL!.scrollTop; 483 // 获取当前内容区高度加上上下内边距高度,即面板组件高度 484 let ch = that.clientHeight; 485 // 鼠标移动事件 486 document.onmousemove = function (event): void { 487 // 移动前的面板高度 - 移动前后鼠标的坐标差值 = 新的面板高度 488 let newHeight: number = preHeight - (event.pageY - preY); 489 // that指向的是tracesheet节点 spacer为垫片 rowsPaneEl为泳道 tabs为tab页组件 490 // litTabpane为当前面板 navRoot为面板头部区的父级容器 search为顶部搜索区整个区域 491 // 这四个判断条件中,第一个尚未找到触发条件 后续和润和确认是否会触发 492 if (that.spacer!.offsetHeight > that.rowsPaneEL!.offsetHeight) { 493 that.tabs!.style.height = `${newHeight}px`; 494 litTabpane!.style.height = `${newHeight - that.navRoot!.offsetHeight}px`; 495 // 设置右上角面板大小化的箭头样式,面板在移动到最底部时,箭头向上,其余情况箭头向下 496 tabsPackUp!.name = 'down'; 497 } else if ( 498 // 只要没有移动到边界区域都会进入该条件 499 that.navRoot!.offsetHeight <= newHeight && 500 that.search!.offsetHeight + that.timerShaft!.offsetHeight + borderTop + that.spacer!.offsetHeight <= 501 window.innerHeight - newHeight 502 ) { 503 that.tabs!.style.height = `${newHeight}px`; 504 litTabpane!.style.height = `${newHeight - that.navRoot!.offsetHeight}px`; 505 tabsPackUp!.name = 'down'; 506 } else if (that.navRoot!.offsetHeight >= newHeight) { 507 // 该条件在面板置底时触发 508 that.tabs!.style.height = `${that.navRoot!.offsetHeight}px`; 509 litTabpane!.style.height = '0px'; 510 tabsPackUp!.name = 'up'; 511 } else if ( 512 that.search!.offsetHeight + that.timerShaft!.offsetHeight + borderTop + that.spacer!.offsetHeight >= 513 window.innerHeight - newHeight 514 ) { 515 // 该条件在面板高度置顶时触发 516 that.tabs!.style.height = `${window.innerHeight - 517 that.search!.offsetHeight - 518 that.timerShaft!.offsetHeight - 519 borderTop - 520 that.spacer!.offsetHeight 521 }px`; 522 litTabpane!.style.height = `${window.innerHeight - 523 that.search!.offsetHeight - 524 that.timerShaft!.offsetHeight - 525 that.navRoot!.offsetHeight - 526 borderTop - 527 that.spacer!.offsetHeight 528 }px`; 529 tabsPackUp!.name = 'down'; 530 } 531 that.tabPaneHeight = litTabpane!.style.height; 532 let currentSH = that.rowsPaneEL!.scrollHeight; 533 // 第一个判断条件尚未确定如何触发,currentSH与scrollH始终相等 534 if (currentSH > scrollH && currentSH > that.rowsPaneEL!.scrollTop + that.clientHeight) { 535 that.rowsPaneEL!.scrollTop = scrollT - (ch - that.clientHeight); 536 } 537 }; 538 } 539 540 private importClickEvent(): void { 541 let importFileBt: HTMLInputElement | undefined | null = 542 this.shadowRoot?.querySelector<HTMLInputElement>('#import-file'); 543 importFileBt!.addEventListener('change', (event): void => { 544 let files = importFileBt?.files; 545 if (files) { 546 let fileList: Array<File> = []; 547 for (let file of files) { 548 if (file.name.endsWith('.so')) { 549 fileList.push(file); 550 } 551 } 552 if (fileList.length > 0) { 553 importFileBt!.disabled = true; 554 window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' }); 555 threadPool.submit( 556 'upload-so', 557 '', 558 fileList, 559 (res: unknown) => { 560 importFileBt!.disabled = false; // @ts-ignore 561 if (res.result === 'ok') { 562 window.publish(window.SmartEvent.UI.UploadSOFile, {}); 563 } else { 564 // @ts-ignore 565 const failedList = res.failedArray.join(','); 566 window.publish(window.SmartEvent.UI.Error, `parse so file ${failedList} failed!`); 567 } 568 }, 569 'upload-so' 570 ); 571 } 572 fileList.length = 0; 573 } 574 importFileBt!.files = null; 575 importFileBt!.value = ''; 576 }); 577 } 578 579 private exportClickEvent(): void { 580 this.exportBt!.onclick = (): void => { 581 let currentTab = this.getTabpaneByKey(this.litTabs?.activekey!); 582 if (currentTab) { 583 let table1 = Array.from( 584 (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitPageTable>('lit-page-table') || [] 585 ); 586 let table2 = Array.from( 587 (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || [] 588 ); 589 let tables = [...table1, ...table2]; 590 591 for (let table of tables) { 592 if (!table.hasAttribute('hideDownload')) { 593 table.exportData(); 594 } 595 } 596 } 597 }; 598 } 599 600 getTabpaneByKey(key: string): LitTabpane | undefined { 601 let tabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []); 602 return tabs.find((it) => it.key === key); 603 } 604 605 initHtml(): string { 606 return ` 607 <style> 608 :host([mode='hidden']){ 609 display: none; 610 } 611 :host{ 612 display: block; 613 background-color: rebeccapurple; 614 } 615 .tabHeight{ 616 height: 30vh; 617 background-color: var(--dark-background,#FFFFFF); 618 } 619 #check-popover[visible="true"] #check-des{ 620 color: #0A59F7; 621 } 622 .popover{ 623 color: var(--dark-color1,#4b5766); 624 justify-content: center; 625 align-items: center; 626 margin-right: 10px; 627 z-index: 2; 628 } 629 .option { 630 display: flex; 631 margin-right: 10px; 632 cursor: pointer; 633 } 634 </style> 635 <div id="vessel" style="border-top: 1px solid var(--dark-border1,#D5D5D5);"> 636 <lit-tabs id="tabs" position="top-left" activekey="1" mode="card" > 637 <div class="option" slot="options"> 638 <lit-popover placement="bottom" class="popover" haveRadio="true" trigger="click" id="options"> 639 <div slot="content"> 640 <lit-tree id="optionsSettingTree" checkable="true"></lit-tree> 641 </div> 642 <lit-icon name="setting" size="21" id="setting"></lit-icon> 643 </lit-popover> 644 </div> 645 <div slot="right" style="margin: 0 10px; color: var(--dark-icon,#606060);display: flex;align-items: center;"> 646 <lit-popover placement="bottomRight" class="popover" haveRadio="true" trigger="click" id="select-process"> 647 <div slot="content"> 648 <lit-tree id="processTree" checkable="true"></lit-tree> 649 </div> 650 <lit-icon name="setting" size="20" id="setting"></lit-icon> 651 </lit-popover> 652 <div title="Import SO" id="import_div" style="width: 20px;height: 20px;display: flex;flex-direction: row;margin-right: 10px"> 653 <input id="import-file" style="display: none;pointer-events: none" type="file" webkitdirectory> 654 <label style="width: 20px;height: 20px;cursor: pointer;" for="import-file"> 655 <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20"> 656 </lit-icon> 657 </label> 658 </div> 659 <lit-icon title="Download Table" id="export-btn" name="import-so" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20"> 660 </lit-icon> 661 <lit-icon title="Maximize Tab" id="max-btn" name="vertical-align-top" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20"> 662 </lit-icon> 663 <lit-icon title="Minimize Tab" id="min-btn" name="down" style="font-weight: bold;cursor: pointer;" size="20"> 664 </lit-icon> 665 </div> 666 </lit-tabs> 667 </div>`; 668 } 669 displayCurrent = (data: SlicesTime): void => 670 this.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(data); 671 displayThreadData = ( 672 data: ThreadStruct, 673 scrollCallback: ((e: ThreadStruct) => void) | undefined, 674 scrollWakeUp: (d: unknown) => void | undefined, 675 scrollPrio: (d: unknown) => void | undefined, 676 callback?: (data: Array<unknown>, str: string) => void 677 ): Promise<void> => 678 this.displayTab<TabPaneCurrentSelection>('current-selection').setThreadData( 679 data, 680 // @ts-ignore 681 scrollCallback, 682 scrollWakeUp, 683 scrollPrio, 684 callback 685 ); 686 displayMemData = (data: ProcessMemStruct): void => 687 this.displayTab<TabPaneCurrentSelection>('current-selection').setMemData(data); 688 displayHangData = (data: HangStruct, sp: SpSystemTrace): Promise<void> => 689 this.displayTab<TabPaneCurrentSelection>('current-selection').setHangData(data, sp); 690 displayClockData = (data: ClockStruct): Promise<void> => 691 this.displayTab<TabPaneCurrentSelection>('current-selection').setClockData(data); 692 displayDmaFenceData = (data: DmaFenceStruct, rowData: unknown): void =>//展示tab页内容 693 // @ts-ignore 694 this.displayTab<TabPaneCurrentSelection>('current-selection').setDmaFenceData(data, rowData); 695 displayPerfToolsData = (data: PerfToolStruct): void => 696 this.displayTab<TabPaneCurrentSelection>('current-selection').setPerfToolsData(data); 697 displayIrqData = (data: IrqStruct): void => 698 this.displayTab<TabPaneCurrentSelection>('current-selection').setIrqData(data); 699 displayStartupData = (data: AppStartupStruct, scrollCallback: Function, rowData: unknown): void => 700 this.displayTab<TabPaneCurrentSelection>('current-selection').setStartupData(data, scrollCallback, rowData); 701 displayAllStartupData = (data: AllAppStartupStruct, scrollCallback: Function): void => 702 this.displayTab<TabPaneCurrentSelection>('current-selection').setAllStartupData(data, scrollCallback); 703 displayStaticInitData = (data: SoStruct, scrollCallback: Function): void => 704 this.displayTab<TabPaneCurrentSelection>('current-selection').setStaticInitData(data, scrollCallback); 705 706 displayNativeHookData = (data: HeapStruct, rowType: string, ipid: number): void => { 707 let val = new SelectionParam(); 708 val.nativeMemoryStatistic.push(rowType); 709 val.nativeMemoryCurrentIPid = ipid; 710 val.nativeMemory = []; 711 val.leftNs = data.startTime! + data.dur!; 712 val.rightNs = data.startTime! + data.dur! + 1; 713 this.selection = val; 714 this.displayTab<TabPaneNMStatisticAnalysis>('box-native-statistic-analysis', 'box-native-calltree').data = val; 715 this.showUploadSoBt(val); 716 this.showSwitchProcessBt(val); 717 }; 718 719 displayGpuSelectedData = (type: string, startTs: number, dataList: Array<SnapshotStruct>): void => { 720 this.displayTab<TabPaneGpuClickSelectComparison>('gpu-click-select-comparison').getGpuClickDataByDB( 721 type, 722 startTs, 723 dataList 724 ); 725 let dataObject = { type: type, startTs: startTs }; 726 this.displayTab<TabPaneGpuClickSelect>('gpu-click-select', 'gpu-click-select-comparison').gpuClickData(dataObject); 727 }; 728 729 displayFuncData = ( 730 names: string[], 731 threadName: string, 732 data: FuncStruct, 733 scrollCallback: Function, 734 callback?: (data: Array<unknown>, str: string, binderTid: number) => void, 735 distributedCallback?: (dataList: FuncStruct[]) => void, 736 ): Promise<void> => 737 this.displayTab<TabPaneCurrentSelection>(...names).setFunctionData(data, threadName, scrollCallback, callback, distributedCallback); 738 displayCpuData = ( 739 data: CpuStruct, 740 callback: ((data: WakeupBean | null) => void) | undefined = undefined, 741 scrollCallback?: (data: CpuStruct) => void 742 ): Promise<void> => 743 this.displayTab<TabPaneCurrentSelection>('current-selection').setCpuData(data, callback, scrollCallback); 744 displayJankData = ( 745 data: JankStruct, 746 callback: ((data: Array<unknown>) => void) | undefined = undefined, 747 scrollCallback: ((e: JankStruct) => void) | undefined 748 // @ts-ignore 749 ): void => this.displayTab<TabPaneCurrentSelection>('current-selection').setJankData(data, callback, scrollCallback); 750 displayShmData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => { 751 this.displayTab<TabPaneVmTrackerShmComparison>('box-vmtracker-shm-comparison').setShmData(data, dataList); 752 this.displayTab<TabPaneVmTrackerShmSelection>( 753 'box-vmtracker-shm-selection', 754 'box-vmtracker-shm-comparison' 755 ).setShmData(data, dataList); 756 }; 757 displaySmapsData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => { 758 let val = new SelectionParam(); 759 val.smapsType = []; 760 val.leftNs = data.startNs; 761 this.selection = val; 762 val.smapsType = []; 763 this.displayTab<TabPaneSmapsComparison>('box-smaps-comparison').setData(val, dataList); 764 this.displayTab<TabPaneSmapsStatistics>( 765 'box-smaps-statistics', 766 'box-smaps-sample', 767 'box-smaps-comparison', 768 'box-smaps-record' 769 ).data = val; 770 }; 771 displaySnapshotData = ( 772 data: HeapSnapshotStruct, 773 dataListCache: Array<HeapSnapshotStruct>, 774 scrollCallback?: (data: HeapSnapshotStruct, dataListCache: Array<HeapSnapshotStruct>) => void 775 ): void => { 776 if (dataListCache.length > 1) { 777 this.displayTab<TabPaneSummary>('box-heap-summary', 'box-heap-comparison').setSnapshotData( 778 data, 779 dataListCache, 780 scrollCallback 781 ); 782 let nav = this.shadowRoot!.querySelector('#tabs')!.shadowRoot!.querySelector( 783 '#nav > #nav-comparison' 784 ) as HTMLDivElement; 785 let tabPaneComparison = this.shadowRoot!.querySelector( 786 '#box-heap-comparison > tabpane-comparison' 787 ) as TabPaneComparison; 788 nav!.onclick = (): void => { 789 tabPaneComparison.initComparison(data, dataListCache); 790 }; 791 } else { 792 this.displayTab<TabPaneSummary>('box-heap-summary').setSnapshotData(data, dataListCache, scrollCallback); 793 } 794 }; 795 displayFlagData = (flagObj: Flag): void => this.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flagObj); 796 displayFreqData = (): CpuFreqStruct | undefined => 797 (this.displayTab<TabPaneCurrentSelection>('box-freq').data = CpuFreqStruct.selectCpuFreqStruct); 798 displayCpuStateData = (): CpuStateStruct | undefined => 799 (this.displayTab<TabPaneCurrentSelection>('cpu-state-click').data = CpuStateStruct.selectStateStruct); 800 displayFreqLimitData = (): CpuFreqLimitsStruct | undefined => 801 (this.displayTab<TabPaneCurrentSelection>('box-freq-limit').data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct); 802 803 displayFrameAnimationData = (data: FrameAnimationStruct, scrollCallback: Function): Promise<void> => 804 this.displayTab<TabPaneCurrentSelection>('current-selection').setFrameAnimationData(data, scrollCallback); 805 displayFrameDynamicData = (row: TraceRow<FrameDynamicStruct>, data: FrameDynamicStruct): void => 806 this.displayTab<TabPaneFrameDynamic>('box-frame-dynamic').buildDynamicTable([data], true); 807 displayFrameSpacingData = (data: FrameSpacingStruct): void => 808 this.displayTab<TabFrameSpacing>('box-frames-spacing').setFrameSpacingData(data); 809 displayJsProfilerData = (data: Array<JsCpuProfilerChartFrame>): void => { 810 let val = new SelectionParam(); 811 val.jsCpuProfilerData = data; 812 this.selection = val; 813 this.displayTab<TabPaneJsCpuStatistics>( 814 'box-js-Profiler-statistics', 815 'box-js-Profiler-bottom-up', 816 'box-js-Profiler-top-down' 817 ).data = data; 818 }; 819 displayPurgTotalAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => { 820 data.type = 'ability'; 821 this.displayTab<TabPanePurgTotalComparisonAbility>('box-purgeable-total-comparison-ability').totalData( 822 data, 823 dataList 824 ); 825 this.displayTab<TabPanePurgTotalSelection>( 826 'box-purgeable-total-selection', 827 'box-purgeable-total-comparison-ability' 828 ).data = data; 829 }; 830 displayPurgPinAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => { 831 data.type = 'ability'; 832 this.displayTab<TabPanePurgPinComparisonAbility>('box-purgeable-pin-comparison-ability').totalData(data, dataList); 833 this.displayTab<TabPanePurgPinSelection>( 834 'box-purgeable-pin-selection', 835 'box-purgeable-pin-comparison-ability' 836 ).data = data; 837 }; 838 displayPurgTotalVMData = (data: SnapshotStruct, dataListCache: Array<SnapshotStruct>): void => { 839 data.type = 'VM'; 840 this.displayTab<TabPanePurgTotalComparisonVM>('box-purgeable-total-comparison-vm').totalData(data, dataListCache); 841 this.displayTab<TabPanePurgTotalSelection>( 842 'box-purgeable-total-selection', 843 'box-purgeable-total-comparison-vm' 844 ).data = data; 845 }; 846 displayPurgPinVMData = (data: SnapshotStruct, dataListCache: Array<SnapshotStruct>): void => { 847 data.type = 'VM'; 848 this.displayTab<TabPanePurgPinComparisonVM>('box-purgeable-pin-comparison-vm').totalData(data, dataListCache); 849 this.displayTab<TabPanePurgPinSelection>('box-purgeable-pin-selection', 'box-purgeable-pin-comparison-vm').data = 850 data; 851 }; 852 displayDmaAbility = (data: number, dataList: Array<SnapshotStruct>): void => { 853 if (dataList.length > 0) { 854 this.displayTab<TabPaneDmaAbilityComparison>('box-dma-ability-comparison').comparisonDataByDB(data, dataList); 855 this.displayTab<TabPaneDmaSelectAbility>( 856 'box-dma-selection-ability', 857 'box-dma-ability-comparison' 858 ).queryDmaClickDataByDB(data); 859 } else { 860 this.displayTab<TabPaneDmaSelectAbility>('box-dma-selection-ability').queryDmaClickDataByDB(data); 861 } 862 }; 863 displayDmaVmTracker = (data: number, dataListCache: Array<SnapshotStruct>): void => { 864 if (dataListCache.length > 0) { 865 this.displayTab<TabPaneDmaVmTrackerComparison>('box-vmTracker-comparison').comparisonDataByDB( 866 data, 867 dataListCache 868 ); 869 this.displayTab<TabPaneDmaSelectVmTracker>( 870 'box-dma-selection-vmTracker', 871 'box-vmTracker-comparison' 872 ).queryDmaVmTrackerClickDataByDB(data); 873 } else { 874 this.displayTab<TabPaneDmaSelectVmTracker>('box-dma-selection-vmTracker').queryDmaVmTrackerClickDataByDB(data); 875 } 876 }; 877 displayGpuMemoryAbility = (data: number, dataList: Array<SnapshotStruct>): void => { 878 if (dataList.length > 0) { 879 this.displayTab<TabPaneGpuMemoryComparison>('box-gpu-memory-comparison').comparisonDataByDB(data, dataList); 880 this.displayTab<TabPaneGpuMemorySelectAbility>( 881 'box-gpu-memory-selection-ability', 882 'box-gpu-memory-comparison' 883 ).queryGpuMemoryClickDataByDB(data); 884 } else { 885 this.displayTab<TabPaneGpuMemorySelectAbility>('box-gpu-memory-selection-ability').data = data; 886 } 887 }; 888 displayGpuMemoryVmTracker = (data: number, dataListCache: Array<SnapshotStruct>): void => { 889 if (dataListCache.length > 0) { 890 this.displayTab<TabPaneGpuMemoryVmTrackerComparison>('box-gpu-memory-vmTracker-comparison').comparisonDataByDB( 891 data, 892 dataListCache 893 ); 894 this.displayTab<TabPaneGpuMemorySelectVmTracker>( 895 'box-gpu-memory-selection-vmTracker', 896 'box-gpu-memory-vmTracker-comparison' 897 ).queryGpuMemoryVmTrackerClickDataByDB(data); 898 } else { 899 this.displayTab<TabPaneGpuMemorySelectVmTracker>( 900 'box-gpu-memory-selection-vmTracker' 901 ).queryGpuMemoryVmTrackerClickDataByDB(data); 902 } 903 }; 904 displayGpuResourceVmTracker = (data: number): void => { 905 this.displayTab<TabPaneGpuResourceVmTracker>('box-smaps-gpu-resource').data = data; 906 }; 907 908 displaySystemLogsData = (): void => { 909 let tblHiLogPanel = this.shadowRoot?.querySelector<LitTabpane>("lit-tabpane[id='box-hilogs']"); 910 if (tblHiLogPanel) { 911 let tblHiLog = tblHiLogPanel.querySelector<TabPaneHiLogs>('tab-hi-log'); 912 if (tblHiLog) { 913 tblHiLog.initTabSheetEl(this); 914 } 915 } 916 }; 917 918 displayHangsData = (): void => { 919 let tblHangPanel = this.shadowRoot?.querySelector<LitTabpane>("lit-tabpane[id='box-hang']"); 920 if (tblHangPanel) { 921 let tblHang = tblHangPanel.querySelector<TabPaneHiLogs>('tab-hang'); 922 if (tblHang) { 923 tblHang.initTabSheetEl(this); 924 } 925 } 926 }; 927 928 displaySampleData = (data: SampleStruct, reqProperty: unknown): void => { 929 this.displayTab<TabPaneSampleInstruction>('box-sample-instruction').setSampleInstructionData(data, reqProperty); 930 this.optionsDiv!.style.display = 'flex'; 931 const select = 932 this.optionsSettingTree!.getCheckdKeys().length === 0 ? ['0'] : this.optionsSettingTree!.getCheckdKeys(); 933 this.optionsSettingTree!.treeData = [ 934 { key: '0', title: 'instruction', checked: select[0] === '0' }, 935 { key: '1', title: 'cycles', checked: select[0] === '1' }, 936 ]; 937 }; 938 displayUserPlugin = (selectData: unknown): void => { 939 this.displayTab<TabPaneUserPlugin>("tab-pane-userplugin").data = selectData; 940 }; 941 942 943 displayGpuCounterData = (data: GpuCounterStruct): void => { 944 this.displayTab<TabPaneGpuCounter>('box-gpu-counter').data = data; 945 }; 946 947 displaySystemStatesData = (): void => { 948 let dataCutPane = this.shadowRoot?.querySelector<TabPaneDataCut>('tabpane-datacut'); 949 if (dataCutPane) { 950 dataCutPane.initTabSheetEl(this); 951 } 952 let tblStatesPanel = this.shadowRoot?.querySelector<TabPaneFreqStatesDataCut>('tabpane-states-datacut'); 953 if (tblStatesPanel) { 954 tblStatesPanel.initTabSheetEl(this); 955 } 956 }; 957 rangeSelect(selection: SelectionParam, restore = false): boolean { 958 this.selection = selection; 959 this.exportBt!.style.display = 'flex'; 960 this.showUploadSoBt(selection); 961 this.showSwitchProcessBt(selection); 962 this.showOptionsBt(selection); // @ts-ignore 963 Reflect.ownKeys(tabConfig) 964 .reverse() 965 .forEach((id) => { 966 // @ts-ignore 967 let element = tabConfig[id]; 968 let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`); 969 if (pane) { 970 pane.hidden = !(element.require && element.require(selection)); 971 } 972 }); 973 if (restore) { 974 if (this.litTabs?.activekey) { 975 this.loadTabPaneData(this.litTabs?.activekey); 976 this.setMode('max'); 977 return true; 978 } else { 979 this.setMode('hidden'); 980 return false; 981 } 982 } else { 983 let firstPane = this.shadowRoot!.querySelector<LitTabpane>("lit-tabpane[hidden='false']"); 984 if (firstPane) { 985 this.litTabs?.activeByKey(firstPane.key); 986 this.loadTabPaneData(firstPane.key); 987 this.setMode('max'); 988 return true; 989 } else { 990 this.setMode('hidden'); 991 return false; 992 } 993 } 994 } 995 996 showOptionsBt(selection: SelectionParam | null | undefined): void { 997 if (selection && selection.sampleData.length > 0) { 998 this.optionsDiv!.style.display = 'flex'; 999 const select = 1000 this.optionsSettingTree!.getCheckdKeys().length === 0 ? ['0'] : this.optionsSettingTree!.getCheckdKeys(); 1001 this.optionsSettingTree!.treeData = [ 1002 { key: '0', title: 'instruction', checked: select[0] === '0' }, 1003 { key: '1', title: 'cycles', checked: select[0] === '1' }, 1004 ]; 1005 } else { 1006 this.optionsDiv!.style.display = 'none'; 1007 } 1008 } 1009 1010 updateRangeSelect(ipid?: number): boolean { 1011 if ( 1012 this.selection && 1013 (this.selection.nativeMemory.length > 0 || 1014 this.selection.nativeMemoryStatistic.length > 0 || 1015 this.selection.perfSampleIds.length > 0 || 1016 this.selection.fileSystemType.length > 0 || 1017 this.selection.fsCount > 0 || 1018 this.selection.fileSysVirtualMemory || 1019 this.selection.vmCount > 0 || 1020 this.selection.diskIOLatency || 1021 this.selection.diskIOipids.length > 0) 1022 ) { 1023 let param: SelectionParam = new SelectionParam(); 1024 Object.assign(param, this.selection); 1025 if (param.nativeMemory.length > 0 || param.nativeMemoryStatistic.length > 0) { 1026 Utils.getInstance().initResponseTypeList(param); 1027 if (ipid) { 1028 Utils.getInstance().setCurrentSelectIPid(ipid); 1029 param.nativeMemoryCurrentIPid = ipid; 1030 } 1031 } 1032 this.rangeSelect(param, true); 1033 return true; 1034 } else { 1035 return false; 1036 } 1037 } 1038 1039 showUploadSoBt(selection: SelectionParam | null | undefined): void { 1040 if ( 1041 selection && 1042 (selection.nativeMemory.length > 0 || 1043 selection.nativeMemoryStatistic.length > 0 || 1044 selection.perfSampleIds.length > 0 || 1045 selection.fileSystemType.length > 0 || 1046 selection.fsCount > 0 || 1047 selection.fileSysVirtualMemory || 1048 selection.vmCount > 0 || 1049 selection.diskIOLatency || 1050 selection.diskIOipids.length > 0 || 1051 selection.threadIds.length > 0) 1052 ) { 1053 this.importDiv!.style.display = 'flex'; 1054 } else { 1055 this.importDiv!.style.display = 'none'; 1056 } 1057 } 1058 isProcessEqual(treeData: Array<{ pid: number; ipid: number }>): boolean { 1059 if (treeData.length !== this.lastProcessSet.size) { 1060 return false; 1061 } 1062 for (let process of treeData) { 1063 if (!this.lastProcessSet.has(process.pid)) { 1064 return false; 1065 } 1066 } 1067 return true; 1068 } 1069 1070 showSwitchProcessBt(selection: SelectionParam | null | undefined): void { 1071 // 2个及以上进程再显示 1072 if (selection && selection.nativeMemoryAllProcess.length > 1) { 1073 this.switchDiv!.style.display = 'flex'; 1074 if (this.isProcessEqual(selection.nativeMemoryAllProcess)) { 1075 if (this.processTree) { 1076 for (const data of this.processTree.treeData) { 1077 if (data.key === `${selection.nativeMemoryCurrentIPid}`) { 1078 data.checked = true; 1079 } else { 1080 data.checked = false; 1081 } 1082 } 1083 //调用set重新更新界面 1084 this.processTree.treeData = this.processTree.treeData; 1085 } 1086 return; 1087 } 1088 this.lastProcessSet = new Set<number>(); 1089 const processArray: Array<TreeItemData> = []; 1090 let isFirst: boolean = true; 1091 for (let process of selection.nativeMemoryAllProcess) { 1092 const treeData: TreeItemData = { 1093 key: `${process.ipid}`, 1094 title: `Process ${process.pid}`, 1095 checked: isFirst, 1096 }; 1097 if (isFirst) { 1098 this.lastSelectIPid = process.ipid; 1099 isFirst = false; 1100 } 1101 processArray.push(treeData); 1102 this.lastProcessSet.add(process.pid); 1103 } 1104 this.processTree!.treeData = processArray; 1105 } else { 1106 this.switchDiv!.style.display = 'none'; 1107 } 1108 } 1109 1110 loadTabPaneData(key: string): void { 1111 let component: unknown = this.shadowRoot 1112 ?.querySelector<LitTabpane>(`#tabs lit-tabpane[key='${key}']`) 1113 ?.children.item(0); 1114 if (component) { 1115 // @ts-ignore 1116 component.data = this.selection; 1117 if (this.selection) { 1118 this.selection.isRowClick = false; 1119 } 1120 } 1121 } 1122 1123 setMode(mode: string): void { 1124 let delta = this.clientHeight; 1125 let show = mode === 'max' ? 1 : -1; 1126 this.setAttribute('mode', mode); 1127 if (mode === 'hidden') { 1128 this.selection = undefined; 1129 } 1130 window.publish(window.SmartEvent.UI.ShowBottomTab, { show: show, delta: delta }); 1131 } 1132 1133 tdClickHandler(e: unknown): void { 1134 // @ts-ignore 1135 this.currentPaneID = e.target.parentElement.id; 1136 //隐藏除了当前Tab页的其他Tab页 1137 this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean => 1138 it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false) 1139 );//todo:看能不能优化 1140 let pane = this.getPaneByID('box-cpu-child');//通过Id找到需要展示的Tab页 1141 pane.closeable = true;//关闭的ican显示 1142 pane.hidden = false; 1143 this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页 1144 // @ts-ignore 1145 pane.tab = e.detail.tabTitle ? e.detail.tabTitle : Utils.transferPTSTitle(e.detail.title);//设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串 1146 let param = new BoxJumpParam(); 1147 param.traceId = this.selection!.traceId; 1148 param.leftNs = this.selection!.leftNs; 1149 param.rightNs = this.selection!.rightNs; 1150 param.cpus = this.selection!.cpus; 1151 // @ts-ignore 1152 param.state = e.detail.summary ? '' : e.detail.state; 1153 // @ts-ignore 1154 param.processId = e.detail.summary ? this.selection.processIds : e.detail.pid; 1155 // @ts-ignore 1156 param.threadId = e.detail.summary ? this.selection.threadIds : e.detail.tid; 1157 param.isJumpPage = true;// @ts-ignore 1158 param.currentId = e.target.parentElement.id;//根据父Tab页的标题,确认子Tab页的dur是否需要处理 1159 (pane.children.item(0) as TabPaneBoxChild).data = param; 1160 } 1161 1162 //Slice Tab点击Occurrences列下的td进行跳转 1163 tdSliceClickHandler(e: unknown): void { 1164 // @ts-ignore 1165 this.currentPaneID = e.target.parentElement.id; 1166 //隐藏除了当前Tab页的其他Tab页 1167 this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean => 1168 it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false) 1169 ); 1170 let pane = this.getPaneByID('box-slice-child');//通过Id找到需要展示的Tab页 1171 pane.closeable = true; 1172 pane.hidden = false; 1173 this.litTabs!.activeByKey(pane.key); //显示key值(sheetconfig里面对应的index是一个数字)对应的Tab页 1174 // @ts-ignore 1175 pane.tab = e.detail.tabTitle;//设置Tab页标题 1176 let param = new SliceBoxJumpParam(); 1177 param.traceId = this.selection!.traceId; 1178 param.leftNs = this.selection!.leftNs; 1179 param.rightNs = this.selection!.rightNs; 1180 param.processId = this.selection!.processIds; 1181 param.threadId = this.selection!.funTids;//@ts-ignore2 1182 param.name = e.detail.allName ? e.detail.allName : [e.detail.name];//@ts-ignore2 1183 param.asyncNames = e.detail.asyncNames;//@ts-ignore2 1184 param.asyncCatNames = e.detail.asyncCatNames; 1185 param.isJumpPage = true; 1186 (pane.children.item(0) as TabPaneSliceChild).data = param; 1187 } 1188 1189 clearMemory(): void { 1190 let allTabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []); 1191 allTabs.forEach((tab) => { 1192 if (tab) { 1193 let tables = Array.from( 1194 (tab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || [] 1195 ); 1196 for (let table of tables) { 1197 table.recycleDataSource = []; 1198 } 1199 } 1200 }); 1201 } 1202} 1203