• 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.js";
17
18import {
19    queryDistributedTerm,
20    querySelectTraceStats,
21    querySystemCalls,
22    querySystemCallsTop,
23    queryTraceCpu,
24    queryTraceCpuTop,
25    queryTraceMemory,
26    queryTraceMemoryTop,
27    queryTraceMemoryUnAgg,
28    queryTraceMetaData,
29    queryTraceTaskName
30} from "../database/SqlLite.js";
31
32import "../../base-ui/table/lit-table.js";
33import {initCpuStrategyData, initTest} from "./metrics/CpuStrategy.js";
34import {initDistributedTermData} from "./metrics/DistributeTermStrategy.js";
35import {initMemoryAggStrategy} from "./metrics/MemAggStrategy.js";
36import {initMemoryStrategy} from "./metrics/MemStrategy.js";
37import {initSysCallsStrategy} from "./metrics/SysCallsStrategy.js";
38import {initSysCallsTopStrategy} from "./metrics/SysCallsTopStrategy.js";
39import {initTraceStateStrategy} from "./metrics/TraceStatsStrategy.js";
40import {initTraceTaskStrategy} from "./metrics/TraceTaskStrategy.js";
41import {initMetaDataStrategy} from "./metrics/MetaDataStrategy.js";
42import {PluginConvertUtils} from "./setting/utils/PluginConvertUtils.js";
43import {info} from "../../log/Log.js";
44import {LitProgressBar} from "../../base-ui/progress-bar/LitProgressBar.js";
45
46@element('sp-metrics')
47export class SpMetrics extends BaseElement {
48    private _metric?: string;
49    private _metricResult?: string;
50    private selectMetricEl: HTMLSelectElement | undefined;
51    private runButtonEl: HTMLButtonElement | undefined | null;
52    private responseJson: HTMLPreElement | undefined | null;
53    private metricOptionalSelects: Array<MetricQueryItem> | undefined;
54    private progressLoad: LitProgressBar | undefined;
55
56    static get observedAttributes() {
57        return ["metric", "metricResult"]
58    }
59
60    get metric(): string {
61        return this.getAttribute("metric") || "";
62    }
63
64    set metric(value: string) {
65        this._metric = value;
66    }
67
68    get metricResult(): string {
69        return this.getAttribute("metricResult") || "";
70    }
71
72    set metricResult(value: string) {
73        this._metricResult = value;
74        this.setAttribute("metricResult", value);
75    }
76
77    reset() {
78        this.selectMetricEl!.selectedIndex = 0
79        this.responseJson!.textContent = ''
80    }
81
82    initElements(): void {
83        this.progressLoad = this.shadowRoot?.querySelector(".load-metric") as LitProgressBar;
84        this.selectMetricEl = this.shadowRoot?.querySelector(".sql-select") as HTMLSelectElement;
85        this.runButtonEl = this.shadowRoot?.querySelector(".sql-select-button") as HTMLButtonElement;
86        this.responseJson = this.shadowRoot?.querySelector(".response-json") as HTMLPreElement;
87        if (this.selectMetricEl) {
88            this.selectMetricEl.addEventListener("selectionchange", () => {
89                if (this.selectMetricEl) this.selectMetricEl.textContent = "";
90            })
91        }
92        this.initMetricDataHandle();
93        this.initMetricSelectOption();
94    }
95
96    async initMetric(queryItem: MetricQueryItem) {
97        this.initMetricData(queryItem).then(item => {
98            this.progressLoad!.loading = false
99        })
100    }
101
102    async initMetricData(queryItem: MetricQueryItem) {
103        let metricQuery = queryItem.metricQuery;
104        let queryList = await metricQuery();
105        info("current Metric Data size is: ", queryList!.length)
106        let metric = queryItem.metricResultHandle;
107        let resultData = metric(queryList);
108        let jsonText = PluginConvertUtils.BeanToCmdTxtWithObjName(resultData, true, queryItem.metricName, 4);
109        this.responseJson!.textContent = jsonText;
110    }
111
112    attributeChangedCallback(name: string, oldValue: string, newValue: string) {
113        switch (name) {
114            case "metric":
115                if (this.selectMetricEl) this.selectMetricEl.textContent = newValue
116                break;
117            case "metricResult":
118                if (this.selectMetricEl) this.selectMetricEl.textContent = newValue
119                break;
120        }
121    }
122
123    runClickListener = (event: any) => {
124        this.progressLoad!.loading = true
125        let selectedIndex = this.selectMetricEl!.selectedIndex;
126        let value = this.selectMetricEl!.options[selectedIndex].value;
127        let resultQuery = this.metricOptionalSelects?.filter((item) => {
128            return item.metricName == value
129        })
130        if (!resultQuery || resultQuery.length < 1) return
131        this.initMetric(resultQuery[0]);
132    }
133
134
135    connectedCallback() {
136        // Run metric button to add listener
137        this.runButtonEl?.addEventListener('click', this.runClickListener);
138    }
139
140    disconnectedCallback() {
141        this.runButtonEl?.removeEventListener('click', this.runClickListener);
142    }
143
144    initMetricSelectOption() {
145        for (let index = 0; index < this.metricOptionalSelects!.length; index++) {
146            let htmlElement = document.createElement('option');
147            if (this.metricOptionalSelects) {
148                htmlElement.textContent = this.metricOptionalSelects[index].metricName;
149                this.selectMetricEl?.appendChild(htmlElement);
150            }
151        }
152    }
153
154    initMetricDataHandle() {
155        this.metricOptionalSelects = [
156            {
157                metricName: 'trace_mem',
158                metricQuery: queryTraceMemory,
159                metricResultHandle: initMemoryStrategy
160            },
161            {
162                metricName: 'trace_mem_top10',
163                metricQuery: queryTraceMemoryTop,
164                metricResultHandle: initMemoryStrategy
165            },
166            {
167                metricName: 'trace_mem_unagg',
168                metricQuery: queryTraceMemoryUnAgg,
169                metricResultHandle: initMemoryAggStrategy
170            },
171            {
172                metricName: 'trace_task_names',
173                metricQuery: queryTraceTaskName,
174                metricResultHandle: initTraceTaskStrategy
175            },
176            {
177                metricName: 'trace_stats',
178                metricQuery: querySelectTraceStats,
179                metricResultHandle: initTraceStateStrategy
180            },
181            {
182                metricName: 'trace_metadata',
183                metricQuery: queryTraceMetaData,
184                metricResultHandle: initMetaDataStrategy
185            },
186            {
187                metricName: 'sys_calls',
188                metricQuery: querySystemCalls,
189                metricResultHandle: initSysCallsStrategy
190            },
191        ]
192    }
193
194    initHtml(): string {
195        return `
196        <style>
197
198        :host{
199            width: 100%;
200            height: 100%;
201            background-color: var(--dark-background5,#F6F6F6);
202            margin: 0;
203            padding: 0;
204            font-size:16px;
205        }
206
207        .metric{
208            display: flex;
209            flex-direction: column;
210            position: absolute;
211            top: 0;
212            bottom: 0;
213            left: 0;
214            right: 0;
215            background-color: var(--dark-background5,#F6F6F6);
216        }
217
218        .metric-select{
219            color: #121212;
220            border-radius: 16px;
221            background-color: var(--dark-background3,#FFFFFF);
222            padding: 1% 2%;
223            margin: 2% 2.5% 0 2.5%;
224            grid-row-gap: 30px;
225        }
226
227        .request{
228            min-height: 15vh;
229            overflow: auto;
230            position: relative;
231        }
232
233        .sql-select{
234            font-family: Helvetica,serif;
235            color: var(--dark-color1,#212121);
236            font-size:0.875em;
237            line-height: 16px;
238            font-weight: 400;
239            text-align: left;
240            width: 50%;
241            height: 32px;
242            flex-wrap: wrap;
243            margin-top: 1%;
244            border: 1px solid var(--dark-color1,#4D4D4D);
245            border-radius: 16px;
246            padding: 5px 10px 5px 10px;
247            -webkit-appearance: none;
248            background: url('img/down.png') no-repeat 98% center var(--dark-background3,#FFFFFF);
249        }
250
251        button{
252            border-radius: 16px;
253            flex-grow: 1;
254            background-color: #0A59F7;
255            height: 32px;
256            width: 96px;
257            font-size: 0.875em;
258            color: var(--dark-background3,#FFFFFF);
259            text-align: center;
260            line-height: 20px;
261            font-weight: 400;
262            border:0 solid;
263            margin-left: 2%;
264        }
265
266        .response{
267            flex-grow: 1;
268            margin-bottom: 1%;
269        }
270
271        .response-json{
272            background-color: var(--dark-background3,#FFFFFF);
273            border-radius: 16px;
274            display: table-cell;
275            font-family: Helvetica,serif;
276            color: var(--dark-color1,#212121);
277            font-size:0.875em;
278            line-height: 20px;
279            font-weight: 400;
280            text-align: left;
281            height: 90%;
282            width: 100%;
283            border: none;
284            outline:none;
285            resize:none;
286        }
287
288        p{
289             display: table-cell;
290             padding: 20% 0;
291             color: #999999;
292             font-size:0.875em;
293             line-height: 20px;
294             font-weight: 400;
295             text-align: left;
296             width: 100%;
297        }
298
299        /*Define scroll bar height, width and background*/
300        ::-webkit-scrollbar
301        {
302          width: 8px;
303          background-color: var(--dark-background3,#FFFFFF);
304        }
305
306        /*define slider*/
307        ::-webkit-scrollbar-thumb
308        {
309          border-radius: 6px;
310          background-color: var(--dark-background7,rgba(0,0,0,0.1));
311        }
312
313        .load-metric{
314            width: 95%;
315            bottom: 0;
316        }
317
318        </style>
319
320        <div class="metric">
321            <div class="metric-select request">
322                <p>Select a metric</p>
323                <select class="sql-select">
324                </select>
325                <button class="sql-select-button">&nbsp;&nbsp; Run &nbsp;&nbsp;</button>
326                <lit-progress-bar class="load-metric"></lit-progress-bar>
327            </div>
328            <div class="metric-select response">
329                 <textarea class="response-json" readonly>
330                 </textarea>
331            </div>
332        </div>
333        `;
334    }
335}
336
337export interface MetricQueryItem {
338    metricName: string
339    metricQuery: Function
340    metricResultHandle: Function
341}
342
343export class SpMetricsItem {
344    itemTip: string | undefined
345    itemValue: any[] | undefined
346}
347