• 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 {SpSystemTrace} from './SpSystemTrace';
17import { TabPaneFrequencySample } from "./trace/sheet/cpu/TabPaneFrequencySample";
18import { TabPaneCounterSample } from "./trace/sheet/cpu/TabPaneCounterSample";
19import { RangeSelect } from "./trace/base/RangeSelect";
20import { TraceRow } from "./trace/base/TraceRow";
21import { SportRuler } from "./trace/timer-shaft/SportRuler";
22import { SelectionParam } from "../bean/BoxSelection";
23import {error, info} from "../../log/Log";
24import { SpStatisticsHttpUtil } from "../../statistics/util/SpStatisticsHttpUtil";
25import { queryEbpfSamplesCount } from "../database/sql/Memory.sql";
26import { SpChartManager } from "./chart/SpChartManager";
27import {ThreadStruct} from "../database/ui-worker/ProcedureWorkerThread";
28import {FlagsConfig} from "./SpFlags";
29import {threadPool} from "../database/SqlLite";
30import {JankStruct} from "../database/ui-worker/ProcedureWorkerJank";
31import {CpuStruct} from "../database/ui-worker/cpu/ProcedureWorkerCPU";
32import {PairPoint} from "../database/ui-worker/ProcedureWorkerCommon";
33import { TraceSheet } from './trace/base/TraceSheet';
34import { TimerShaftElement } from './trace/TimerShaftElement';
35import { SpChartList } from './trace/SpChartList';
36type HTMLElementAlias = HTMLElement | null | undefined;
37
38function rightButtonOnClick(sp: SpSystemTrace,rightStar: HTMLElementAlias) {
39    Object.assign(sp, {
40        ext(): string {
41            return "Handle the right button click event";
42        }
43    })
44
45    return function (event: any) {
46        if (SpSystemTrace.btnTimer) {
47            return;
48        }
49        // 唤醒树有值则不再重复添加
50        const startIndex = CpuStruct.selectCpuStruct!.displayProcess?.indexOf('[');
51        if (SpSystemTrace.wakeupList.length === 0) {
52            SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!);
53            sp.queryCPUWakeUpList(CpuStruct.wakeupBean!);
54            CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime;
55            CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name;
56            CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId;
57            CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim();
58            CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid;
59            sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct));
60        } else {
61            sp.wakeupListNull();
62            SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!);
63            sp.queryCPUWakeUpList(CpuStruct.wakeupBean!);
64            CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime;
65            CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name;
66            CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId;
67            CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim();
68            CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid;
69            sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct));
70        }
71        setTimeout(() => {
72            requestAnimationFrame(() => sp.refreshCanvas(false));
73        }, 300);
74        rightStar!.style.visibility = 'visible';
75        rightStar!.style.cursor = 'pointer';
76        SpSystemTrace.btnTimer = setTimeout(() => {
77            SpSystemTrace.btnTimer = null; // 2.清空节流阀,方便下次开启定时器
78        }, 2000);
79    }
80}
81function rightStarOnClick(sp:SpSystemTrace) {
82   return function (ev:any){
83       let wakeupLists = [];
84       wakeupLists.push(CpuStruct.selectCpuStruct?.cpu);
85       for (let wakeupBean of SpSystemTrace.wakeupList) {
86           wakeupLists.push(wakeupBean.cpu);
87       }
88       let wakeupCpuLists = Array.from(new Set(wakeupLists)).sort();
89       for (let wakeupCpu of wakeupCpuLists) {
90           let cpuFavoriteRow: any = sp.shadowRoot?.querySelector<TraceRow<any>>(
91             `trace-row[row-type='cpu-data'][row-id='${wakeupCpu}']`
92           );
93           if (cpuFavoriteRow === null || cpuFavoriteRow === undefined) {
94               continue;
95           }
96           cpuFavoriteRow!.setAttribute('collect-type', '');
97           let replaceRow = document.createElement('div');
98           replaceRow.setAttribute('row-id', cpuFavoriteRow.rowId + '-' + cpuFavoriteRow.rowType);
99           replaceRow.setAttribute('type', 'replaceRow');
100           replaceRow.setAttribute('row-parent-id', cpuFavoriteRow.rowParentId);
101           replaceRow.style.display = 'none';
102           cpuFavoriteRow.rowHidden = !cpuFavoriteRow.hasAttribute('scene');
103           if (sp.rowsEL!.contains(cpuFavoriteRow)) {
104               sp.rowsEL!.replaceChild(replaceRow, cpuFavoriteRow);
105           }
106           cpuFavoriteRow.tampName = cpuFavoriteRow.name;
107           sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, sp.currentCollectGroup, true);
108           sp.collectRows.push(cpuFavoriteRow);
109           sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0);
110           sp.currentClickRow = null;
111           cpuFavoriteRow.setAttribute('draggable', 'true');
112           cpuFavoriteRow.addEventListener('dragstart', cpuFavoriteRowDragStart(sp,cpuFavoriteRow));
113           cpuFavoriteRow.addEventListener('dragover', cpuFavoriteRowDragOver(sp));
114           cpuFavoriteRow.addEventListener('drop', cpuFavoriteRowDropHandler(sp,cpuFavoriteRow));
115           cpuFavoriteRow.addEventListener('dragend', cpuFavoriteRowDragendHandler(sp));
116       }
117       sp.refreshFavoriteCanvas();
118       sp.refreshCanvas(true);
119   }
120}
121function cpuFavoriteRowDragStart(sp: SpSystemTrace, cpuFavoriteRow: any) {
122    return function () {
123        sp.currentClickRow = cpuFavoriteRow;
124    }
125}
126function cpuFavoriteRowDragOver(sp: SpSystemTrace) {
127    return function (ev:any){
128        ev.preventDefault();
129        ev.dataTransfer.dropEffect = 'move';
130    }
131}
132function cpuFavoriteRowDropHandler(sp: SpSystemTrace, cpuFavoriteRow: any) {
133    return function (ev:any){
134        if (
135          sp.favoriteChartListEL != null &&
136          sp.currentClickRow != null &&
137          sp.currentClickRow !== cpuFavoriteRow
138        ) {
139            let rect = cpuFavoriteRow.getBoundingClientRect();
140            if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) {
141                //向上移动
142                sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow);
143            } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) {
144                //向下移动
145                sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow.nextSibling);
146            }
147            sp.refreshFavoriteCanvas();
148        }
149    }
150}
151function cpuFavoriteRowDragendHandler(sp: SpSystemTrace) {
152    return function(){
153        sp.linkNodes.forEach((itln) => {
154            if (itln[0].rowEL.collect) {
155                itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
156            } else {
157                itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
158            }
159            if (itln[1].rowEL.collect) {
160                itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
161            } else {
162                itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
163            }
164            itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
165            itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
166        });
167        sp.currentClickRow = null;
168    }
169}
170function triangleFlagHandler(sp:SpSystemTrace) {
171    return function (event:any) {
172        let temporaryTime = sp.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type);
173        if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime);
174    };
175}
176function numberCalibrationHandler(sp: SpSystemTrace) {
177    return function (event: any) {
178        sp.timerShaftEL!.sportRuler!.times = event.detail.time;
179        sp.timerShaftEL!.sportRuler!.counts = event.detail.counts;
180        sp.timerShaftEL!.sportRuler!.durations = event.detail.durations;
181        sp.timerShaftEL!.sportRuler?.draw();
182    }
183}
184function flagChangeHandler(sp: SpSystemTrace) {
185    return function (event: any) {
186        sp.timerShaftEL?.modifyFlagList(event.detail);
187        if (event.detail.hidden) {
188            sp.selectFlag = undefined;
189            if (sp._flagList.length <= 0) {
190                if (TraceRow.rangeSelectObject) {
191                    let showTab = sp.getShowTab();
192                    showTab = showTab.filter((it) => it !== 'box-flag');
193                    sp.traceSheetEL?.displayTab(...showTab);
194                } else {
195                    sp.traceSheetEL?.setAttribute('mode', 'hidden');
196                }
197            }
198            sp.refreshCanvas(true);
199        }
200    }
201}
202function slicesChangeHandler(sp:SpSystemTrace) {
203   return function (event: any) {
204       sp.timerShaftEL?.modifySlicesList(event.detail);
205       if (event.detail.hidden) {
206           sp.slicestime = null;
207           if (sp._slicesList.length <= 0) {
208               if (TraceRow.rangeSelectObject) {
209                   let showTab = sp.getShowTab();
210                   showTab = showTab.filter((it) => it !== 'tabpane-current');
211                   sp.traceSheetEL?.displayTab(...showTab);
212               } else {
213                   sp.traceSheetEL?.setAttribute('mode', 'hidden');
214               }
215           }
216           sp.refreshCanvas(true);
217       }
218   }
219}
220function collectHandler(sp: SpSystemTrace) {
221    return function (event: any) {
222        let currentRow = event.detail.row;
223        if (currentRow.collect) {
224            collectHandlerYes(sp,currentRow,event);
225        } else {
226            collectHandlerNo(sp,currentRow,event);
227        }
228        sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0);
229        sp.refreshFavoriteCanvas();
230        sp.refreshCanvas(true);
231        sp.linkNodes.forEach((itln) => {
232            if (itln[0].rowEL === currentRow) {
233                if (itln[0].rowEL.collect) {
234                    itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
235                } else {
236                    itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
237                }
238                itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
239            } else if (itln[1].rowEL === currentRow) {
240                if (itln[1].rowEL.collect) {
241                    itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
242                } else {
243                    itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
244                }
245                itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
246            }
247        });
248        // 收藏夹元素拖动排序功能
249        sp.currentClickRow = null;
250        currentRow.setAttribute('draggable', 'true');
251        currentRow.addEventListener('dragstart', () => {
252            sp.currentClickRow = currentRow;
253        });
254        currentRow.addEventListener('dragover', (ev: any) => {
255            ev.preventDefault();
256            ev.dataTransfer.dropEffect = 'move';
257        });
258        currentRow.addEventListener('drop', collectHandlerDrop(sp,currentRow));
259        currentRow.addEventListener('dragend', collectHandlerDragEnd(sp));
260    };
261}
262function collectHandlerNo(sp: SpSystemTrace, currentRow: any, event: any) {
263    sp.favoriteChartListEL?.deleteRow(currentRow, event.detail.type !== 'auto-collect');
264    if (event.detail.type !== 'auto-collect') {
265        let rowIndex = sp.collectRows.indexOf(currentRow);
266        if (rowIndex !== -1) {
267            sp.collectRows.splice(rowIndex, 1);
268        }
269    }
270    let row = currentRow;
271    let allowExpansionRow = [];
272    while (row.hasParentRowEl) {
273        let parent = row.parentRowEl;
274        allowExpansionRow.push(parent);
275        row = parent;
276    }
277    for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) {
278        if (allowExpansionRow[index]?.hasAttribute('scene')) {
279            if (allowExpansionRow[index]!.expansion) {
280                allowExpansionRow[index].updateChildRowStatus();
281            } else {
282                allowExpansionRow[index].expansion = true;
283            }
284        }
285    }
286    allowExpansionRow.length = 0;
287    let replaceRow = sp.rowsEL!.querySelector<HTMLCanvasElement>(
288      `div[row-id='${currentRow.rowId}-${currentRow.rowType}']`
289    );
290    // 取消收藏时,删除父亲ID
291    currentRow.name = currentRow.tampName;
292    if (replaceRow != null) {
293        sp.rowsEL!.replaceChild(currentRow, replaceRow);
294        currentRow.style.boxShadow = `0 10px 10px #00000000`;
295    }
296}
297function collectHandlerYes(sp: SpSystemTrace, currentRow: any, event: any){
298    if (
299      !sp.collectRows.find((find) => {
300          return find === currentRow;
301      })
302    ) {
303        sp.collectRows.push(currentRow);
304    }
305    let replaceRow = document.createElement('div');
306    replaceRow.setAttribute('row-id', currentRow.rowId + '-' + currentRow.rowType);
307    replaceRow.setAttribute('type', 'replaceRow');
308    replaceRow.setAttribute('row-parent-id', currentRow.rowParentId);
309    replaceRow.style.display = 'none';
310    if (!currentRow.hasAttribute('scene')) {
311        currentRow.setAttribute('row-hidden', '');
312    } else {
313        currentRow.removeAttribute('row-hidden');
314    }
315    // 添加收藏时,在线程名前面追加父亲ID
316    let rowParentId = currentRow.rowParentId;
317    currentRow.tampName = currentRow.name;
318    if (rowParentId) {
319        let parentRows = sp.shadowRoot?.querySelectorAll<TraceRow<any>>(`trace-row[row-id='${rowParentId}']`);
320        parentRows?.forEach((parentRow) => {
321            if (
322              parentRow?.name &&
323              parentRow?.name != currentRow.name &&
324              !parentRow.rowType!.startsWith('cpu') &&
325              !parentRow.rowType!.startsWith('thread') &&
326              !parentRow.rowType!.startsWith('func') &&
327              !currentRow.name.includes(parentRow.name)
328            ) {
329                currentRow.name += '(' + parentRow.name + ')';
330            }
331        });
332    }
333    if (!currentRow.hasParentRowEl) {
334        sp.rowsEL!.replaceChild(replaceRow, currentRow);
335    }
336    sp.favoriteChartListEL?.insertRow(currentRow, sp.currentCollectGroup, event.detail.type !== 'auto-collect');
337}
338function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement|undefined|null) {
339    return function (ev:any) {
340        if (sp.favoriteChartListEL !== null && sp.currentClickRow !== null && sp.currentClickRow !== currentRow) {
341            let rect = currentRow!.getBoundingClientRect();
342            if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) {
343                //向上移动
344                sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!);
345            } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) {
346                //向下移动
347                sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!.nextSibling!);
348            }
349            sp.refreshFavoriteCanvas();
350        }
351    };
352}
353function collectHandlerDragEnd(sp: SpSystemTrace) {
354    return function (ev:any) {
355        sp.linkNodes.forEach((itln) => {
356            if (itln[0].rowEL.collect) {
357                itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
358            } else {
359                itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
360            }
361            if (itln[1].rowEL.collect) {
362                itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
363            } else {
364                itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
365            }
366            itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
367            itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
368        });
369        sp.currentClickRow = null;
370    };
371}
372function selectHandler(sp: SpSystemTrace) {
373    sp.rangeSelect.selectHandler = (rows, refreshCheckBox): void => {
374        rows.forEach((item) => {
375            sp.setAttribute('clickRow', item.rowType!);
376            sp.setAttribute('rowName', item.name);
377            sp.setAttribute('rowId', item.rowId!);
378        });
379        if (rows.length == 0) {
380            const allRows = [
381                ...sp.shadowRoot!.querySelectorAll<TraceRow<any>>('trace-row'),
382                ...sp.favoriteChartListEL!.getAllCollectRows(),
383            ];
384            for (const row of allRows) {
385                row.checkType = '-1';
386                if (row.folder) {
387                    row.childrenList.forEach((item) => {
388                        row.checkType = '-1';
389                    });
390                }
391            }
392            sp.refreshCanvas(true);
393            if (!SportRuler.isMouseInSportRuler) {
394                sp.traceSheetEL?.setAttribute('mode', 'hidden');
395            }
396            return;
397        }
398        selectHandlerRefreshCheckBox(sp,rows, refreshCheckBox);
399        if (!sp.isSelectClick) {
400            sp.rangeTraceRow = [];
401        }
402        selectHandlerRows(sp, rows);
403    };
404}
405function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array<TraceRow<any>>, refreshCheckBox: boolean) {
406    if (refreshCheckBox) {
407        if (rows.length > 0) {
408            sp.queryAllTraceRow().forEach((row) => {
409                row.checkType = '0';
410                if (row.folder) {
411                    row.childrenList.forEach((ite) => ite.checkType = '0');
412                }
413            });
414            rows.forEach((it) => it.checkType = '2');
415        } else {
416            sp.queryAllTraceRow().forEach((row) => {
417                row.checkType = '-1';
418                if (row.folder) {
419                    row.childrenList.forEach((it) => it.checkType = '-1');
420                }
421            });
422            return;
423        }
424    }
425}
426function selectHandlerRows(sp: SpSystemTrace, rows: Array<TraceRow<any>>) {
427    let selection = new SelectionParam();
428    selection.cpuStateRowsId = sp.stateRowsId;
429    selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0;
430    selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0;
431    selection.recordStartNs = (window as any).recordStartNS;
432    rows.forEach((it) => {
433        selection.pushSelection(it, sp);
434        if (sp.rangeTraceRow!.length !== rows.length) {
435            let event = sp.createPointEvent(it);
436            SpStatisticsHttpUtil.addOrdinaryVisitAction({
437                action: 'trace_row',
438                event: event,
439            });
440        }
441    });
442    if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) {
443        selection.promiseList.push(
444          queryEbpfSamplesCount(
445            TraceRow.rangeSelectObject?.startNS || 0,
446            TraceRow.rangeSelectObject?.endNS || 0,
447            selection.diskIOipids
448          ).then((res) => {
449              if (res.length > 0) {
450                  selection.fsCount = res[0].fsCount;
451                  selection.vmCount = res[0].vmCount;
452              }
453              return new Promise((resolve) => resolve(1));
454          })
455        );
456    }
457    sp.rangeTraceRow = rows;
458    sp.isSelectClick = false;
459    sp.selectStructNull();
460    sp.timerShaftEL?.removeTriangle('inverted');
461    if (selection.promiseList.length > 0) {
462        Promise.all(selection.promiseList).then(() => {
463            selection.promiseList = [];
464            sp.traceSheetEL?.rangeSelect(selection);
465        });
466    } else {
467        sp.traceSheetEL?.rangeSelect(selection);
468    }
469    sp.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。
470    sp.selectionParam = selection;
471}
472function resizeObserverHandler(sp:SpSystemTrace) {
473    // @ts-ignore
474    new ResizeObserver((entries) => {
475        TraceRow.FRAME_WIDTH = sp.clientWidth - 249 - sp.getScrollWidth();
476        requestAnimationFrame(() => {
477            sp.timerShaftEL?.updateWidth(sp.clientWidth - 1 - sp.getScrollWidth());
478            sp.shadowRoot!.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => {
479                it.updateWidth(sp.clientWidth);
480            });
481        });
482    }).observe(sp);
483
484    new ResizeObserver((entries) => {
485        sp.canvasPanelConfig();
486        if (sp.traceSheetEL!.getAttribute('mode') == 'hidden') {
487            sp.timerShaftEL?.removeTriangle('triangle');
488        }
489        sp.refreshFavoriteCanvas();
490        sp.refreshCanvas(true);
491    }).observe(sp.rowsPaneEL!);
492}
493function mutationObserverHandler(sp: SpSystemTrace) {
494    new MutationObserver((mutations, observer) => {
495        for (const mutation of mutations) {
496            if (mutation.type === 'attributes') {
497                if (sp.style.visibility === 'visible') {
498                    if (TraceRow.rangeSelectObject && SpSystemTrace.sliceRangeMark) {
499                        sp.timerShaftEL?.setSlicesMark(
500                          TraceRow.rangeSelectObject.startNS || 0,
501                          TraceRow.rangeSelectObject.endNS || 0,
502                          false
503                        );
504                        SpSystemTrace.sliceRangeMark = undefined;
505                        window.publish(window.SmartEvent.UI.RefreshCanvas, {});
506                    }
507                }
508            }
509        }
510    }).observe(sp, {
511        attributes: true,
512        childList: false,
513        subtree: false,
514    });
515}
516function intersectionObserverHandler(sp: SpSystemTrace) {
517    sp.intersectionObserver = new IntersectionObserver(
518      (entries) => {
519          entries.forEach((it) => {
520              let tr = it.target as TraceRow<any>;
521              tr.intersectionRatio = it.intersectionRatio;
522              if (!it.isIntersecting) {
523                  tr.sleeping = true;
524                  sp.invisibleRows.indexOf(tr) == -1 && sp.invisibleRows.push(tr);
525                  sp.visibleRows = sp.visibleRows.filter((it) => !it.sleeping);
526              } else {
527                  tr.sleeping = false;
528                  sp.visibleRows.indexOf(tr) == -1 && sp.visibleRows.push(tr);
529                  sp.invisibleRows = sp.invisibleRows.filter((it) => it.sleeping);
530              }
531              sp.visibleRows
532                .filter((vr) => vr.expansion)
533                .forEach((vr) => {
534                    vr.sticky = sp.visibleRows.some((vro) => vr.childrenList.filter((it) => !it.collect).indexOf(vro) >= 0);
535                });
536              sp.visibleRows
537                .filter((vr) => !vr.folder && vr.parentRowEl && vr.parentRowEl.expansion)
538                .forEach((vr) => (vr.parentRowEl!.sticky = true));
539              if (sp.handler) {
540                  clearTimeout(sp.handler);
541              }
542              sp.handler = setTimeout(() => sp.refreshCanvas(false), 100);
543          });
544      },
545      { threshold: [0, 0.01, 0.99, 1] }
546    );
547}
548function observerHandler(sp: SpSystemTrace) {
549    resizeObserverHandler(sp);
550    mutationObserverHandler(sp);
551    intersectionObserverHandler(sp);
552}
553function windowKeyDownHandler(sp: SpSystemTrace) {
554    return function (ev: KeyboardEvent) {
555        if (ev.key.toLocaleLowerCase() === 'escape') {
556            sp.queryAllTraceRow().forEach((it) => {
557                it.checkType = '-1';
558            });
559            TraceRow.rangeSelectObject = undefined;
560            sp.rangeSelect.rangeTraceRow = [];
561            sp.selectStructNull();
562            sp.timerShaftEL?.setSlicesMark();
563            sp.traceSheetEL?.setAttribute('mode', 'hidden');
564            sp.removeLinkLinesByBusinessType('janks', 'task');
565        }
566    }
567}
568function smartEventSubscribe(sp: SpSystemTrace) {
569    window.subscribe(window.SmartEvent.UI.SliceMark, (data) => sp.sliceMarkEventHandler(data));
570    window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => {});
571    window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => sp.refreshCanvas(false));
572    window.subscribe(window.SmartEvent.UI.KeyboardEnable, (tr) => {
573        sp.keyboardEnable = tr.enable;
574        if (!sp.keyboardEnable) {
575            sp.stopWASD();
576        }
577    });
578    window.subscribe(window.SmartEvent.UI.CollapseAllLane, (collapse: boolean) => {
579        if (!collapse) {
580            // 一键折叠之前,记录当前打开的泳道图
581            sp.expandRowList =
582              Array.from(sp.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[folder][expansion]`)) || [];
583        }
584        sp.collapseAll = true;
585        sp.setAttribute('disable', '');
586        sp.expandRowList!.forEach((it) => (it.expansion = collapse));
587        sp.collapseAll = false;
588        sp.removeAttribute('disable');
589        sp.refreshCanvas(true);
590    });
591    window.subscribe(window.SmartEvent.UI.MouseEventEnable, (tr) => {
592        sp.mouseEventEnable = tr.mouseEnable;
593        if (sp.mouseEventEnable) {
594            sp.removeAttribute('disable');
595        } else {
596            sp.setAttribute('disable', '');
597        }
598    });
599    window.subscribe(window.SmartEvent.UI.CollectGroupChange, (group: string) => sp.currentCollectGroup = group);
600}
601
602export function documentInitEvent(sp:SpSystemTrace) : void{
603    if (!document) {
604        return
605    }
606    document.addEventListener('triangle-flag', triangleFlagHandler(sp));
607    document.addEventListener('number_calibration', numberCalibrationHandler(sp));
608    document.addEventListener('flag-change', flagChangeHandler(sp));
609    document.addEventListener('slices-change', slicesChangeHandler(sp));
610    if (sp.timerShaftEL?.collecBtn) {
611        sp.timerShaftEL.collecBtn.onclick = () => {
612            if (sp.timerShaftEL!.collecBtn!.hasAttribute('close')) {
613                sp.timerShaftEL!.collecBtn!.removeAttribute('close');
614                sp.favoriteChartListEL?.showCollectArea();
615            } else {
616                sp.timerShaftEL!.collecBtn!.setAttribute('close', '');
617                sp.favoriteChartListEL?.hideCollectArea();
618            }
619        };
620    }
621    document.addEventListener('collect', collectHandler(sp));
622}
623
624export function spSystemTraceInitElement(sp:SpSystemTrace){
625    window.subscribe(window.SmartEvent.UI.LoadFinishFrame, () => sp.drawAllLines());
626    sp.traceSheetEL = sp.shadowRoot?.querySelector<TraceSheet>('.trace-sheet');
627    if (!sp || !sp.shadowRoot || !sp.traceSheetEL){
628        return;
629    }
630    let rightButton: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot
631      ?.querySelector('#current-selection > tabpane-current-selection')
632      ?.shadowRoot?.querySelector('#rightButton');
633    let rightStar: HTMLElement | null | undefined =sp.traceSheetEL.shadowRoot
634      ?.querySelector('#current-selection > tabpane-current-selection')
635      ?.shadowRoot?.querySelector('#right-star');
636    sp.tipEL = sp.shadowRoot.querySelector<HTMLDivElement>('.tip');
637    sp.rowsPaneEL = sp.shadowRoot.querySelector<HTMLDivElement>('.rows-pane');
638    sp.rowsEL = sp.rowsPaneEL;
639    sp.spacerEL = sp.shadowRoot.querySelector<HTMLDivElement>('.spacer');
640    sp.timerShaftEL = sp.shadowRoot.querySelector<TimerShaftElement>('.timer-shaft');
641    sp.favoriteChartListEL = sp.shadowRoot.querySelector<SpChartList>('#favorite-chart-list');
642    if (!sp.traceSheetEL.shadowRoot){
643        return;
644    }
645    sp.tabCpuFreq = sp.traceSheetEL.shadowRoot.querySelector<TabPaneFrequencySample>('tabpane-frequency-sample');
646    sp.tabCpuState = sp.traceSheetEL.shadowRoot.querySelector<TabPaneCounterSample>('tabpane-counter-sample');
647    sp.rangeSelect = new RangeSelect(sp);
648    rightButton?.addEventListener('click', rightButtonOnClick(sp,rightStar));
649    rightStar?.addEventListener('click', rightStarOnClick(sp));
650    documentInitEvent(sp);
651    SpSystemTrace.scrollViewWidth = sp.getScrollWidth();
652    selectHandler(sp);
653    observerHandler(sp);
654    window.addEventListener('keydown', windowKeyDownHandler(sp));
655    sp.chartManager = new SpChartManager(sp);
656    sp.canvasPanel = sp.shadowRoot.querySelector<HTMLCanvasElement>('#canvas-panel')!;
657    sp.canvasPanelCtx = sp.canvasPanel.getContext('2d');
658    sp.canvasFavoritePanelCtx = sp.favoriteChartListEL!.context();
659    sp.canvasPanelConfig();
660    smartEventSubscribe(sp);
661}
662
663function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: any) {
664    sp.moveRangeToCenter(findEntry.startTime!, findEntry.dur!);
665    sp.queryAllTraceRow().forEach((item) => {
666        item.highlight = false;
667    });
668    if (findEntry.type == 'cpu') {
669        findEntryTypeCpu(sp, findEntry);
670    } else if (findEntry.type == 'func') {
671        findEntryTypeFunc(sp, findEntry);
672    } else if (findEntry.type == 'thread||process') {
673        findEntryTypeThreadProcess(sp, findEntry);
674    } else if (findEntry.type == 'sdk') {
675        findEntryTypeSdk(sp, findEntry);
676    }
677    sp.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted');
678}
679
680export function spSystemTraceShowStruct(sp:SpSystemTrace,previous: boolean, currentIndex: number, structs: Array<any>, retargetIndex?: number){
681    if (structs.length == 0) {
682        return 0;
683    }
684    let findIndex = spSystemTraceShowStructFindIndex(sp,previous,currentIndex,structs,retargetIndex);
685    let findEntry: any;
686    if (findIndex >= 0) {
687        findEntry = structs[findIndex];
688    } else {
689        if (previous) {
690            for (let i = structs.length - 1; i >= 0; i--) {
691                let it = structs[i];
692                if (it.startTime! + it.dur! < TraceRow.range!.startNS) {
693                    findIndex = i;
694                    break;
695                }
696            }
697            if (findIndex == -1) {
698                findIndex = structs.length - 1;
699            }
700        } else {
701            findIndex = structs.findIndex((it) => it.startTime! > TraceRow.range!.endNS);
702            if (findIndex == -1) {
703                findIndex = 0;
704            }
705        }
706        findEntry = structs[findIndex];
707    }
708    moveRangeToCenterAndHighlight(sp, findEntry);
709    return findIndex;
710}
711function spSystemTraceShowStructFindIndex(sp: SpSystemTrace,  previous: boolean, currentIndex: number, structs: Array<any>, retargetIndex: number | undefined) {
712    let findIndex = -1;
713    if (previous) {
714        if (retargetIndex) {
715            findIndex = retargetIndex - 1;
716        } else {
717            for (let i = structs.length - 1; i >= 0; i--) {
718                let it = structs[i];
719                if (
720                  i < currentIndex
721                ) {
722                    findIndex = i;
723                    break;
724                }
725            }
726        }
727    } else {
728        if (currentIndex == -1) {
729            findIndex = 0;
730        } else {
731            findIndex = structs.findIndex((it, idx) => {
732                return (
733                  idx > currentIndex
734                );
735            });
736        }
737    }
738    return findIndex;
739}
740function findEntryTypeCpu(sp: SpSystemTrace, findEntry: any) {
741    CpuStruct.selectCpuStruct = findEntry;
742    CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct;
743    sp.queryAllTraceRow(`trace-row[row-type='cpu-data']`, (row) => row.rowType === 'cpu-data').forEach((item) => {
744        if (item.rowId === `${findEntry.cpu}`) {
745            sp.rechargeCpuData(
746              findEntry,
747              item.dataListCache.find((it) => it.startTime > findEntry.startTime)
748            );
749            item.fixedList = [findEntry];
750        }
751        item.highlight = item.rowId == `${findEntry.cpu}`;
752        item.draw(true);
753    });
754    sp.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true);
755    sp.onClickHandler(TraceRow.ROW_TYPE_CPU);
756}
757function findEntryTypeFunc(sp: SpSystemTrace, findEntry: any) {
758    sp.observerScrollHeightEnable = true;
759    sp.moveRangeToCenter(findEntry.startTime!, findEntry.dur!);
760    sp.scrollToActFunc(
761      {
762          startTs: findEntry.startTime,
763          dur: findEntry.dur,
764          tid: findEntry.tid,
765          pid: findEntry.pid,
766          depth: findEntry.depth,
767          argsetid: findEntry.argsetid,
768          funName: findEntry.funName,
769          cookie: findEntry.cookie,
770      },
771      true
772    );
773}
774function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: any) {
775    let threadProcessRow = sp.rowsEL?.querySelectorAll<TraceRow<ThreadStruct>>('trace-row')[0];
776    if (threadProcessRow) {
777        let filterRow = threadProcessRow.childrenList.filter(
778          (row) => row.rowId === findEntry.rowId && row.rowId === findEntry.rowType
779        )[0];
780        filterRow!.highlight = true;
781        sp.closeAllExpandRows(findEntry.rowParentId);
782        sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true);
783        let completeEntry = () => {
784            sp.hoverStructNull();
785            sp.selectStructNull();
786            sp.wakeupListNull();
787            sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true);
788        };
789        if (filterRow!.isComplete) {
790            completeEntry();
791        } else {
792            filterRow!.onComplete = completeEntry;
793        }
794    }
795}
796function findEntryTypeSdk(sp: SpSystemTrace, findEntry: any) {
797    let parentRow = sp.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-type='sdk'][folder]`);
798    if (parentRow) {
799        let sdkRow = parentRow.childrenList.filter(
800          (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType
801        )[0];
802        sdkRow!.highlight = true;
803    }
804    sp.hoverStructNull();
805    sp.selectStructNull();
806    sp.wakeupListNull();
807    sp.onClickHandler(findEntry.rowType!);
808    sp.closeAllExpandRows(findEntry.rowParentId);
809    sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true);
810}
811async function spSystemTraceInitBuffer(sp:SpSystemTrace,param:{buf?:ArrayBuffer;Url?:string},wasmConfigUri:string,progress:Function) {
812    if (param.buf) {
813        let configJson = '';
814        try {
815            configJson = await fetch(wasmConfigUri).then((res) => res.text());
816        } catch (e) {
817            error('getWasmConfigFailed', e);
818        }
819        let parseConfig = FlagsConfig.getSpTraceStreamParseConfig();
820        let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, parseConfig, configJson, progress);
821        if (!status) {
822            return { status: false, msg: msg };
823        }
824        SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap == undefined ? undefined : sdkConfigMap;
825        return null
826    }else{
827        return null;
828    }
829}
830async function spSystemTraceInitUrl(sp:SpSystemTrace,param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) {
831    if (param.url) {
832        let { status, msg } = await threadPool.initServer(param.url, progress);
833        if (!status) {
834            return { status: false, msg: msg };
835        }else{
836            return null;
837        }
838    }else{
839        return null;
840    }
841}
842export async function spSystemTraceInit(sp:SpSystemTrace,param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) {
843    progress('Load database', 6);
844    sp.rowsPaneEL!.scroll({top: 0, left: 0});
845    let rsBuf = await spSystemTraceInitBuffer(sp,param,wasmConfigUri,progress);
846    if (rsBuf) {
847        return rsBuf;
848    }
849    let rsUrl = await spSystemTraceInitUrl(sp,param,wasmConfigUri,progress);
850    if (rsUrl) {
851        return rsUrl;
852    }
853    await sp.chartManager?.init(progress);
854    let rowId: string = '';
855    sp.rowsEL?.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => {
856        if (it.name.includes('Ark Ts')) {
857            rowId = it.rowId!;
858        }
859        if (it.folder) it.addEventListener('expansion-change', sp.extracted(it));
860    });
861    progress('completed', 100);
862    info('All TraceRow Data initialized');
863    sp.loadTraceCompleted = true;
864    sp.rowsEL!.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => {
865        if (rowId !== '' && (it.rowId?.includes(rowId) || it.name.includes(rowId))) {
866            it.addTemplateTypes('Ark Ts');
867            for (let child of it.childrenList) {
868                child.addTemplateTypes('Ark Ts');
869            }
870        }
871        if (it.folder) {
872            let offsetYTimeOut: any = undefined;
873            it.addEventListener('expansion-change', expansionChangeHandler(sp,offsetYTimeOut));
874        }
875        if (sp.loadTraceCompleted) {
876            sp.traceSheetEL?.displaySystemLogsData();
877        }
878        sp.intersectionObserver?.observe(it);
879    });
880    return { status: true, msg: 'success' };
881}
882function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: any) {
883    return function (event: any) {
884        let max = [...sp.rowsPaneEL!.querySelectorAll('trace-row')].reduce(
885          (pre, cur) => pre + cur.clientHeight!, 0);
886        let offset = sp.rowsPaneEL!.scrollHeight - max;
887        sp.rowsPaneEL!.scrollTop = sp.rowsPaneEL!.scrollTop - offset;
888        JankStruct.delJankLineFlag = false;
889        if (offsetYTimeOut) {
890            clearTimeout(offsetYTimeOut);
891        }
892        if (event.detail.expansion) {
893            offsetYTimeOut = setTimeout(() => {
894                sp.linkNodes.forEach((linkNode) => {
895                    JankStruct.selectJankStructList?.forEach((selectStruct: any) => {
896                        if (event.detail.rowId == selectStruct.pid) {
897                            JankStruct.selectJankStruct = selectStruct;
898                            JankStruct.hoverJankStruct = selectStruct;
899                        }
900                    });
901                    linkNodeHandler(linkNode, sp);
902                });
903            }, 300);
904        } else {
905            if (JankStruct!.selectJankStruct) {
906                JankStruct.selectJankStructList?.push(<JankStruct>JankStruct!.selectJankStruct);
907            }
908            offsetYTimeOut = setTimeout(() => {
909                sp.linkNodes?.forEach((linkNode) => linkNodeHandler(linkNode, sp));
910            }, 300);
911        }
912        let refreshTimeOut = setTimeout(() => {
913            sp.refreshCanvas(true);
914            clearTimeout(refreshTimeOut);
915        }, 360);
916    }
917}
918function linkNodeHandler(linkNode: PairPoint[], sp: SpSystemTrace){
919    if (linkNode[0].rowEL.collect) {
920        linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195;
921    } else {
922        linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
923    }
924    linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY;
925    if (linkNode[1].rowEL.collect) {
926        linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195;
927    } else {
928        linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop;
929    }
930    linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY;
931}
932
933
934const eventMap = {
935    'cpu-data': 'Cpu',
936    'cpu-state': 'Cpu State',
937    'cpu-freq': 'Cpu Frequency',
938    'cpu-limit-freq': 'Cpu Freq Limit',
939    'process': 'Process',
940    'native-memory': 'Native Memory',
941    'thread': 'Thread',
942    'func': 'Func',
943    'mem': 'Memory',
944    'virtual-memory-cell': 'Virtual Memory',
945    'virtual-memory-group': 'Virtual Memory',
946    'fps': 'FPS',
947    'ability-monitor': 'Ability Monitor',
948    'cpu-ability': 'Cpu Ability',
949    'memory-ability': 'Memory Ability',
950    'disk-ability': 'DiskIO Ability',
951    'network-ability': 'Network Ability',
952    'sdk': 'Sdk',
953    'sdk-counter': 'SDK Counter',
954    'sdk-slice': 'Sdk Slice',
955    'energy': 'Energy',
956    'power-energy': 'Power Event',
957    'system-energy': 'System Event',
958    'anomaly-energy': 'Anomaly Event',
959    'clock-group': 'Clocks',
960    'clock': 'clock',
961    'irq-group': 'Irqs',
962    'irq': 'irq',
963    'hiperf': 'HiPerf (All)',
964    'hiperf-event': 'HiPerf Event',
965    'hiperf-report': 'HiPerf Report',
966    'hiperf-process': 'HiPerf Process',
967    'hiperf-thread': 'HiPerf Thread',
968    'js-memory': 'Js Memory',
969}
970export function spSystemTraceInitPointToEvent(sp: SpSystemTrace) {
971    sp.eventMap = eventMap;
972}
973