1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciimport { SpSystemTrace } from '../SpSystemTrace';
17fb726d48Sopenharmony_ciimport { TraceRow } from '../trace/base/TraceRow';
18fb726d48Sopenharmony_ciimport { procedurePool } from '../../database/Procedure';
19fb726d48Sopenharmony_ciimport { EBPFChartStruct, EBPFRender } from '../../database/ui-worker/ProcedureWorkerEBPF';
20fb726d48Sopenharmony_ciimport { ColorUtils } from '../trace/base/ColorUtils';
21fb726d48Sopenharmony_ciimport { Utils } from '../trace/base/Utils';
22fb726d48Sopenharmony_ciimport { renders } from '../../database/ui-worker/ProcedureWorker';
23fb726d48Sopenharmony_ciimport { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU';
24fb726d48Sopenharmony_ciimport { diskIoSender, fileSysVMSender, fileSystemSender } from '../../database/data-trafic/EBPFSender';
25fb726d48Sopenharmony_ciimport { hasFileSysData } from '../../database/sql/Memory.sql';
26fb726d48Sopenharmony_ciimport { getDiskIOProcess } from '../../database/sql/SqlLite.sql';
27fb726d48Sopenharmony_ciimport { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil';
28fb726d48Sopenharmony_ci
29fb726d48Sopenharmony_ciexport class SpEBPFChart {
30fb726d48Sopenharmony_ci  private trace: SpSystemTrace;
31fb726d48Sopenharmony_ci
32fb726d48Sopenharmony_ci  constructor(trace: SpSystemTrace) {
33fb726d48Sopenharmony_ci    this.trace = trace;
34fb726d48Sopenharmony_ci  }
35fb726d48Sopenharmony_ci
36fb726d48Sopenharmony_ci  async init(): Promise<void> {
37fb726d48Sopenharmony_ci    let sys = await hasFileSysData();
38fb726d48Sopenharmony_ci    if (sys.length > 0) {
39fb726d48Sopenharmony_ci      //@ts-ignore
40fb726d48Sopenharmony_ci      let fsCount = sys[0].fsCount ?? 0;
41fb726d48Sopenharmony_ci      //@ts-ignore
42fb726d48Sopenharmony_ci      let vmCount = sys[0].vmCount ?? 0;
43fb726d48Sopenharmony_ci      //@ts-ignore
44fb726d48Sopenharmony_ci      let ioCount = sys[0].ioCount ?? 0;
45fb726d48Sopenharmony_ci      if (sys && sys.length > 0 && (fsCount > 0 || vmCount > 0 || ioCount > 0)) {
46fb726d48Sopenharmony_ci        let folder = await this.initFolder();
47fb726d48Sopenharmony_ci        await this.initFileCallchain();
48fb726d48Sopenharmony_ci        if (fsCount > 0) {
49fb726d48Sopenharmony_ci          await this.initLogicalRead(folder);
50fb726d48Sopenharmony_ci          await this.initLogicalWrite(folder);
51fb726d48Sopenharmony_ci        }
52fb726d48Sopenharmony_ci        if (vmCount > 0) {
53fb726d48Sopenharmony_ci          await this.initVirtualMemoryTrace(folder);
54fb726d48Sopenharmony_ci        }
55fb726d48Sopenharmony_ci        if (ioCount > 0) {
56fb726d48Sopenharmony_ci          await this.initDiskIOLatency(folder);
57fb726d48Sopenharmony_ci          await this.initProcessDiskIOLatency(folder);
58fb726d48Sopenharmony_ci        }
59fb726d48Sopenharmony_ci        // 统计ebpf插件
60fb726d48Sopenharmony_ci        let requsetBody = {
61fb726d48Sopenharmony_ci          eventData: {
62fb726d48Sopenharmony_ci            plugin: ['hiebpf-plugin']
63fb726d48Sopenharmony_ci          }
64fb726d48Sopenharmony_ci        };
65fb726d48Sopenharmony_ci        SpStatisticsHttpUtil.recordPluginUsage(requsetBody);
66fb726d48Sopenharmony_ci      }
67fb726d48Sopenharmony_ci    }
68fb726d48Sopenharmony_ci  }
69fb726d48Sopenharmony_ci
70fb726d48Sopenharmony_ci  async initFileCallchain(): Promise<unknown> {
71fb726d48Sopenharmony_ci    return new Promise<unknown>((resolve, reject) => {
72fb726d48Sopenharmony_ci      procedurePool.submitWithName('logic0', 'fileSystem-init', null, undefined, (res: unknown) => {
73fb726d48Sopenharmony_ci        resolve(res);
74fb726d48Sopenharmony_ci      });
75fb726d48Sopenharmony_ci    });
76fb726d48Sopenharmony_ci  }
77fb726d48Sopenharmony_ci
78fb726d48Sopenharmony_ci  //@ts-ignore
79fb726d48Sopenharmony_ci  async initFolder(): Promise<TraceRow<unknown>> {
80fb726d48Sopenharmony_ci    let fsFolder = TraceRow.skeleton();
81fb726d48Sopenharmony_ci    fsFolder.rowId = 'FileSystem';
82fb726d48Sopenharmony_ci    fsFolder.index = 0;
83fb726d48Sopenharmony_ci    fsFolder.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM_GROUP;
84fb726d48Sopenharmony_ci    fsFolder.rowParentId = '';
85fb726d48Sopenharmony_ci    fsFolder.style.height = '40px';
86fb726d48Sopenharmony_ci    fsFolder.folder = true;
87fb726d48Sopenharmony_ci    fsFolder.name = 'EBPF'; /* & I/O Latency */
88fb726d48Sopenharmony_ci    fsFolder.addTemplateTypes('HiEBpf');
89fb726d48Sopenharmony_ci    fsFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler;
90fb726d48Sopenharmony_ci    fsFolder.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore
91fb726d48Sopenharmony_ci    fsFolder.supplierFrame = (): Promise<Array<unknown>> => new Promise<Array<unknown>>((resolve) => resolve([]));
92fb726d48Sopenharmony_ci    fsFolder.onThreadHandler = (useCache): void => {
93fb726d48Sopenharmony_ci      fsFolder.canvasSave(this.trace.canvasPanelCtx!);
94fb726d48Sopenharmony_ci      if (fsFolder.expansion) {
95fb726d48Sopenharmony_ci        // @ts-ignore
96fb726d48Sopenharmony_ci        this.trace.canvasPanelCtx?.clearRect(0, 0, fsFolder.frame.width, fsFolder.frame.height);
97fb726d48Sopenharmony_ci      } else {
98fb726d48Sopenharmony_ci        (renders.empty as EmptyRender).renderMainThread(
99fb726d48Sopenharmony_ci          {
100fb726d48Sopenharmony_ci            context: this.trace.canvasPanelCtx,
101fb726d48Sopenharmony_ci            useCache: useCache,
102fb726d48Sopenharmony_ci            type: '',
103fb726d48Sopenharmony_ci          },
104fb726d48Sopenharmony_ci          fsFolder
105fb726d48Sopenharmony_ci        );
106fb726d48Sopenharmony_ci      }
107fb726d48Sopenharmony_ci      fsFolder.canvasRestore(this.trace.canvasPanelCtx!, this.trace);
108fb726d48Sopenharmony_ci    };
109fb726d48Sopenharmony_ci    this.trace.rowsEL?.appendChild(fsFolder);
110fb726d48Sopenharmony_ci    return fsFolder;
111fb726d48Sopenharmony_ci  }
112fb726d48Sopenharmony_ci
113fb726d48Sopenharmony_ci  //@ts-ignore
114fb726d48Sopenharmony_ci  async initLogicalRead(folder: TraceRow<unknown>): Promise<void> {
115fb726d48Sopenharmony_ci    let logicalReadRow = TraceRow.skeleton<EBPFChartStruct>();
116fb726d48Sopenharmony_ci    logicalReadRow.rowId = 'FileSystemLogicalRead';
117fb726d48Sopenharmony_ci    logicalReadRow.index = 1;
118fb726d48Sopenharmony_ci    logicalReadRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM;
119fb726d48Sopenharmony_ci    logicalReadRow.rowParentId = folder.rowId;
120fb726d48Sopenharmony_ci    logicalReadRow.rowHidden = !folder.expansion;
121fb726d48Sopenharmony_ci    logicalReadRow.style.height = '40px';
122fb726d48Sopenharmony_ci    logicalReadRow.setAttribute('children', '');
123fb726d48Sopenharmony_ci    logicalReadRow.name = 'FileSystem Logical Read';
124fb726d48Sopenharmony_ci    logicalReadRow.supplierFrame = async (): Promise<EBPFChartStruct[]> => {
125fb726d48Sopenharmony_ci      const res = await fileSystemSender(2, TraceRow.range?.scale || 50, logicalReadRow);
126fb726d48Sopenharmony_ci      return res;
127fb726d48Sopenharmony_ci    };
128fb726d48Sopenharmony_ci    logicalReadRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
129fb726d48Sopenharmony_ci    logicalReadRow.selectChangeHandler = this.trace.selectChangeHandler;
130fb726d48Sopenharmony_ci    logicalReadRow.focusHandler = (): void => this.focusHandler(logicalReadRow);
131fb726d48Sopenharmony_ci    logicalReadRow.findHoverStruct = (): void => {
132fb726d48Sopenharmony_ci      EBPFChartStruct.hoverEBPFStruct = logicalReadRow.getHoverStruct(false);
133fb726d48Sopenharmony_ci    };
134fb726d48Sopenharmony_ci    logicalReadRow.onThreadHandler = (useCache): void => {
135fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
136fb726d48Sopenharmony_ci      if (logicalReadRow.currentContext) {
137fb726d48Sopenharmony_ci        context = logicalReadRow.currentContext;
138fb726d48Sopenharmony_ci      } else {
139fb726d48Sopenharmony_ci        context = logicalReadRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
140fb726d48Sopenharmony_ci      }
141fb726d48Sopenharmony_ci      logicalReadRow.canvasSave(context);
142fb726d48Sopenharmony_ci      //@ts-ignore
143fb726d48Sopenharmony_ci      (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread(
144fb726d48Sopenharmony_ci        {
145fb726d48Sopenharmony_ci          context: context,
146fb726d48Sopenharmony_ci          useCache: useCache,
147fb726d48Sopenharmony_ci          type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-logical-read`,
148fb726d48Sopenharmony_ci          chartColor: ColorUtils.MD_PALETTE[0],
149fb726d48Sopenharmony_ci        },
150fb726d48Sopenharmony_ci        logicalReadRow
151fb726d48Sopenharmony_ci      );
152fb726d48Sopenharmony_ci      logicalReadRow.canvasRestore(context, this.trace);
153fb726d48Sopenharmony_ci    };
154fb726d48Sopenharmony_ci    folder.addChildTraceRow(logicalReadRow);
155fb726d48Sopenharmony_ci  }
156fb726d48Sopenharmony_ci
157fb726d48Sopenharmony_ci  //@ts-ignore
158fb726d48Sopenharmony_ci  async initLogicalWrite(folder: TraceRow<unknown>): Promise<void> {
159fb726d48Sopenharmony_ci    let logicalWriteRow = TraceRow.skeleton<EBPFChartStruct>();
160fb726d48Sopenharmony_ci    logicalWriteRow.rowId = 'FileSystemLogicalWrite';
161fb726d48Sopenharmony_ci    logicalWriteRow.index = 2;
162fb726d48Sopenharmony_ci    logicalWriteRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM;
163fb726d48Sopenharmony_ci    logicalWriteRow.rowParentId = folder.rowId;
164fb726d48Sopenharmony_ci    logicalWriteRow.rowHidden = !folder.expansion;
165fb726d48Sopenharmony_ci    logicalWriteRow.style.height = '40px';
166fb726d48Sopenharmony_ci    logicalWriteRow.setAttribute('children', '');
167fb726d48Sopenharmony_ci    logicalWriteRow.name = 'FileSystem Logical Write';
168fb726d48Sopenharmony_ci    logicalWriteRow.supplierFrame = async (): Promise<EBPFChartStruct[]> => {
169fb726d48Sopenharmony_ci      const res = await fileSystemSender(3, TraceRow.range?.scale || 50, logicalWriteRow);
170fb726d48Sopenharmony_ci      return res;
171fb726d48Sopenharmony_ci    };
172fb726d48Sopenharmony_ci    logicalWriteRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
173fb726d48Sopenharmony_ci    logicalWriteRow.selectChangeHandler = this.trace.selectChangeHandler;
174fb726d48Sopenharmony_ci    logicalWriteRow.focusHandler = (): void => this.focusHandler(logicalWriteRow);
175fb726d48Sopenharmony_ci    logicalWriteRow.findHoverStruct = (): void => {
176fb726d48Sopenharmony_ci      EBPFChartStruct.hoverEBPFStruct = logicalWriteRow.getHoverStruct(false);
177fb726d48Sopenharmony_ci    };
178fb726d48Sopenharmony_ci    logicalWriteRow.onThreadHandler = (useCache): void => {
179fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
180fb726d48Sopenharmony_ci      if (logicalWriteRow.currentContext) {
181fb726d48Sopenharmony_ci        context = logicalWriteRow.currentContext;
182fb726d48Sopenharmony_ci      } else {
183fb726d48Sopenharmony_ci        context = logicalWriteRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
184fb726d48Sopenharmony_ci      }
185fb726d48Sopenharmony_ci      logicalWriteRow.canvasSave(context);
186fb726d48Sopenharmony_ci      //@ts-ignore
187fb726d48Sopenharmony_ci      (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread(
188fb726d48Sopenharmony_ci        {
189fb726d48Sopenharmony_ci          context: context,
190fb726d48Sopenharmony_ci          useCache: useCache,
191fb726d48Sopenharmony_ci          type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-logical-write`,
192fb726d48Sopenharmony_ci          chartColor: ColorUtils.MD_PALETTE[8],
193fb726d48Sopenharmony_ci        },
194fb726d48Sopenharmony_ci        logicalWriteRow
195fb726d48Sopenharmony_ci      );
196fb726d48Sopenharmony_ci      logicalWriteRow.canvasRestore(context, this.trace);
197fb726d48Sopenharmony_ci    };
198fb726d48Sopenharmony_ci    folder.addChildTraceRow(logicalWriteRow);
199fb726d48Sopenharmony_ci  }
200fb726d48Sopenharmony_ci
201fb726d48Sopenharmony_ci  //@ts-ignore
202fb726d48Sopenharmony_ci  async initDiskIOLatency(folder: TraceRow<unknown>): Promise<void> {
203fb726d48Sopenharmony_ci    let diskIoRow = TraceRow.skeleton<EBPFChartStruct>();
204fb726d48Sopenharmony_ci    diskIoRow.rowId = 'FileSystemDiskIOLatency';
205fb726d48Sopenharmony_ci    diskIoRow.index = 4;
206fb726d48Sopenharmony_ci    diskIoRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM;
207fb726d48Sopenharmony_ci    diskIoRow.rowParentId = folder.rowId;
208fb726d48Sopenharmony_ci    diskIoRow.rowHidden = !folder.expansion;
209fb726d48Sopenharmony_ci    diskIoRow.style.height = '40px';
210fb726d48Sopenharmony_ci    diskIoRow.style.width = '100%';
211fb726d48Sopenharmony_ci    diskIoRow.setAttribute('children', '');
212fb726d48Sopenharmony_ci    diskIoRow.name = 'Disk I/O Latency';
213fb726d48Sopenharmony_ci    diskIoRow.supplierFrame = async (): Promise<EBPFChartStruct[]> => {
214fb726d48Sopenharmony_ci      const res = await diskIoSender(true, 0, [1, 2, 3, 4], TraceRow.range?.scale || 50, diskIoRow);
215fb726d48Sopenharmony_ci      return res;
216fb726d48Sopenharmony_ci    };
217fb726d48Sopenharmony_ci    diskIoRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
218fb726d48Sopenharmony_ci    diskIoRow.selectChangeHandler = this.trace.selectChangeHandler;
219fb726d48Sopenharmony_ci    diskIoRow.focusHandler = (): void => this.focusHandler(diskIoRow);
220fb726d48Sopenharmony_ci    diskIoRow.findHoverStruct = (): void => {
221fb726d48Sopenharmony_ci      EBPFChartStruct.hoverEBPFStruct = diskIoRow.getHoverStruct(false);
222fb726d48Sopenharmony_ci    };
223fb726d48Sopenharmony_ci    diskIoRow.onThreadHandler = (useCache): void => {
224fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
225fb726d48Sopenharmony_ci      if (diskIoRow.currentContext) {
226fb726d48Sopenharmony_ci        context = diskIoRow.currentContext;
227fb726d48Sopenharmony_ci      } else {
228fb726d48Sopenharmony_ci        context = diskIoRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
229fb726d48Sopenharmony_ci      }
230fb726d48Sopenharmony_ci      diskIoRow.canvasSave(context);
231fb726d48Sopenharmony_ci      //@ts-ignore
232fb726d48Sopenharmony_ci      (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread(
233fb726d48Sopenharmony_ci        {
234fb726d48Sopenharmony_ci          context: context,
235fb726d48Sopenharmony_ci          useCache: useCache,
236fb726d48Sopenharmony_ci          type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io`,
237fb726d48Sopenharmony_ci          chartColor: ColorUtils.MD_PALETTE[0],
238fb726d48Sopenharmony_ci        },
239fb726d48Sopenharmony_ci        diskIoRow
240fb726d48Sopenharmony_ci      );
241fb726d48Sopenharmony_ci      diskIoRow.canvasRestore(context, this.trace);
242fb726d48Sopenharmony_ci    };
243fb726d48Sopenharmony_ci    folder.addChildTraceRow(diskIoRow);
244fb726d48Sopenharmony_ci  }
245fb726d48Sopenharmony_ci
246fb726d48Sopenharmony_ci  //@ts-ignore
247fb726d48Sopenharmony_ci  initProcessDiskIOLatencyRead(i: number, folder: TraceRow<unknown>, process: unknown): TraceRow<EBPFChartStruct> {
248fb726d48Sopenharmony_ci    let rowRead = TraceRow.skeleton<EBPFChartStruct>();
249fb726d48Sopenharmony_ci    rowRead.index = 5 + 2 * i; //@ts-ignore
250fb726d48Sopenharmony_ci    rowRead.rowId = `FileSystemDiskIOLatency-read-${process.ipid}`;
251fb726d48Sopenharmony_ci    rowRead.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM;
252fb726d48Sopenharmony_ci    rowRead.rowParentId = folder.rowId;
253fb726d48Sopenharmony_ci    rowRead.rowHidden = !folder.expansion;
254fb726d48Sopenharmony_ci    rowRead.style.height = '40px';
255fb726d48Sopenharmony_ci    rowRead.style.width = '100%';
256fb726d48Sopenharmony_ci    rowRead.setAttribute('children', ''); //@ts-ignore
257fb726d48Sopenharmony_ci    rowRead.name = `${process.name ?? 'Process'}(${process.ipid}) Max Read Latency`;
258fb726d48Sopenharmony_ci    rowRead.supplierFrame = async (): Promise<EBPFChartStruct[]> => {
259fb726d48Sopenharmony_ci      //@ts-ignore
260fb726d48Sopenharmony_ci      const res = await diskIoSender(false, process.ipid, [1, 3], TraceRow.range?.scale || 50, rowRead);
261fb726d48Sopenharmony_ci      return res;
262fb726d48Sopenharmony_ci    };
263fb726d48Sopenharmony_ci    rowRead.favoriteChangeHandler = this.trace.favoriteChangeHandler;
264fb726d48Sopenharmony_ci    rowRead.selectChangeHandler = this.trace.selectChangeHandler;
265fb726d48Sopenharmony_ci    rowRead.focusHandler = (): void => this.focusHandler(rowRead);
266fb726d48Sopenharmony_ci    rowRead.findHoverStruct = (): void => {
267fb726d48Sopenharmony_ci      EBPFChartStruct.hoverEBPFStruct = rowRead.getHoverStruct(false);
268fb726d48Sopenharmony_ci    };
269fb726d48Sopenharmony_ci    rowRead.onThreadHandler = (useCache): void => {
270fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
271fb726d48Sopenharmony_ci      if (rowRead.currentContext) {
272fb726d48Sopenharmony_ci        context = rowRead.currentContext;
273fb726d48Sopenharmony_ci      } else {
274fb726d48Sopenharmony_ci        context = rowRead.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
275fb726d48Sopenharmony_ci      }
276fb726d48Sopenharmony_ci      rowRead.canvasSave(context);
277fb726d48Sopenharmony_ci      //@ts-ignore
278fb726d48Sopenharmony_ci      (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread(
279fb726d48Sopenharmony_ci        {
280fb726d48Sopenharmony_ci          context: context,
281fb726d48Sopenharmony_ci          useCache: useCache, //@ts-ignore
282fb726d48Sopenharmony_ci          type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-read-${process.pid}`,
283fb726d48Sopenharmony_ci          chartColor: ColorUtils.MD_PALETTE[0],
284fb726d48Sopenharmony_ci        },
285fb726d48Sopenharmony_ci        rowRead
286fb726d48Sopenharmony_ci      );
287fb726d48Sopenharmony_ci      rowRead.canvasRestore(context, this.trace);
288fb726d48Sopenharmony_ci    };
289fb726d48Sopenharmony_ci    return rowRead;
290fb726d48Sopenharmony_ci  }
291fb726d48Sopenharmony_ci
292fb726d48Sopenharmony_ci  //@ts-ignore
293fb726d48Sopenharmony_ci  private initProcessDiskIOWrite(i: number, folder: TraceRow<unknown>, process: unknown): TraceRow<EBPFChartStruct> {
294fb726d48Sopenharmony_ci    let rowWrite = TraceRow.skeleton<EBPFChartStruct>();
295fb726d48Sopenharmony_ci    rowWrite.index = 5 + 2 * i + 1; //@ts-ignore
296fb726d48Sopenharmony_ci    rowWrite.rowId = `FileSystemDiskIOLatency-write-${process.ipid}`;
297fb726d48Sopenharmony_ci    rowWrite.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM;
298fb726d48Sopenharmony_ci    rowWrite.rowParentId = folder.rowId;
299fb726d48Sopenharmony_ci    rowWrite.rowHidden = !folder.expansion;
300fb726d48Sopenharmony_ci    rowWrite.style.height = '40px';
301fb726d48Sopenharmony_ci    rowWrite.style.width = '100%';
302fb726d48Sopenharmony_ci    rowWrite.setAttribute('children', ''); //@ts-ignore
303fb726d48Sopenharmony_ci    rowWrite.name = `${process.name ?? 'Process'}(${process.pid}) Max Write Latency`;
304fb726d48Sopenharmony_ci    rowWrite.supplierFrame = async (): Promise<EBPFChartStruct[]> => {
305fb726d48Sopenharmony_ci      //@ts-ignore
306fb726d48Sopenharmony_ci      const res = await diskIoSender(false, process.ipid, [2, 4], TraceRow.range?.scale || 50, rowWrite);
307fb726d48Sopenharmony_ci      return res;
308fb726d48Sopenharmony_ci    };
309fb726d48Sopenharmony_ci    rowWrite.favoriteChangeHandler = this.trace.favoriteChangeHandler;
310fb726d48Sopenharmony_ci    rowWrite.selectChangeHandler = this.trace.selectChangeHandler;
311fb726d48Sopenharmony_ci    rowWrite.focusHandler = (): void => this.focusHandler(rowWrite);
312fb726d48Sopenharmony_ci    rowWrite.findHoverStruct = (): void => {
313fb726d48Sopenharmony_ci      EBPFChartStruct.hoverEBPFStruct = rowWrite.getHoverStruct(false);
314fb726d48Sopenharmony_ci    };
315fb726d48Sopenharmony_ci    rowWrite.onThreadHandler = (useCache): void => {
316fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
317fb726d48Sopenharmony_ci      if (rowWrite.currentContext) {
318fb726d48Sopenharmony_ci        context = rowWrite.currentContext;
319fb726d48Sopenharmony_ci      } else {
320fb726d48Sopenharmony_ci        context = rowWrite.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
321fb726d48Sopenharmony_ci      }
322fb726d48Sopenharmony_ci      rowWrite.canvasSave(context);
323fb726d48Sopenharmony_ci      //@ts-ignore
324fb726d48Sopenharmony_ci      (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread(
325fb726d48Sopenharmony_ci        {
326fb726d48Sopenharmony_ci          context: context,
327fb726d48Sopenharmony_ci          useCache: useCache, //@ts-ignore
328fb726d48Sopenharmony_ci          type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-write-${process.pid}`,
329fb726d48Sopenharmony_ci          chartColor: ColorUtils.MD_PALETTE[8],
330fb726d48Sopenharmony_ci        },
331fb726d48Sopenharmony_ci        rowWrite
332fb726d48Sopenharmony_ci      );
333fb726d48Sopenharmony_ci      rowWrite.canvasRestore(context, this.trace);
334fb726d48Sopenharmony_ci    };
335fb726d48Sopenharmony_ci    return rowWrite;
336fb726d48Sopenharmony_ci  }
337fb726d48Sopenharmony_ci
338fb726d48Sopenharmony_ci  //@ts-ignore
339fb726d48Sopenharmony_ci  async initProcessDiskIOLatency(folder: TraceRow<unknown>): Promise<void> {
340fb726d48Sopenharmony_ci    let processes = (await getDiskIOProcess()) || [];
341fb726d48Sopenharmony_ci    for (let i = 0, len = processes.length; i < len; i++) {
342fb726d48Sopenharmony_ci      let process = processes[i];
343fb726d48Sopenharmony_ci      const rowRead = this.initProcessDiskIOLatencyRead(i, folder, process);
344fb726d48Sopenharmony_ci      folder.addChildTraceRow(rowRead);
345fb726d48Sopenharmony_ci      const rowWrite = this.initProcessDiskIOWrite(i, folder, process);
346fb726d48Sopenharmony_ci      folder.addChildTraceRow(rowWrite);
347fb726d48Sopenharmony_ci    }
348fb726d48Sopenharmony_ci  }
349fb726d48Sopenharmony_ci
350fb726d48Sopenharmony_ci  //@ts-ignore
351fb726d48Sopenharmony_ci  async initVirtualMemoryTrace(folder: TraceRow<unknown>): Promise<void> {
352fb726d48Sopenharmony_ci    let vmTraceRow = TraceRow.skeleton<EBPFChartStruct>();
353fb726d48Sopenharmony_ci    vmTraceRow.rowId = 'FileSystemVirtualMemory';
354fb726d48Sopenharmony_ci    vmTraceRow.index = 3;
355fb726d48Sopenharmony_ci    vmTraceRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM;
356fb726d48Sopenharmony_ci    vmTraceRow.rowParentId = folder.rowId;
357fb726d48Sopenharmony_ci    vmTraceRow.rowHidden = !folder.expansion;
358fb726d48Sopenharmony_ci    vmTraceRow.rangeSelect = true;
359fb726d48Sopenharmony_ci    vmTraceRow.style.height = '40px';
360fb726d48Sopenharmony_ci    vmTraceRow.style.width = '100%';
361fb726d48Sopenharmony_ci    vmTraceRow.setAttribute('children', '');
362fb726d48Sopenharmony_ci    vmTraceRow.name = 'Page Fault Trace';
363fb726d48Sopenharmony_ci    vmTraceRow.supplierFrame = async (): Promise<EBPFChartStruct[]> => {
364fb726d48Sopenharmony_ci      const res = await fileSysVMSender(TraceRow.range?.scale || 50, vmTraceRow);
365fb726d48Sopenharmony_ci      return res;
366fb726d48Sopenharmony_ci    };
367fb726d48Sopenharmony_ci    vmTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
368fb726d48Sopenharmony_ci    vmTraceRow.selectChangeHandler = this.trace.selectChangeHandler;
369fb726d48Sopenharmony_ci    vmTraceRow.focusHandler = (): void => this.focusHandler(vmTraceRow);
370fb726d48Sopenharmony_ci    vmTraceRow.findHoverStruct = (): void => {
371fb726d48Sopenharmony_ci      EBPFChartStruct.hoverEBPFStruct = vmTraceRow.getHoverStruct(false, false, 'size');
372fb726d48Sopenharmony_ci    };
373fb726d48Sopenharmony_ci    vmTraceRow.onThreadHandler = (useCache): void => {
374fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D;
375fb726d48Sopenharmony_ci      if (vmTraceRow.currentContext) {
376fb726d48Sopenharmony_ci        context = vmTraceRow.currentContext;
377fb726d48Sopenharmony_ci      } else {
378fb726d48Sopenharmony_ci        context = vmTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!;
379fb726d48Sopenharmony_ci      }
380fb726d48Sopenharmony_ci      vmTraceRow.canvasSave(context);
381fb726d48Sopenharmony_ci      //@ts-ignore
382fb726d48Sopenharmony_ci      (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread(
383fb726d48Sopenharmony_ci        {
384fb726d48Sopenharmony_ci          context: context,
385fb726d48Sopenharmony_ci          useCache: useCache,
386fb726d48Sopenharmony_ci          type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-virtual-memory`,
387fb726d48Sopenharmony_ci          chartColor: ColorUtils.MD_PALETTE[0],
388fb726d48Sopenharmony_ci        },
389fb726d48Sopenharmony_ci        vmTraceRow
390fb726d48Sopenharmony_ci      );
391fb726d48Sopenharmony_ci      vmTraceRow.canvasRestore(context, this.trace);
392fb726d48Sopenharmony_ci    };
393fb726d48Sopenharmony_ci    folder.addChildTraceRow(vmTraceRow);
394fb726d48Sopenharmony_ci  }
395fb726d48Sopenharmony_ci
396fb726d48Sopenharmony_ci  focusHandler(row: TraceRow<EBPFChartStruct>): void {
397fb726d48Sopenharmony_ci    let num = 0;
398fb726d48Sopenharmony_ci    let tip = '';
399fb726d48Sopenharmony_ci    if (EBPFChartStruct.hoverEBPFStruct) {
400fb726d48Sopenharmony_ci      num = EBPFChartStruct.hoverEBPFStruct.size ?? 0;
401fb726d48Sopenharmony_ci      let group10Ms = EBPFChartStruct.hoverEBPFStruct.group10Ms ?? false;
402fb726d48Sopenharmony_ci      if (row.rowId!.startsWith('FileSystemDiskIOLatency')) {
403fb726d48Sopenharmony_ci        if (num > 0) {
404fb726d48Sopenharmony_ci          let tipStr = Utils.getProbablyTime(num);
405fb726d48Sopenharmony_ci          if (group10Ms) {
406fb726d48Sopenharmony_ci            tip = `<span>${tipStr} (10.00ms)</span>`;
407fb726d48Sopenharmony_ci          } else {
408fb726d48Sopenharmony_ci            tip = `<span>${tipStr}</span>`;
409fb726d48Sopenharmony_ci          }
410fb726d48Sopenharmony_ci        }
411fb726d48Sopenharmony_ci      } else {
412fb726d48Sopenharmony_ci        if (num > 0) {
413fb726d48Sopenharmony_ci          if (group10Ms) {
414fb726d48Sopenharmony_ci            tip = `<span>${num} (10.00ms)</span>`;
415fb726d48Sopenharmony_ci          } else {
416fb726d48Sopenharmony_ci            tip = `<span>${num}</span>`;
417fb726d48Sopenharmony_ci          }
418fb726d48Sopenharmony_ci        }
419fb726d48Sopenharmony_ci      }
420fb726d48Sopenharmony_ci    }
421fb726d48Sopenharmony_ci    this.trace?.displayTip(row, EBPFChartStruct.hoverEBPFStruct, tip);
422fb726d48Sopenharmony_ci  }
423fb726d48Sopenharmony_ci}
424