• 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 { getThreadPoolTraceBufferCacheKey } from './database/SqlLite';
17
18export enum TraceMode {
19  NORMAL,
20  LONG_TRACE,
21  DISTRIBUTED,
22}
23
24export const applicationHtml: string = `
25        <style>
26        :host{
27
28        }
29        .dark{
30        --dark-background: #272C34;
31        --dark-background1: #424851;
32        --dark-background2: #262f3c;
33        --dark-background3: #292D33;
34        --dark-background4: #323841;
35        --dark-background5: #333840;
36        --dark-background6: rgba(82,145,255,0.2);
37        --dark-background7: #494d52;
38        --dark-background8: #5291FF;
39        --dark-color: rgba(255,255,255,0.6);
40        --dark-color1: rgba(255,255,255,0.86);
41        --dark-color2: rgba(255,255,255,0.9);
42        --dark-border: #474F59;
43        --dark-color3:#4694C2;
44        --dark-color4:#5AADA0;
45        --dark-border1: #454E5A;
46        --bark-expansion:#0076FF;
47        --bark-prompt:#9e9e9e;
48        --dark-icon:#adafb3;
49        --dark-img: url('img/dark_pic.png');
50            background: #272C34;
51            color: #FFFFFF;
52        }
53        .root{
54            display: grid;
55            grid-template-rows: min-content 1fr;
56            grid-template-columns: min-content 1fr;
57            grid-template-areas: 'm s'
58                                 'm b';
59            height: 100vh;
60            width: 100vw;
61        }
62        .filedrag::after {
63             content: 'Drop the trace file to open it';
64             position: fixed;
65             z-index: 2001;
66             top: 0;
67             left: 0;
68             right: 0;
69             bottom: 0;
70             border: 5px dashed var(--dark-color1,#404854);
71             text-align: center;
72             font-size: 3rem;
73             line-height: 100vh;
74             background: rgba(255, 255, 255, 0.5);
75        }
76        .menu{
77            grid-area: m;
78            /*transition: all 0.2s;*/
79            box-shadow: 4px 0px 20px rgba(0,0,0,0.05);
80            z-index: 2000;
81        }
82        .search-vessel{
83            z-index: 999;
84            position: relative;
85            cursor: default;
86        }
87        .progress{
88            bottom: 0;
89            position: absolute;
90            height: 1px;
91            left: 0;
92            right: 0;
93        }
94
95        :host(:not([search])) .search-vessel  {
96           display: none;
97        }
98        :host(:not([search])) .search-vessel .search  {
99            background-color: var(--dark-background5,#F6F6F6);
100        }
101        .search{
102            grid-area: s;
103            background-color: var(--dark-background,#FFFFFF);
104            height: 48px;
105            display: flex;
106            justify-content: center;
107            align-items: center;
108
109        }
110        .search .search-bg{
111            background-color: var(--dark-background5,#fff);
112            border-radius: 40px;
113            padding: 3px 20px;
114            display: flex;
115            justify-content: center;
116            align-items: center;
117            border: 1px solid var(--dark-border,#c5c5c5);
118        }
119        lit-search input{
120            outline: none;
121            border: 0px;
122            background-color: transparent;
123            font-size: inherit;
124            color: var(--dark-color,#666666);
125            width: 30vw;
126            height: auto;
127            vertical-align:middle;
128            line-height:inherit;
129            height:inherit;
130            padding: 6px 6px 6px 6px};
131            max-height: inherit;
132            box-sizing: border-box;
133
134        }
135        ::placeholder { /* CSS 3 標準 */
136          color: #b5b7ba;
137          font-size: 1em;
138        }
139        lit-search input::placeholder {
140          color: #b5b7ba;
141          font-size: 1em;
142        }
143        .content{
144            grid-area: b;
145            background-color: #ffffff;
146            height: 100%;
147            overflow: auto;
148            position:relative;
149        }
150        .sheet{
151
152        }
153        .sidebar-button{
154            position: absolute;
155            top: 0;
156            left: 0;
157            background-color: var(--dark-background1,#FFFFFF);
158            height: 100%;
159            border-radius: 0 5px 5px 0;
160            width: 48px;
161            display: flex;
162            align-content: center;
163            justify-content: center;
164            cursor: pointer;
165        }
166        :host{
167            font-size: inherit;
168            display: inline-block;
169            transition: .3s;
170         }
171         :host([spin]){
172            animation: rotate 1.75s linear infinite;
173         }
174         @keyframes rotate {
175            to{
176                transform: rotate(360deg);
177            }
178         }
179         .icon{
180            display: block;
181            width: 1em;
182            height: 1em;
183            margin: auto;
184            fill: currentColor;
185            overflow: hidden;
186            font-size: 20px;
187            color: #1E4EEA;
188         }
189        :host([chart_filter]) .chart-filter {
190            display: grid;
191            grid-template-rows: min-content min-content min-content max-content auto;
192            overflow-y: clip;
193            height: 99%;
194            visibility: visible;
195            position: absolute;
196            width: 40%;
197            right: 0;
198            z-index: 1001;
199            top: 0;
200        }
201        :host([custom-color]) .custom-color {
202            display: grid;
203            grid-template-rows: min-content min-content min-content max-content auto;
204            overflow-y: auto;
205            height: 100%;
206            visibility: visible;
207            position: absolute;
208            width: 50%;
209            right: 0;
210            z-index: 1002;
211            top: 0;
212        }
213        .filter-config {
214            opacity: 1;
215            visibility: hidden;
216        }
217        .filter-config:hover {
218            opacity: 0.7;
219        }
220        .page-button[prohibit] {
221          cursor: none;
222        }
223        .page-button {
224            background: #D8D8D8;
225            border-radius: 12px;
226            width: 24px;
227            height: 24px;
228            margin-right: 12px;
229            display: flex;
230            justify-content: center;
231            align-items: center;
232        }
233        #preview-button:hover {
234          cursor: pointer;
235          background: #0A59F7;
236          color: #FFFFFF;
237          opacity: 1;
238        }
239        #next-button:hover {
240          cursor: pointer;
241          background: #0A59F7;
242          color: #FFFFFF;
243          opacity: 1;
244        }
245        .pagination:hover {
246          cursor: pointer;
247          background: #0A59F7;
248          color: #FFFFFF;
249          opacity: 1;
250        }
251        .confirm-button:hover {
252          cursor: pointer;
253          background: #0A59F7;
254          color: #FFFFFF;
255          opacity: 1;
256        }
257        .pagination {
258            background: #D8D8D8;
259            color: #000000;
260            border-radius: 12px;
261            width: 24px;
262            height: 24px;
263            margin-right: 12px;
264            display: flex;
265            justify-content: center;
266            align-items: center;
267            font-family: Helvetica;
268            font-size: 12px;
269            text-align: center;
270            line-height: 20px;
271            font-weight: 400;
272            opacity: 0.6;
273        }
274        .pagination[selected] {
275            background: #0A59F7;
276            color: #FFFFFF;
277            opacity: 1;
278        }
279        .page-jump-font {
280            opacity: 0.6;
281            font-family: Helvetica;
282            font-size: 12px;
283            color: #000000;
284            text-align: center;
285            line-height: 20px;
286            font-weight: 400;
287        }
288        .page-input {
289            background: #D8D8D8;
290            border-radius: 10px;
291            width: 40px;
292            height: 24px;
293            justify-content: center;
294            align-items: center;
295            text-align: center;
296            margin-right: 8px;
297            border: none;
298        }
299        .confirm-button {
300            font-family: Helvetica;
301            font-size: 12px;
302            color: #0A59F7;
303            text-align: center;
304            font-weight: 400;
305            border: 1px solid #0A59F7;
306            border-radius: 10px;
307            width: 64px;
308            height: 24px;
309            line-height: 24px;
310        }
311        .long_trace_page {
312            justify-content: center;
313            width: -webkit-fill-available;
314            margin-right: 5.2em;
315            align-items: center;
316            display: none;
317        }
318        .content-center-option {
319          justify-content: center;
320          width: -webkit-fill-available;
321          margin-right: 5.2em;
322          align-items: center;
323          width: auto;
324        }
325        .page-number-list {
326            display: flex;
327        }
328
329        #sp-ai-analysis {
330            top:75px;
331            right:0px;
332            position:absolute;
333            z-index:9999;
334            min-width:430px;
335            max-width:75%;
336            width:430px;
337            height:740px;
338            box-shadow:3px 0px 14px #000;
339            border-radius:8px;
340            background-color:#fff;
341            padding:10px 10px 30px 5px;
342            box-sizing:border-box;
343            visibility:hidden;
344        }
345        </style>
346        <div class="root" style="position: relative;">
347            <sp-bubble-ai style="visibility: visible; top:50%;right:2px;position: absolute;z-index: 10000" id="sp-bubbles" draggable ="true"></sp-bubble-ai>
348            <sp-advertisement style="bottom:2px;right:2px;position: absolute;z-index: 10086" id= "sp-advertisement"></sp-advertisement>
349            <lit-main-menu id="main-menu" class="menu" data=''></lit-main-menu>
350            <sp-keyboard style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 8888" id="sp-keyboard">
351            </sp-keyboard>
352            <div class="search-vessel">
353                <div class="search" style="position: relative;">
354                    <div class="sidebar-button" style="width: 0">
355                        <svg class="icon" id="icon" aria-hidden="true" viewBox="0 0 1024 1024">
356                             <use id="use" xlink:href="./base-ui/icon.svg#icon-menu"></use>
357                        </svg>
358                    </div>
359                    <div class = "content-left-option" style="text-align: left;
360                      position: absolute;left: 5px ; cursor: pointer;top: 15px">
361                      <div title="Import Key Path" id="import-key-path" style="display: none ;text-align: left;cursor: pointer;">
362                        <input id="import-config" style="display: none;pointer-events: none" type="file" accept=".json" >
363                        <label style="width: 20px;height: 20px;cursor: pointer;" for="import-config">
364                            <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20">
365                            </lit-icon>
366                        </label>
367                      </div>
368                      <lit-icon  id="close-key-path" name="close" title="Close Key Path" color='#fff' size="20" style="display: none;text-align: left;cursor: pointer;">
369                      </lit-icon>
370                    </div>
371                    <lit-search id="lit-search"></lit-search>
372                    <lit-search id="lit-record-search"></lit-search>
373                    <div class="content-center-option" style="display: ">
374                      <div class="long_trace_page" style="display: none;">
375                        <div class="page-button" id="preview-button">
376                          <img title="preview" src="img/preview.png"/>
377                        </div>
378                        <div class="page-number-list"></div>
379                        <div class="page-button" id="next-button" style="margin-right: 8px;">
380                           <img title="next" src="img/next.png"/>
381                        </div>
382                        <div class="page-jump-font" style="margin-right: 8px;">To</div>
383                        <input class="page-input" />
384                        <div class="confirm-button">Confirm</div>
385                      </div>
386                    </div>
387                </div>
388                <div class = "content-right-option" style="display: flex;flex-flow: nowrap;text-align: right;position: absolute;right: 1.2em;cursor: pointer;top: 17px"">
389                  <lit-icon class="export-record" title="Download Mark Trace" name="download" size="16" style="margin-left: 0.8em;"></lit-icon>
390                  <img class="cut-trace-file" title="Cut Trace File" src="img/menu-cut.svg" style="margin-left: 0.8em;">
391                  <img class="filter-config" title="Display Template" src="img/config_filter.png" style="margin-left: 0.8em;">
392                </div>
393                <lit-progress-bar class="progress"></lit-progress-bar>
394            </div>
395            <div id="app-content" class="content">
396                <sp-welcome style="visibility:visible;top:0px;left:0px;position:absolute;z-index: 100" id="sp-welcome">
397                </sp-welcome>
398                </sp-ai-analysis>
399                <sp-system-trace style="visibility:hidden;z-index: 101;" id="sp-system-trace">
400                </sp-system-trace>
401                <sp-record-trace record_template='false' style="overflow:auto;width:100%;height:100%;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 102" id="sp-record-trace">
402                </sp-record-trace>
403                <sp-scheduling-analysis style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;" id="sp-scheduling-analysis"></sp-scheduling-analysis>
404                <sp-metrics style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 105" id="sp-metrics">
405                </sp-metrics>
406                <sp-query-sql style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 106" id="sp-query-sql">
407                </sp-query-sql>
408                <sp-info-and-stats style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 107" id="sp-info-and-stats">
409                </sp-info-and-stats>
410                <sp-convert-trace style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0;left:0;right:0;bottom:0;position:absolute;z-index: 107" id="sp-convert-trace">
411                </sp-convert-trace>
412                <sp-help style="width:100%;height:100%;overflow:hidden;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 103" id="sp-help">
413                </sp-help>
414                <sp-flags style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 104" id="sp-flags">
415                </sp-flags>
416                <sp-third-party style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 104" id="sp-third-party">
417                </sp-third-party>
418                <trace-row-config class="chart-filter" style="height:100%;top:0px;right:0;bottom:0px;position:absolute;z-index: 1001"></trace-row-config>
419                <custom-theme-color class="custom-color" style="height:100%;top:0px;right:0;bottom:0px;position:absolute;z-index: 1001"></custom-theme-color>
420            </div>
421                <sp-ai-analysis id="sp-ai-analysis" style="visibility:hidden;">
422        </div>
423        `;
424
425export function readTraceFileBuffer(): Promise<ArrayBuffer | undefined> {
426  return new Promise((resolve) => {
427    caches.match(getThreadPoolTraceBufferCacheKey('1')).then((res) => {
428      if (res) {
429        res.arrayBuffer().then((buffer) => {
430          resolve(buffer);
431        });
432      } else {
433        resolve(undefined);
434      }
435    });
436  });
437}
438
439export function clearTraceFileCache(): void {
440  caches.keys().then((keys) => {
441    keys.forEach((key) => {
442      if (key === getThreadPoolTraceBufferCacheKey('1')) {
443        caches.delete(key).then();
444      } else if (key.includes('/') && key.includes('-')) {
445        let splits = key.split('/');
446        let keyStr = splits[splits.length - 1];
447        let time = keyStr.split('-')[0];
448        let fileDate = new Date(parseInt(time));
449        if (fileDate.toLocaleDateString() !== new Date().toLocaleDateString()) {
450          //如果不是当天的缓存则删去缓存文件
451          caches.delete(key).then();
452        }
453      } else {
454        caches.delete(key).then();
455      }
456    });
457  });
458}
459
460export function postLog(filename: string, fileSize: string): void {
461  fetch(`https://${window.location.host.split(':')[0]}:${window.location.port}/logger`, {
462    method: 'POST',
463    headers: {
464      'Content-Type': 'application/json',
465    },
466    body: JSON.stringify({
467      fileName: filename,
468      fileSize: fileSize,
469    }),
470  })
471    .then((response) => response.json())
472    .then((data) => { })
473    .catch((error) => { });
474}
475
476export function indexedDataToBufferData(sourceData: unknown): ArrayBuffer {
477  let uintArrayLength = 0;
478  //@ts-ignore
479  let uintDataList = sourceData.map((item: unknown) => {
480    //@ts-ignore
481    let currentBufData = new Uint8Array(item.buf);
482    uintArrayLength += currentBufData.length;
483    return currentBufData;
484  });
485  let resultArrayBuffer = new ArrayBuffer(uintArrayLength);
486  let resultUintArray = new Uint8Array(resultArrayBuffer);
487  let offset = 0;
488  uintDataList.forEach((currentArray: Uint8Array) => {
489    resultUintArray.set(currentArray, offset);
490    offset += currentArray.length;
491  });
492  return resultArrayBuffer;
493}
494
495export function findFreeSizeAlgorithm(numbers: Array<number>, freeSize: number): Array<number> {
496  let closestSize = 0;
497  let currentSize = 0;
498  let finalIndex: Array<number> = [];
499  let currentSelectIndex: Array<number> = [];
500
501  function reBackFind(index: number): void {
502    if (index === numbers.length) {
503      const sumDifference = Math.abs(currentSize - freeSize);
504      if (currentSize <= freeSize && sumDifference < Math.abs(closestSize - freeSize)) {
505        closestSize = currentSize;
506        finalIndex = [...currentSelectIndex];
507      }
508      return;
509    }
510    currentSize += numbers[index];
511    currentSelectIndex.push(index);
512    reBackFind(index + 1);
513    currentSize -= numbers[index];
514    currentSelectIndex.pop();
515    reBackFind(index + 1);
516  }
517
518  reBackFind(0);
519  return finalIndex;
520}
521
522export function getCurrentDataTime(): string[] {
523  let current = new Date();
524  let year = '' + current.getFullYear();
525  let month = ('0' + (current.getMonth() + 1)).slice(-2);
526  let day = ('0' + current.getDate()).slice(-2);
527  let hours = ('0' + current.getHours()).slice(-2);
528  let minutes = ('0' + current.getMinutes()).slice(-2);
529  let seconds = ('0' + current.getSeconds()).slice(-2);
530  return [year, month, day, hours, minutes, seconds];
531}
532
533// 定义ZIP文件的文件头常量
534const ZIP_HEADER = [0x50, 0x4B, 0x03, 0x04];
535// 定义ZLIB文件的文件头常量
536const ZLIB_HEADER = [0x78, 0x9c];
537
538/**
539 * 验证Uint8Array实例并检查长度是否满足要求
540 * @param uint8Array 待验证的Uint8Array实例
541 * @param requiredLength 所需的最小长度
542 * @returns 如果uint8Array是一个Uint8Array实例且长度大于等于requiredLength,则返回true,否则返回false
543 */
544function validateUint8Array(uint8Array: Uint8Array, requiredLength: number): boolean {
545  return uint8Array instanceof Uint8Array && uint8Array.length >= requiredLength;
546}
547
548/**
549 * 检查Uint8Array是否表示一个ZIP文件
550 * @param uint8Array 待检查的Uint8Array实例
551 * @returns 如果uint8Array表示的是一个ZIP文件,则返回true,否则返回false
552 */
553export function isZipFile(uint8Array: Uint8Array): boolean {
554  if (!validateUint8Array(uint8Array, ZIP_HEADER.length)) {
555    return false;
556  }
557  for (let i = 0; i < ZIP_HEADER.length; i++) {
558    if (uint8Array[i] !== ZIP_HEADER[i]) {
559      return false;
560    }
561  }
562  return true;
563}
564
565/**
566 * 检查Uint8Array是否表示一个ZLIB文件
567 * @param uint8Array 待检查的Uint8Array实例
568 * @returns 如果uint8Array表示的是一个ZLIB文件,则返回true,否则返回false
569 */
570export function isZlibFile(uint8Array: Uint8Array): boolean {
571  if (!validateUint8Array(uint8Array, ZLIB_HEADER.length)) {
572    return false;
573  }
574  for (let i = 0; i < ZLIB_HEADER.length; i++) {
575    if (uint8Array[i] !== ZLIB_HEADER[i]) {
576      return false;
577    }
578  }
579  return true;
580}