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 { TraceRow } from '../../component/trace/base/TraceRow';
17import { BaseStruct, dataFilterHandler, drawLoadingFrame, ns2x, Rect, Render } from './ProcedureWorkerCommon';
18import { ColorUtils } from '../../component/trace/base/ColorUtils';
19
20export class HiSysEventRender extends Render {
21  renderMainThread(
22    req: {
23      useCache: boolean;
24      context: CanvasRenderingContext2D;
25      type: string;
26    },
27    row: TraceRow<HiSysEventStruct>
28  ): void {
29    let hiSysEventFilter = row.dataListCache;
30    let minorFilter: HiSysEventStruct[] = [];
31    let criticalFilter: HiSysEventStruct[] = [];
32    let minorList = hiSysEventFilter.filter((struct) => {
33      return struct.depth === 0;
34    });
35    let criticalList = hiSysEventFilter.filter((struct) => {
36      return struct.depth === 1;
37    });
38    dataFilterHandler(minorList, minorFilter, {
39      startKey: 'ts',
40      durKey: 'dur',
41      startNS: TraceRow.range?.startNS ?? 0,
42      endNS: TraceRow.range?.endNS ?? 0,
43      totalNS: TraceRow.range?.totalNS ?? 0,
44      frame: row.frame,
45      paddingTop: padding * 2,
46      useCache: req.useCache || !(TraceRow.range?.refresh ?? false),
47    });
48    dataFilterHandler(criticalList, criticalFilter, {
49      startKey: 'ts',
50      durKey: 'dur',
51      startNS: TraceRow.range?.startNS ?? 0,
52      endNS: TraceRow.range?.endNS ?? 0,
53      totalNS: TraceRow.range?.totalNS ?? 0,
54      frame: row.frame,
55      paddingTop: rectHeight + padding * 2,
56      useCache: req.useCache || !(TraceRow.range?.refresh ?? false),
57    });
58    hiSysEventFilter = minorFilter.concat(criticalFilter);
59    drawLoadingFrame(req.context, row.dataListCache, row);
60    req.context.beginPath();
61    let find = false;
62    for (let re of hiSysEventFilter) {
63      HiSysEventStruct.draw(req.context, re);
64    }
65    if (!find && row.isHover) {
66      HiSysEventStruct.hoverHiSysEventStruct = undefined;
67    }
68    req.context.closePath();
69  }
70}
71
72export function hiSysEvent(
73  hiSysEventList: Array<HiSysEventStruct>,
74  hiSysEventFilter: Array<HiSysEventStruct>,
75  startNS: number,
76  endNS: number,
77  totalNS: number,
78  row: TraceRow<HiSysEventStruct>,
79  use: boolean
80): void {
81  if (use && hiSysEventFilter.length > 0) {
82    for (let i = 0, len = hiSysEventFilter.length; i < len; i++) {
83      let item = hiSysEventFilter[i];
84      if ((item.startTs || 0) + (item.dur || 0) >= startNS && (item.startTs || 0) <= endNS) {
85        // @ts-ignore
86        HiSysEventStruct.setSysEventFrame(item, startNS, endNS, totalNS, row.frame);
87      } else {
88        item.frame = undefined;
89      }
90    }
91    return;
92  }
93  hiSysEventFilter.length = 0;
94  if (hiSysEventList) {
95    for (let index = 0; index < hiSysEventList.length; index++) {
96      let item = hiSysEventList[index];
97      if ((item.startTs || 0) + (item.dur || 0) >= startNS && (item.startTs || 0) <= endNS) {
98        // @ts-ignore
99        HiSysEventStruct.setSysEventFrame(item, startNS, endNS, totalNS, row.frame);
100        hiSysEventFilter.push(item);
101      }
102    }
103  }
104}
105
106export class HiSysEventStruct extends BaseStruct {
107  static hoverHiSysEventStruct: HiSysEventStruct | undefined;
108  static selectHiSysEventStruct: HiSysEventStruct | undefined;
109  id: number | undefined;
110  domain: string | undefined;
111  eventName: string | undefined;
112  eventType: string | undefined;
113  startTs: number | undefined;
114  tz: string | undefined;
115  pid: number | undefined;
116  tid: number | undefined;
117  uid: number | undefined;
118  info: string | undefined;
119  level: string | undefined;
120  seq: number | undefined;
121  contents: string | undefined;
122  dur: number | undefined;
123  depth: number | undefined;
124
125  static setSysEventFrame(
126    sysEventNode: HiSysEventStruct,
127    startNS: number,
128    endNS: number,
129    totalNS: number,
130    frame: Rect
131  ): void {
132    let x1: number;
133    let x2: number;
134    if ((sysEventNode.startTs || 0) >= startNS && (sysEventNode.startTs || 0) <= endNS) {
135      x1 = ns2x(sysEventNode.startTs || 0, startNS, endNS, totalNS, frame);
136    } else {
137      x1 = 0;
138    }
139    if (
140      (sysEventNode.startTs || 0) + (sysEventNode.dur || 0) >= startNS &&
141      (sysEventNode.startTs || 0) + (sysEventNode.dur || 0) <= endNS
142    ) {
143      x2 = ns2x((sysEventNode.startTs || 0) + (sysEventNode.dur || 0), startNS, endNS, totalNS, frame);
144    } else {
145      x2 = frame.width;
146    }
147    if (!sysEventNode.frame) {
148      sysEventNode.frame = new Rect(0, 0, 0, 0);
149    }
150    let getV: number = x2 - x1 < 1 ? 1 : x2 - x1;
151    sysEventNode.frame.x = Math.floor(x1);
152    sysEventNode.frame.y = sysEventNode.depth! * rectHeight + padding * 2;
153    sysEventNode.frame.width = Math.ceil(getV);
154    sysEventNode.frame.height = 20;
155  }
156
157  static draw(ctx: CanvasRenderingContext2D, data: HiSysEventStruct): void {
158    if (data.depth === undefined || data.depth === null) {
159      return;
160    }
161    if (data.frame) {
162      ctx.globalAlpha = 1;
163      ctx.fillStyle = ColorUtils.getHisysEventColor(data.depth!);
164      ctx.fillRect(data.frame.x, data.frame.y + padding * data.depth, data.frame.width, rectHeight);
165    }
166  }
167}
168
169const padding = 5;
170const rectHeight = 10;
171