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: var(--dark-color1,#47A7E0); 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 </style> 329 <div class="root" style="position: relative;"> 330 <lit-main-menu id="main-menu" class="menu" data=''></lit-main-menu> 331 <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"> 332 </sp-keyboard> 333 <div class="search-vessel"> 334 <div class="search" style="position: relative;"> 335 <div class="sidebar-button" style="width: 0"> 336 <svg class="icon" id="icon" aria-hidden="true" viewBox="0 0 1024 1024"> 337 <use id="use" xlink:href="./base-ui/icon.svg#icon-menu"></use> 338 </svg> 339 </div> 340 <div class = "content-left-option" style="text-align: left; 341 position: absolute;left: 5px ; cursor: pointer;top: 15px"> 342 <div title="Import Key Path" id="import-key-path" style="display: none ;text-align: left;cursor: pointer;"> 343 <input id="import-config" style="display: none;pointer-events: none" type="file" accept=".json" > 344 <label style="width: 20px;height: 20px;cursor: pointer;" for="import-config"> 345 <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20"> 346 </lit-icon> 347 </label> 348 </div> 349 <lit-icon id="close-key-path" name="close" title="Close Key Path" color='#fff' size="20" style="display: none;text-align: left;cursor: pointer;"> 350 </lit-icon> 351 </div> 352 <lit-search id="lit-search"></lit-search> 353 <lit-search id="lit-record-search"></lit-search> 354 <div class="content-center-option" style="display: "> 355 <div class="long_trace_page" style="display: none;"> 356 <div class="page-button" id="preview-button"> 357 <img title="preview" src="img/preview.png"/> 358 </div> 359 <div class="page-number-list"></div> 360 <div class="page-button" id="next-button" style="margin-right: 8px;"> 361 <img title="next" src="img/next.png"/> 362 </div> 363 <div class="page-jump-font" style="margin-right: 8px;">To</div> 364 <input class="page-input" /> 365 <div class="confirm-button">Confirm</div> 366 </div> 367 </div> 368 </div> 369 <div class = "content-right-option" style="display: flex;flex-flow: nowrap;text-align: right;position: absolute;right: 1.2em;cursor: pointer;top: 17px""> 370 <lit-icon class="export-record" title="Download Mark Trace" name="download" size="16" style="margin-left: 0.8em;"></lit-icon> 371 <img class="cut-trace-file" title="Cut Trace File" src="img/menu-cut.svg" style="margin-left: 0.8em;"> 372 <img class="filter-config" title="Display Template" src="img/config_filter.png" style="margin-left: 0.8em;"> 373 </div> 374 <lit-progress-bar class="progress"></lit-progress-bar> 375 </div> 376 <div id="app-content" class="content"> 377 <sp-welcome style="visibility:visible;top:0px;left:0px;position:absolute;z-index: 100" id="sp-welcome"> 378 </sp-welcome> 379 <sp-system-trace style="visibility:hidden;z-index: 101;" id="sp-system-trace"> 380 </sp-system-trace> 381 <sp-record-trace 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"> 382 </sp-record-trace> 383 <sp-record-trace record_template='' 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-template"> 384 </sp-record-trace> 385 <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> 386 <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"> 387 </sp-metrics> 388 <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"> 389 </sp-query-sql> 390 <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"> 391 </sp-info-and-stats> 392 <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"> 393 </sp-convert-trace> 394 <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"> 395 </sp-help> 396 <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"> 397 </sp-flags> 398 <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"> 399 </sp-third-party> 400 <trace-row-config class="chart-filter" style="height:100%;top:0px;right:0;bottom:0px;position:absolute;z-index: 1001"></trace-row-config> 401 <custom-theme-color class="custom-color" style="height:100%;top:0px;right:0;bottom:0px;position:absolute;z-index: 1001"></custom-theme-color> 402 </div> 403 </div> 404 `; 405 406export function readTraceFileBuffer(): Promise<ArrayBuffer | undefined> { 407 return new Promise((resolve) => { 408 caches.match(getThreadPoolTraceBufferCacheKey('1')).then((res) => { 409 if (res) { 410 res.arrayBuffer().then((buffer) => { 411 resolve(buffer); 412 }); 413 } else { 414 resolve(undefined); 415 } 416 }); 417 }); 418} 419 420export function clearTraceFileCache(): void { 421 caches.keys().then((keys) => { 422 keys.forEach((key) => { 423 if (key === getThreadPoolTraceBufferCacheKey('1')) { 424 caches.delete(key).then(); 425 } else if (key.includes('/') && key.includes('-')) { 426 let splits = key.split('/'); 427 let keyStr = splits[splits.length - 1]; 428 let time = keyStr.split('-')[0]; 429 let fileDate = new Date(parseInt(time)); 430 if (fileDate.toLocaleDateString() !== new Date().toLocaleDateString()) { 431 //如果不是当天的缓存则删去缓存文件 432 caches.delete(key).then(); 433 } 434 } else { 435 caches.delete(key).then(); 436 } 437 }); 438 }); 439} 440 441export function postLog(filename: string, fileSize: string): void { 442 fetch(`https://${window.location.host.split(':')[0]}:${window.location.port}/logger`, { 443 method: 'POST', 444 headers: { 445 'Content-Type': 'application/json', 446 }, 447 body: JSON.stringify({ 448 fileName: filename, 449 fileSize: fileSize, 450 }), 451 }) 452 .then((response) => response.json()) 453 .then((data) => { }) 454 .catch((error) => { }); 455} 456 457export function indexedDataToBufferData(sourceData: unknown): ArrayBuffer { 458 let uintArrayLength = 0; 459 //@ts-ignore 460 let uintDataList = sourceData.map((item: unknown) => { 461 //@ts-ignore 462 let currentBufData = new Uint8Array(item.buf); 463 uintArrayLength += currentBufData.length; 464 return currentBufData; 465 }); 466 let resultArrayBuffer = new ArrayBuffer(uintArrayLength); 467 let resultUintArray = new Uint8Array(resultArrayBuffer); 468 let offset = 0; 469 uintDataList.forEach((currentArray: Uint8Array) => { 470 resultUintArray.set(currentArray, offset); 471 offset += currentArray.length; 472 }); 473 return resultArrayBuffer; 474} 475 476export function findFreeSizeAlgorithm(numbers: Array<number>, freeSize: number): Array<number> { 477 let closestSize = 0; 478 let currentSize = 0; 479 let finalIndex: Array<number> = []; 480 let currentSelectIndex: Array<number> = []; 481 482 function reBackFind(index: number): void { 483 if (index === numbers.length) { 484 const sumDifference = Math.abs(currentSize - freeSize); 485 if (currentSize <= freeSize && sumDifference < Math.abs(closestSize - freeSize)) { 486 closestSize = currentSize; 487 finalIndex = [...currentSelectIndex]; 488 } 489 return; 490 } 491 currentSize += numbers[index]; 492 currentSelectIndex.push(index); 493 reBackFind(index + 1); 494 currentSize -= numbers[index]; 495 currentSelectIndex.pop(); 496 reBackFind(index + 1); 497 } 498 499 reBackFind(0); 500 return finalIndex; 501} 502 503export function getCurrentDataTime(): string[] { 504 let current = new Date(); 505 let year = '' + current.getFullYear(); 506 let month = ('0' + (current.getMonth() + 1)).slice(-2); 507 let day = ('0' + current.getDate()).slice(-2); 508 let hours = ('0' + current.getHours()).slice(-2); 509 let minutes = ('0' + current.getMinutes()).slice(-2); 510 let seconds = ('0' + current.getSeconds()).slice(-2); 511 return [year, month, day, hours, minutes, seconds]; 512} 513