• 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 { BaseElement, element } from '../../base-ui/BaseElement';
17import { SpFlagHtml } from './SpFlag.html';
18import { LitSelectV } from '../../base-ui/select/LitSelectV';
19import { SysCallMap } from './trace/base/SysCallUtils';
20
21const NUM = '000000';
22//vsync二级下拉选框对应的value和content
23const VSYNC_CONTENT = [
24  { value: 'H:VsyncGenerator', content: 'VsyncGeneratior' },
25  { value: 'H:rs_SendVsync', content: 'Vsync-rs' },
26  { value: 'H:app_SendVsync', content: 'Vsync-app' }
27];
28//cat二级下拉选框对应的value和content
29const CAT_CONTENT = [
30  { value: 'business', content: 'Business first' },
31  { value: 'thread', content: 'Thread first' }
32];
33//hang二级下拉选框对应的value和content
34const HANG_CONTENT = [
35  { value: `33${NUM}`, content: 'Instant' },
36  { value: `100${NUM}`, content: 'Circumstantial' },
37  { value: `250${NUM}`, content: 'Micro' },
38  { value: `500${NUM}`, content: 'Severe' }
39];
40
41//整合默认值
42const CONFIG_STATE: unknown = {
43  'VSync': ['vsyncValue', 'VsyncGeneratior'],
44  'Start&Finish Trace Category': ['catValue', 'Business first'],
45  'Hangs Detection': ['hangValue', 'Instant'],
46};
47
48@element('sp-flags')
49export class SpFlags extends BaseElement {
50  private bodyEl: HTMLElement | undefined | null;
51  private xiaoLubanEl: Element | null | undefined;
52  private systemCallSelect: LitSelectV | undefined | null;
53  private systemCallInput: HTMLInputElement | undefined | null;
54  private systemCallEventId: number[] = [];
55  private systemCallSwitch: HTMLSelectElement | undefined | null;
56
57
58  connectedCallback(): void {
59    this.systemCallSelect?.addEventListener('blur', this.systemCallSelectBlurHandler);
60  }
61
62  disconnectedCallback(): void {
63    super.disconnectedCallback();
64    this.systemCallSelect?.removeEventListener('blur', this.systemCallSelectBlurHandler);
65  }
66
67  initElements(): void {
68    let parentElement = this.parentNode as HTMLElement;
69    parentElement.style.overflow = 'hidden';
70    this.bodyEl = this.shadowRoot?.querySelector('.body');
71    this.initConfigList();
72    this.systemCallSelect = this.shadowRoot?.querySelector<LitSelectV>("lit-select-v[title='SystemCall']");
73    this.systemCallSwitch = this.shadowRoot?.querySelector("select[title='System Calls']");
74    this.systemCallInput = this.systemCallSelect!.shadowRoot?.querySelector('input') as HTMLInputElement;
75    this.updateSystemCallSelect();
76  }
77
78   private updateSystemCallSelect(): void {
79    const selectedArr = FlagsConfig.getSystemcallEventId('SystemParsing');
80    let checkAll = true;
81    systemCallConfigList[0].selectArray = Array.from(SysCallMap.entries())
82          .map(([id, name]) => {
83            if (!selectedArr.includes(id)) {
84              checkAll = false;
85            }
86            return `${name}`;
87          });
88    this.systemCallSelect?.dataSource(systemCallConfigList[0].selectArray, 'ALL-SystemCall');
89    this.systemCallSelect?.setIgnoreValues(['ALL-SystemCall']);
90    if (this.systemCallSwitch?.title === 'System Calls' && this.systemCallSwitch.selectedOptions[0].value === 'Enabled') {
91      this.systemCallSelect?.removeAttribute('disabled');
92      const arr = checkAll ? ['ALL-SystemCall' ] : [];
93      FlagsConfig.getSystemcallEventId('SystemParsing').forEach(it => arr.push(SysCallMap.get(it) || ''));
94      this.systemCallSelect?.setSelectedOptions(arr);
95    } else {
96      this.systemCallSelect?.setAttribute('disabled', 'disabled');
97      this.systemCallSelect?.setSelectedOptions([]);
98    }
99  }
100
101  private systemCallSelectBlurHandler = () => {
102    let systemCallSelectOptions = this.systemCallSelect!.shadowRoot?.querySelectorAll('.option');
103    this.systemCallEventId = [];
104    systemCallSelectOptions!.forEach((option) => {
105      if (option.hasAttribute('selected')) {
106        const systemCallEventItem = Array.from(SysCallMap.entries())
107            .find(([id, name]) => name === option.getAttribute('value'));
108        if (systemCallEventItem) {
109          this.handleSystemCallEventId(systemCallEventItem[0]);
110        }
111      }
112    });
113    FlagsConfig.updateSystemcallEventId(this.systemCallEventId, 'SystemParsing');
114    return this.systemCallEventId;
115  };
116
117  private handleSystemCallEventId = (systemCallEventId: number): void => {
118    this.systemCallEventId.push(systemCallEventId);
119  };
120
121  initHtml(): string {
122    return SpFlagHtml;
123  }
124
125  private createConfigDiv(): HTMLDivElement {
126    let configDiv = document.createElement('div');
127    configDiv.className = 'flag-widget';
128    return configDiv;
129  }
130  //控制按钮设置为'Disabled'时,我们需要给一个默认值
131  private createCustomDiv(config: FlagConfigItem, configDiv: HTMLDivElement): void {
132    let configHadDiv = document.createElement('div');
133    configHadDiv.className = 'flag-head-div';
134    let titleLabel = document.createElement('label');
135    titleLabel.textContent = config.title;
136    titleLabel.className = 'flag-title-label';
137    let configSelect = document.createElement('select');
138    configSelect.className = 'flag-select';
139    configSelect.setAttribute('title', config.title);
140    config.switchOptions.forEach((optionItem) => {
141      let configOption = document.createElement('option');
142      configOption.value = optionItem.option;
143      configOption.textContent = optionItem.option;
144      if (optionItem.selected) {
145        configOption.selected = true;
146      }
147      configSelect.appendChild(configOption);
148    });
149    // 页面刷新时,选项并未改变,小鲁班也应当展示
150    this.xiaoLubanEl = document.querySelector('sp-application')?.shadowRoot?.querySelector('#sp-bubbles')
151      ?.shadowRoot?.querySelector('#xiao-luban-help');
152    if (configSelect.title === 'AI' && configSelect.selectedOptions[0].value === 'Enabled') {
153      this.xiaoLubanEl?.setAttribute('enabled', '');
154    }
155    configSelect.addEventListener('change', () => {
156      this.flagSelectListener(configSelect);
157      if (configSelect.title === 'AI') {
158        let userIdInput: HTMLInputElement | null | undefined = this.shadowRoot?.querySelector('#user_id_input');
159        if (configSelect.selectedOptions[0].value === 'Enabled') {
160          if (userIdInput?.value === '') {
161            userIdInput.style.border = '1px solid red';
162          }
163          this.xiaoLubanEl?.setAttribute('enabled', '');
164        } else {
165          userIdInput!.style.border = '1px solid #ccc';
166          this.xiaoLubanEl?.removeAttribute('enabled');
167        }
168      }
169      if (configSelect.title === 'System Calls') {
170        if (configSelect.selectedOptions[0].value === 'Enabled') {
171          this.systemCallSelect?.removeAttribute('disabled');
172        } else {
173          this.systemCallSelect?.setAttribute('disabled', 'disabled');
174          this.systemCallEventId = [];
175          FlagsConfig.updateSystemcallEventId([], 'SystemParsing');
176          this.systemCallSelect?.setSelectedOptions([]);
177        }
178      }
179    });
180    let userIdInput: HTMLInputElement | null | undefined = this.shadowRoot?.querySelector('#user_id_input');
181    if (configSelect.title === 'AI' && configSelect.selectedOptions[0].value === 'Enabled' && userIdInput?.value === '') {
182      userIdInput.style.border = '1px solid red';
183    }
184    let description = document.createElement('div');
185    description.className = 'flag-des-div';
186    description.textContent = config.describeContent;
187    configHadDiv.appendChild(titleLabel);
188    configHadDiv.appendChild(configSelect);
189    configDiv.appendChild(configHadDiv);
190    configDiv.appendChild(description);
191  }
192  //监听flag-select的状态选择
193  private flagSelectListener(configSelect: HTMLSelectElement): void {
194    // @ts-ignore
195    let title = configSelect.getAttribute('title');
196    //@ts-ignore
197    let listSelect = this.shadowRoot?.querySelector(`#${CONFIG_STATE[title]?.[0]}`);
198    // @ts-ignore
199    FlagsConfig.updateFlagsConfig(title!, configSelect.selectedOptions[0].value);
200    //@ts-ignore
201    if (listSelect) {
202      // @ts-ignore
203      if (configSelect.selectedOptions[0].value === 'Enabled') {
204        listSelect?.removeAttribute('disabled');
205      } else {
206        listSelect?.childNodes.forEach((child: ChildNode) => {
207          let selectEl = child as HTMLOptionElement;
208          //@ts-ignore
209          if (child.textContent === CONFIG_STATE[title]?.[1]) {
210            selectEl.selected = true;
211            //@ts-ignore
212            FlagsConfig.updateFlagsConfig(CONFIG_STATE[title]?.[0], selectEl.value);
213          } else {
214            selectEl.selected = false;
215          }
216        });
217        listSelect?.setAttribute('disabled', 'disabled');
218      }
219    }
220  }
221
222  //初始化Flag对应的内容
223  private initConfigList(): void {
224    let allConfig = FlagsConfig.getAllFlagConfig();
225    allConfig.forEach((config) => {
226      let configDiv = this.createConfigDiv();
227      this.createCustomDiv(config, configDiv);
228      if (config.title === 'AnimationAnalysis') {
229        let configFooterDiv = document.createElement('div');
230        configFooterDiv.className = 'config_footer';
231        let deviceWidthLabelEl = document.createElement('label');
232        deviceWidthLabelEl.className = 'device_label';
233        deviceWidthLabelEl.textContent = 'PhysicalWidth :';
234        let deviceWidthEl = document.createElement('input');
235        deviceWidthEl.value = <string>config.addInfo!.physicalWidth;
236        deviceWidthEl.addEventListener('keyup', () => {
237          deviceWidthEl.value = deviceWidthEl.value.replace(/\D/g, '');
238        });
239        deviceWidthEl.addEventListener('blur', () => {
240          if (deviceWidthEl.value !== '') {
241            FlagsConfig.updateFlagsConfig('physicalWidth', Number(deviceWidthEl.value));
242          }
243        });
244        deviceWidthEl.className = 'device_input';
245        let deviceHeightLabelEl = document.createElement('label');
246        deviceHeightLabelEl.textContent = 'PhysicalHeight :';
247        deviceHeightLabelEl.className = 'device_label';
248        let deviceHeightEl = document.createElement('input');
249        deviceHeightEl.className = 'device_input';
250        deviceHeightEl.value = <string>config.addInfo!.physicalHeight;
251        deviceHeightEl.addEventListener('keyup', () => {
252          deviceHeightEl.value = deviceHeightEl.value.replace(/\D/g, '');
253        });
254        deviceHeightEl.addEventListener('blur', () => {
255          if (deviceWidthEl.value !== '') {
256            FlagsConfig.updateFlagsConfig('physicalHeight', Number(deviceHeightEl.value));
257          }
258        });
259        configFooterDiv.appendChild(deviceWidthLabelEl);
260        configFooterDiv.appendChild(deviceWidthEl);
261        configFooterDiv.appendChild(deviceHeightLabelEl);
262        configFooterDiv.appendChild(deviceHeightEl);
263        configDiv.appendChild(configFooterDiv);
264      }
265      //@ts-ignore
266      let configKey = CONFIG_STATE[config.title]?.[0];
267      if (config.title === 'VSync') {//初始化Vsync
268        let configFooterDiv = this.createPersonOption(VSYNC_CONTENT, configKey, config);
269        configDiv.appendChild(configFooterDiv);
270      }
271
272      if (config.title === 'Start&Finish Trace Category') {//初始化Start&Finish Trace Category
273        let configFooterDiv = this.createPersonOption(CAT_CONTENT, configKey, config);
274        configDiv.appendChild(configFooterDiv);
275      }
276
277      if (config.title === 'Hangs Detection') {//初始化Hangs Detection
278        let configFooterDiv = this.createPersonOption(HANG_CONTENT, configKey, config);
279        configDiv.appendChild(configFooterDiv);
280      }
281      if (config.title === 'AI') {
282        let configFooterDiv = document.createElement('div');
283        configFooterDiv.className = 'config_footer';
284        let userIdLabelEl = document.createElement('label');
285        userIdLabelEl.className = 'device_label';
286        userIdLabelEl.textContent = 'User Id: ';
287        let userIdInputEl = document.createElement('input');
288        userIdInputEl.value = <string>config.addInfo!.userId;
289        userIdInputEl.addEventListener('blur', () => {
290          if (userIdInputEl.value !== '') {
291            userIdInputEl.style.border = '1px solid #ccc';
292            FlagsConfig.updateFlagsConfig('userId', userIdInputEl.value);
293          } else {
294            userIdInputEl.style.border = '1px solid red';
295          }
296        });
297        userIdInputEl.className = 'device_input';
298        userIdInputEl.id = 'user_id_input';
299        configFooterDiv.appendChild(userIdLabelEl);
300        configFooterDiv.appendChild(userIdInputEl);
301        configDiv.appendChild(configFooterDiv);
302      }
303      if (config.title === 'System Calls') {
304        let configFooterDiv = document.createElement('div');
305        configFooterDiv.className = 'config_footer';
306        let systemCallConfigEl = document.createElement('div');
307        systemCallConfigEl.className = 'system-call-config';
308        systemCallConfigList.forEach((config) => {
309          let systemCallConfigDiv = document.createElement('div');
310          if (config.hidden) {
311            systemCallConfigDiv.className = 'systemCall-config-div hidden';
312          } else {
313            systemCallConfigDiv.className = 'systemCall-config-div';
314          }
315          switch (config.type) {
316            case 'select-multiple':
317              this.configTypeBySelectMultiple(config, systemCallConfigDiv);
318              break;
319            default:
320              break;
321          }
322          systemCallConfigEl.appendChild(systemCallConfigDiv);
323        })
324        configFooterDiv.appendChild(systemCallConfigEl);
325        configDiv.appendChild(configFooterDiv);
326      }
327      this.bodyEl!.appendChild(configDiv);
328    });
329  }
330
331  private configTypeBySelectMultiple(config: unknown, systemCallConfigDiv: HTMLDivElement): void {
332    let html = '';
333    //@ts-ignore
334    let placeholder = config.selectArray[0];
335    html += `<lit-select-v default-value='' rounded='' class='systemCall-config-select config'
336mode='multiple' canInsert='' title='${
337        //@ts-ignore
338        config.title
339    }' rounded placement = 'bottom' placeholder='${placeholder}'>`;
340    //@ts-ignore
341    config.selectArray.forEach((value: string) => {
342      html += `<lit-select-option value='${value}'>${value}</lit-select-option>`;
343    });
344    html += '</lit-select-v>';
345    systemCallConfigDiv.innerHTML = systemCallConfigDiv.innerHTML + html;
346  }
347
348  private createPersonOption(list: unknown, key: string, config: unknown): HTMLDivElement {
349    let configFooterDiv = document.createElement('div');
350    configFooterDiv.className = 'config_footer';
351    let lableEl = document.createElement('lable');
352    lableEl.className = 'list_lable';
353    let typeEl = document.createElement('select');
354    typeEl.setAttribute('id', key);
355    typeEl.className = 'flag-select';
356    //根据给出的list遍历添加option下来选框
357    //@ts-ignore
358    for (const settings of list) {
359      let option = document.createElement('option');
360      option.value = settings.value;
361      option.textContent = settings.content;
362      //初始化二级按钮状态
363      //@ts-ignore
364      if (option.value === config.addInfo?.[key]) {
365        option.selected = true;
366        FlagsConfig.updateFlagsConfig(key, option.value);
367      }
368      typeEl.appendChild(option);
369    }
370    typeEl.addEventListener('change', function () {
371      let selectValue = this.selectedOptions[0].value;
372      FlagsConfig.updateFlagsConfig(key, selectValue);
373    });
374    let flagsItem = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY);
375    let flagsItemJson = JSON.parse(flagsItem!);
376    //@ts-ignore
377    let vsync = flagsItemJson[config.title];
378    if (vsync === 'Enabled') {
379      typeEl.removeAttribute('disabled');
380    } else {
381      typeEl.setAttribute('disabled', 'disabled');
382      //@ts-ignore
383      FlagsConfig.updateFlagsConfig(key, config.addInfo?.[key]);
384    }
385    configFooterDiv.appendChild(lableEl);
386    configFooterDiv.appendChild(typeEl);
387    return configFooterDiv;
388  }
389}
390
391export type Params = {
392  [key: string]: unknown;
393};
394
395export class FlagsConfig {
396  static FLAGS_CONFIG_KEY = 'FlagsConfig';
397  static SYSTEM_PRASE = 'SystemParsing';
398  static DEFAULT_CONFIG: Array<FlagConfigItem> = [
399    {
400      title: 'TaskPool',
401      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
402      describeContent: 'Analyze TaskPool templates',
403    },
404    {
405      title: 'AnimationAnalysis',
406      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
407      describeContent: 'Analyze Animation effect templates',
408      addInfo: { physicalWidth: 0, physicalHeight: 0 },
409    },
410    {
411      title: 'AppStartup',
412      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
413      describeContent: 'App Startup templates',
414    },
415    {
416      title: 'SchedulingAnalysis',
417      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
418      describeContent: 'Scheduling analysis templates',
419    },
420    {
421      title: 'BinderRunnable',
422      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
423      describeContent: 'support Cpu State Binder-Runnable',
424    },
425    {
426      title: 'FfrtConvert',
427      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
428      describeContent: 'Ffrt Convert templates',
429    },
430    {
431      title: 'HMKernel',
432      switchOptions: [{ option: 'Enabled', selected: true }, { option: 'Disabled' }],
433      describeContent: '',
434    },
435    {
436      title: 'VSync',
437      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
438      describeContent: 'VSync Signal drawing',
439      addInfo: { vsyncValue: VSYNC_CONTENT[0].value },
440    },
441    {
442      title: 'Hangs Detection',
443      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
444      describeContent: 'hangs type:Instant(33ms~100ms),Circumstantial(100ms~250ms),Micro(250ms~500ms),Severe(>=500ms)',
445      addInfo: { hangValue: HANG_CONTENT[0].value },
446    },
447    {
448      title: 'LTPO',
449      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
450      describeContent: 'Lost Frame and HitchTime templates',
451    },
452    {
453      title: 'Start&Finish Trace Category',
454      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
455      describeContent: 'Asynchronous trace aggregation',
456      addInfo: { catValue: CAT_CONTENT[0].value },
457    },
458    {
459      title: 'UserPluginsRow',
460      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
461      describeContent: 'User Upload Plugin To Draw',
462    },
463    {
464      title: 'CPU by Irq',
465      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
466      describeContent: 'The real CPU after being split by irq and softirq',
467    },
468    {
469      title: 'RawTraceCutStartTs',
470      switchOptions: [{ option: 'Enabled', selected: true }, { option: 'Disabled' }],
471      describeContent: 'Raw Trace Cut By StartTs, StartTs = Max(Cpu1 StartTs, Cpu2 StartTs, ..., CpuN StartTs)',
472    },
473    {
474      title: 'AI',
475      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
476      describeContent: 'Start AI',
477      addInfo: { userId: '' },
478    },
479    {
480      title: 'System Calls',
481      switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }],
482      describeContent: 'Start System Call Parsing',
483      addInfo: { userId: '' },
484    }
485  ];
486
487  static getAllFlagConfig(): Array<FlagConfigItem> {
488    let flagsConfigStr = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY);
489    if (flagsConfigStr === null) {
490      let flagConfigObj: Params = {};
491      FlagsConfig.DEFAULT_CONFIG.forEach((config) => {
492        let selectedOption = config.switchOptions.filter((option) => {
493          return option.selected;
494        });
495        let value = config.switchOptions[0].option;
496        if (selectedOption[0] !== undefined) {
497          value = selectedOption[0].option;
498        }
499        flagConfigObj[config.title] = value;
500        if (config.addInfo) {
501          for (const [key, value] of Object.entries(config.addInfo)) {
502            flagConfigObj[key] = value;
503          }
504        }
505      });
506      window.localStorage.setItem(FlagsConfig.FLAGS_CONFIG_KEY, JSON.stringify(flagConfigObj));
507      return FlagsConfig.DEFAULT_CONFIG;
508    } else {
509      let flagsConfig = JSON.parse(flagsConfigStr);
510      FlagsConfig.DEFAULT_CONFIG.forEach((config) => {
511        let cfg = flagsConfig[config.title];
512        if (cfg) {
513          config.switchOptions.forEach((option) => {
514            if (option.option === cfg) {
515              option.selected = true;
516            } else {
517              option.selected = false;
518            }
519          });
520        }
521        if (config.addInfo) {
522          for (const [key, value] of Object.entries(config.addInfo)) {
523            let cfg = flagsConfig[key];
524            if (cfg) {
525              config.addInfo[key] = cfg;
526            }
527          }
528        }
529      });
530    }
531    return FlagsConfig.DEFAULT_CONFIG;
532  }
533
534  static getSpTraceStreamParseConfig(): string {
535    let parseConfig = {};
536    FlagsConfig.getAllFlagConfig().forEach((configItem) => {
537      let selectedOption = configItem.switchOptions.filter((option) => {
538        return option.selected;
539      });
540      // @ts-ignore
541      parseConfig[configItem.title] = selectedOption[0].option === 'Enabled' ? 1 : 0;
542      // @ts-ignore
543      if (configItem.title === 'System Calls') {
544        // @ts-ignore
545        parseConfig[configItem.title] =  selectedOption[0].option === 'Enabled' ? FlagsConfig.getSystemcallEventId('SystemParsing').join(';') : '';
546      }
547    });
548    return JSON.stringify({ config: parseConfig });
549  }
550
551  static getFlagsConfig(flagName: string): Params | undefined {
552    let flagConfigObj: Params = {};
553    let configItem = FlagsConfig.getAllFlagConfig().find((config) => {
554      return config.title === flagName;
555    });
556    if (configItem) {
557      let selectedOption = configItem.switchOptions.filter((option) => {
558        return option.selected;
559      });
560      let value = configItem.switchOptions[0].option;
561      if (selectedOption[0] !== undefined) {
562        value = selectedOption[0].option;
563      }
564      flagConfigObj[configItem.title] = value;
565      if (configItem.addInfo) {
566        for (const [key, value] of Object.entries(configItem.addInfo)) {
567          flagConfigObj[key] = value;
568        }
569      }
570      return flagConfigObj;
571    } else {
572      return configItem;
573    }
574  }
575
576  static getFlagsConfigEnableStatus(flagName: string): boolean {
577    let config = FlagsConfig.getFlagsConfig(flagName);
578    let enable: boolean = false;
579    if (config && config[flagName]) {
580      enable = config[flagName] === 'Enabled';
581    }
582    return enable;
583  }
584  //获取Cat的二级下拉选框所选的内容
585  static getSecondarySelectValue(value: string): string {
586    let list = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY);
587    let listJson = JSON.parse(list!);
588    let catSelectValue = listJson[value];
589    return catSelectValue;
590  }
591
592  static updateFlagsConfig(key: string, value: unknown): void {
593    let flagsConfigStr = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY);
594    let flagConfigObj: Params = {};
595    if (flagsConfigStr !== null) {
596      flagConfigObj = JSON.parse(flagsConfigStr);
597    }
598    flagConfigObj[key] = value;
599    window.localStorage.setItem(FlagsConfig.FLAGS_CONFIG_KEY, JSON.stringify(flagConfigObj));
600  }
601
602
603  static getSystemcallEventId(value: string): number[] {
604    let list = window.localStorage.getItem(FlagsConfig.SYSTEM_PRASE);
605    return JSON.parse(list!) || [];
606  }
607
608  static updateSystemcallEventId(systemCallEventId: number[], value: unknown): void {
609    let systemCallEventIdArray:number[] = [];
610    if (systemCallEventId !== null) {
611      systemCallEventIdArray = systemCallEventId;
612    }
613    window.localStorage.setItem(FlagsConfig.SYSTEM_PRASE, JSON.stringify(systemCallEventIdArray));
614  }
615}
616
617export interface FlagConfigItem {
618  title: string;
619  switchOptions: OptionItem[];
620  describeContent: string;
621  addInfo?: Params;
622}
623
624export interface OptionItem {
625  option: string;
626  selected?: boolean;
627}
628
629const systemCallConfigList = [
630  {
631    title: 'SystemCall',
632    des: '',
633    hidden: true,
634    type: 'select-multiple',
635    selectArray: [''],
636  }]
637