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 '../../../base-ui/radiobox/LitRadioBox'; 18import { LitRadioBox } from '../../../base-ui/radiobox/LitRadioBox'; 19import '../../../base-ui/slider/LitSlider'; 20import { LitSlider } from '../../../base-ui/slider/LitSlider'; 21import '../../../base-ui/popover/LitPopover'; 22import { info } from '../../../log/Log'; 23import { SpApplication } from '../../SpApplication'; 24import { NUM_200, NUM_30, NUM_3600, NUM_60, NUM_64 } from '../../bean/NumBean'; 25import { SpRecordSettingHtml } from './SpRecordSetting.html'; 26 27@element('record-setting') 28export class SpRecordSetting extends BaseElement { 29 private memoryBufferSlider: LitSlider | undefined; 30 private maxDurationSliders: LitSlider | undefined; 31 private snapShotSlider: LitSlider | undefined; 32 private radioBox: LitRadioBox | undefined; 33 private longTraceRadio: LitRadioBox | undefined; 34 private bufferNumber: HTMLElement | undefined; 35 private durationNumber: HTMLElement | undefined; 36 private snapShotNumber: HTMLElement | undefined; 37 private outputPath: HTMLInputElement | undefined; 38 private lastMemoryValue: string | undefined; 39 private lastDurationValue: string | undefined; 40 private maxSizeInput: HTMLInputElement | undefined; 41 isRecordTemplate: boolean = false; 42 43 get longTraceSingleFileMaxSize(): number { 44 let maxFileSizeEl = this.shadowRoot?.querySelector<HTMLInputElement>('.max_size_result'); 45 if (maxFileSizeEl) { 46 return Number(maxFileSizeEl.value); 47 } 48 return NUM_200; 49 } 50 51 get recordMod(): boolean { 52 if (this.radioBox) { 53 return this.radioBox.checked; 54 } 55 return false; 56 } 57 58 get longOutPath(): string { 59 if (this.outputPath && this.outputPath.value !== '' && this.outputPath.value !== 'long_trace') { 60 return `/data/local/tmp/${this.outputPath.value}/`; 61 } 62 return '/data/local/tmp/long_trace/'; 63 } 64 65 get output(): string { 66 if (SpApplication.isLongTrace && !this.isRecordTemplate) { 67 if (this.outputPath && this.outputPath.value !== 'long_trace/' && this.outputPath.value !== '') { 68 return `/data/local/tmp/${this.outputPath.value}/hiprofiler_data.htrace`; 69 } 70 return '/data/local/tmp/long_trace/hiprofiler_data.htrace'; 71 } else { 72 if (this.outputPath && this.outputPath.value !== '') { 73 return `/data/local/tmp/${this.outputPath.value}`; 74 } 75 return '/data/local/tmp/hiprofiler_data.htrace'; 76 } 77 } 78 79 get bufferSize(): number { 80 if (this.bufferNumber?.hasAttribute('percent')) { 81 info('bufferSize is : ', this.bufferNumber!.getAttribute('percent')); 82 return Number(this.bufferNumber!.getAttribute('percent')); 83 } 84 return NUM_64; 85 } 86 87 get maxDur(): number { 88 if (this.durationNumber?.hasAttribute('percent')) { 89 info('maxDur is : ', this.durationNumber!.getAttribute('percent')); 90 return Number(this.durationNumber!.getAttribute('percent')); 91 } 92 return NUM_30; 93 } 94 95 get snapShot(): number { 96 if (this.snapShotNumber?.hasAttribute('percent')) { 97 info('snapShot is : ', this.snapShotNumber!.getAttribute('percent')); 98 let snapShot = Number(this.snapShotNumber!.getAttribute('percent')) < 200 ? '0' : this.snapShotNumber!.getAttribute('percent'); 99 return Number(snapShot); 100 } 101 return NUM_200; 102 } 103 104 resetValue(): void { 105 let bufferInput = this.shadowRoot?.querySelector('.memory_buffer_result') as HTMLInputElement; 106 let parentElement = this.memoryBufferSlider!.parentNode as Element; 107 if (bufferInput.style.color !== 'var(--dark-color1,#000000)' && this.lastMemoryValue) { 108 bufferInput.value = `${this.lastMemoryValue}`; 109 this.memoryBufferSlider!.percent = `${this.lastMemoryValue}`; 110 this.memoryBufferSlider!.sliderStyle = { 111 minRange: 4, 112 maxRange: 512, 113 defaultValue: `${this.lastMemoryValue}`, 114 resultUnit: 'MB', 115 stepSize: 2, 116 lineColor: 'var(--dark-color3,#46B1E3)', 117 buttonColor: '#999999', 118 }; 119 parentElement.setAttribute('percent', `${this.lastMemoryValue}`); 120 this.lastMemoryValue = `${this.lastMemoryValue}`; 121 bufferInput.style.color = 'var(--dark-color1,#000000)'; 122 } 123 124 let durationInput = this.shadowRoot?.querySelector('.max_duration_result') as HTMLInputElement; 125 let durationEl = this.maxDurationSliders!.parentNode as Element; 126 if (durationInput.style.color !== 'var(--dark-color1,#000000)' && this.lastDurationValue) { 127 durationInput.style.color = 'var(--dark-color1,#000000)'; 128 let durationList = this.lastDurationValue.split(':'); 129 let resultDuration = 130 Number(durationList[0]) * NUM_3600 + Number(durationList[1]) * NUM_60 + Number(durationList[2]); 131 durationInput.value = this.lastDurationValue; 132 this.maxDurationSliders!.sliderStyle = { 133 minRange: 10, 134 maxRange: 3600, 135 defaultValue: this.lastDurationValue!, 136 resultUnit: 'h:m:s', 137 stepSize: 1, 138 lineColor: 'var(--dark-color4,#61CFBE)', 139 buttonColor: '#999999', 140 }; 141 durationEl.setAttribute('percent', resultDuration.toString()); 142 } 143 } 144 145 initElements(): void { 146 this.bufferNumber = this.shadowRoot?.querySelector('.buffer-size') as HTMLElement; 147 this.durationNumber = this.shadowRoot?.querySelector('.max-duration') as HTMLElement; 148 this.snapShotNumber = this.shadowRoot?.querySelector('.snapShot') as HTMLElement; 149 let inputs = this.shadowRoot?.querySelectorAll('input'); 150 inputs!.forEach((item) => { 151 item.addEventListener('keydown', (ev) => { 152 // @ts-ignore 153 if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { 154 ev.preventDefault(); 155 } 156 }); 157 }); 158 this.shadowRoot?.querySelectorAll<HTMLButtonElement>('.MenuButton').forEach((button) => { 159 button!.addEventListener('mouseenter', () => { 160 button.style.backgroundColor = '#EFEFEF'; 161 }); 162 button!.addEventListener('mouseout', () => { 163 button.style.backgroundColor = '#E4E3E9'; 164 }); 165 }); 166 this.radioBox = this.shadowRoot?.querySelector('#litradio') as LitRadioBox; 167 this.addLongTraceConfig(); 168 this.initLitSlider(); 169 } 170 171 private getLongTraceSlideHTML(): string { 172 return `<div class="max-single-file-size"> 173 <div class="record-title"> 174 <span class="record-mode" >Single file max size</span> 175 <span class="record-prompt"> (single file size after cutting is 200MB - 300MB) </span> 176 </div> 177 <lit-slider id="max-size" defaultColor="var(--dark-color4,#86C5E3)" open dir="right"> 178 </lit-slider> 179 <div class='resultValue'> 180 <input class="max_size_result" type="text" value = '200' 181 oninput="if(this.value > 300){this.value = '300'} 182 if (this.value < 200) { 183 this.parentElement.style.border = '1px solid red' 184 } else { 185 this.parentElement.style.border = '1px solid #ccc' 186 } 187 if (this.value > 0 && this.value.toString().startsWith('0')){ 188 this.value = Number(this.value) 189 }" > 190 <span style="text-align: center; margin: 8px 8px 8px 0"> MB </span> 191 </div> 192 </div>`; 193 } 194 195 private addLongTraceConfig(): void { 196 this.longTraceRadio = this.shadowRoot?.querySelector('#longTraceRadio') as LitRadioBox; 197 this.outputPath = this.shadowRoot?.querySelector<HTMLInputElement>('#trace_path') as HTMLInputElement; 198 let rootEl = this.shadowRoot?.querySelector('.root') as HTMLDivElement; 199 let longTraceMaxSlide = document.createElement('div'); 200 longTraceMaxSlide.innerHTML = this.getLongTraceSlideHTML(); 201 let maxSingleFileEl = longTraceMaxSlide.querySelector<HTMLDivElement>('.max-single-file-size'); 202 let maxSizeSliders = longTraceMaxSlide.querySelector('#max-size') as LitSlider; 203 this.maxSizeInput = longTraceMaxSlide.querySelector('.max_size_result') as HTMLInputElement; 204 this.maxSizeInput.onkeydown = (ev): void => { 205 // @ts-ignore 206 if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { 207 ev.preventDefault(); 208 } 209 }; 210 let maxSizeParentElement = maxSizeSliders.parentNode as Element; 211 maxSizeSliders.sliderStyle = { 212 minRange: 200, 213 maxRange: 300, 214 defaultValue: '200', 215 resultUnit: 'MB', 216 stepSize: 2, 217 lineColor: 'var(--dark-color3,#46B1E3)', 218 buttonColor: '#999999', 219 }; 220 maxSizeSliders.addEventListener('input', () => { 221 if (maxSingleFileEl?.hasAttribute('percent')) { 222 this.maxSizeInput!.value = `${maxSingleFileEl?.getAttribute('percent')}`; 223 } else { 224 this.maxSizeInput!.value = maxSizeSliders.sliderStyle.defaultValue; 225 } 226 }); 227 this.maxSizeInput.value = maxSizeSliders.sliderStyle.defaultValue; 228 maxSizeParentElement.setAttribute('percent', '50'); 229 this.maxSizeInput.style.color = 'var(--dark-color1,#000000)'; 230 this.maxSizeInput.addEventListener('input', () => { 231 this.maxSizeInputHandler(maxSizeSliders, maxSizeParentElement); 232 }); 233 this.radioBox!.addEventListener('click', () => { 234 this.normalModelRadioHandler(rootEl, longTraceMaxSlide); 235 }); 236 this.longTraceRadio.addEventListener('click', () => { 237 this.longTraceModelRadioHandler(rootEl, longTraceMaxSlide); 238 }); 239 } 240 241 private normalModelRadioHandler(rootEl: HTMLDivElement, longTraceMaxSlide: HTMLDivElement): void { 242 SpApplication.isLongTrace = false; 243 if (rootEl.lastChild === longTraceMaxSlide) { 244 rootEl.removeChild(longTraceMaxSlide); 245 } 246 this.outputPath!.value = 'hiprofiler_data.htrace'; 247 } 248 249 private longTraceModelRadioHandler(rootEl: HTMLDivElement, longTraceMaxSlide: HTMLDivElement): void { 250 SpApplication.isLongTrace = true; 251 rootEl.appendChild(longTraceMaxSlide); 252 this.outputPath!.value = 'long_trace'; 253 } 254 255 private maxSizeInputHandler(maxSizeSliders: LitSlider, maxSizeParentElement: Element): void { 256 maxSizeSliders!.percent = this.maxSizeInput!.value; 257 let htmlInputElement = maxSizeSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 258 htmlInputElement.value = this.maxSizeInput!.value; 259 maxSizeSliders!.sliderStyle = { 260 minRange: 200, 261 maxRange: 300, 262 defaultValue: this.maxSizeInput!.value, 263 resultUnit: 'MB', 264 stepSize: 2, 265 lineColor: 'var(--dark-color3,#46B1E3)', 266 buttonColor: '#999999', 267 }; 268 maxSizeParentElement.setAttribute('percent', this.maxSizeInput!.value); 269 } 270 271 initLitSlider(): void { 272 this.memoryBufferSlider = this.shadowRoot?.querySelector<LitSlider>('#memory-buffer') as LitSlider; 273 this.memoryBufferSlider.sliderStyle = { 274 minRange: 4, 275 maxRange: 512, 276 defaultValue: '64', 277 resultUnit: 'MB', 278 stepSize: 2, 279 lineColor: 'var(--dark-color3,#46B1E3)', 280 buttonColor: '#999999', 281 }; 282 this.lastMemoryValue = '64'; 283 this.initMemoryBufferEl(); 284 this.maxDurationSliders = this.shadowRoot?.querySelector<LitSlider>('#max-duration') as LitSlider; 285 this.maxDurationSliders.sliderStyle = { 286 minRange: 10, 287 maxRange: 3600, 288 defaultValue: '00:00:30', 289 resultUnit: 'h:m:s', 290 stepSize: 1, 291 lineColor: 'var(--dark-color4,#61CFBE)', 292 buttonColor: '#999999', 293 }; 294 this.lastDurationValue = '00:00:30'; 295 let durationParentElement = this.maxDurationSliders!.parentNode as Element; 296 let durationInput = this.shadowRoot?.querySelector('.max_duration_result') as HTMLInputElement; 297 durationInput.value = this.maxDurationSliders.sliderStyle.defaultValue; 298 this.maxDurationSliders.addEventListener('input', () => { 299 durationInput.value = this.maxDurationSliders!.formatSeconds(this.maxDur.toString()); 300 }); 301 durationInput.style.color = 'var(--dark-color1,#000000)'; 302 durationInput.addEventListener('input', () => { 303 this.maxDurationInputHandler(durationInput, durationParentElement); 304 }); 305 let maxDurationInput = this.maxDurationSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 306 maxDurationInput.addEventListener('input', () => { 307 durationInput.style.color = 'var(--dark-color1,#000000)'; 308 durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 309 durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 310 }); 311 this.snapShotSlider = this.shadowRoot?.querySelector<LitSlider>('#snapShot') as LitSlider; 312 this.snapShotSlider.sliderStyle = { 313 minRange: 0, 314 maxRange: 1000, 315 defaultValue: '0', 316 resultUnit: 'MS', 317 stepSize: 1, 318 lineColor: 'var(--dark-color3,#46B1E3)', 319 buttonColor: '#999999', 320 }; 321 this.initSnapShotEl(); 322 } 323 324 private initSnapShotEl(): void { 325 let parentElement = this.snapShotSlider!.parentNode as Element; 326 let snapShotInput = this.shadowRoot?.querySelector('.snapShot_result') as HTMLInputElement; 327 snapShotInput.value = this.snapShotSlider!.sliderStyle.defaultValue; 328 this.snapShotSlider!.addEventListener('input', () => { 329 snapShotInput.value = this.snapShot.toString(); 330 this.isUseLocalhdc(snapShotInput.value); 331 }); 332 parentElement.setAttribute('percent', '0'); 333 snapShotInput.style.color = 'var(--dark-color1,#000000)'; 334 snapShotInput.addEventListener('input', () => { 335 this.snapShotInputHandler(snapShotInput, parentElement); 336 this.isUseLocalhdc(snapShotInput.value); 337 }); 338 let memoryBufferInput = this.snapShotSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 339 memoryBufferInput.addEventListener('input', () => { 340 snapShotInput.style.color = 'var(--dark-color1,#000000)'; 341 snapShotInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 342 snapShotInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 343 }); 344 } 345 346 private isUseLocalhdc(val: string): void { 347 this.dispatchEvent(new CustomEvent('showTip', { 348 detail: { 349 value: 'snapshot', 350 isShow:!(Number(val) < 200) 351 } 352 })); 353 } 354 355 private initMemoryBufferEl(): void { 356 let parentElement = this.memoryBufferSlider!.parentNode as Element; 357 let bufferInput = this.shadowRoot?.querySelector('.memory_buffer_result') as HTMLInputElement; 358 bufferInput.value = this.memoryBufferSlider!.sliderStyle.defaultValue; 359 this.memoryBufferSlider!.addEventListener('input', () => { 360 bufferInput.value = this.bufferSize.toString(); 361 }); 362 parentElement.setAttribute('percent', '64'); 363 bufferInput.style.color = 'var(--dark-color1,#000000)'; 364 bufferInput.addEventListener('input', () => { 365 this.memoryBufferInputHandler(bufferInput, parentElement); 366 }); 367 let memoryBufferInput = this.memoryBufferSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 368 memoryBufferInput.addEventListener('input', () => { 369 bufferInput.style.color = 'var(--dark-color1,#000000)'; 370 bufferInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 371 bufferInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 372 }); 373 } 374 375 private maxDurationInputHandler(durationInput: HTMLInputElement, durationParentElement: Element): void { 376 if (this.durationNumber!.hasAttribute('percent')) { 377 this.durationNumber!.removeAttribute('percent'); 378 } 379 durationInput.style.color = 'var(--dark-color1,#000000)'; 380 durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 381 durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 382 let regExpMatchArray = durationInput.value.trim(); 383 if (regExpMatchArray === '') { 384 durationInput.style.color = 'red'; 385 durationParentElement.setAttribute('percent', '30'); 386 return; 387 } 388 let regExpMatch = durationInput.value.trim().match('^\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}$'); 389 if (regExpMatch) { 390 let durationList = regExpMatchArray.split(':'); 391 let resultDuration = 392 Number(durationList[0]) * NUM_3600 + Number(durationList[1]) * NUM_60 + Number(durationList[2]); 393 if ( 394 Number(durationList[0]) > NUM_60 || 395 Number(durationList[1]) > NUM_60 || 396 Number(durationList[2]) > NUM_60 || 397 resultDuration > this.maxDurationSliders!.sliderStyle.maxRange || 398 resultDuration < this.maxDurationSliders!.sliderStyle.minRange 399 ) { 400 durationInput.style.color = 'red'; 401 durationParentElement.setAttribute('percent', '30'); 402 } else { 403 durationInput.style.color = 'var(--dark-color1,#000000)'; 404 durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 405 durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 406 let htmlInputElement = this.maxDurationSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 407 htmlInputElement.value = `${resultDuration}`; 408 this.maxDurationSliders!.sliderStyle = { 409 minRange: 10, 410 maxRange: 3600, 411 defaultValue: `${Number(durationList[0])}:${Number(durationList[1])}:${Number(durationList[2])}`, 412 resultUnit: 'h:m:s', 413 stepSize: 1, 414 lineColor: 'var(--dark-color4,#61CFBE)', 415 buttonColor: '#999999', 416 }; 417 durationParentElement.setAttribute('percent', resultDuration.toString()); 418 this.lastDurationValue = regExpMatchArray; 419 } 420 } else { 421 durationInput.style.color = 'red'; 422 durationParentElement.setAttribute('percent', '30'); 423 } 424 } 425 426 private memoryBufferInputHandler(bufferInput: HTMLInputElement, parentElement: Element): void { 427 if (this.bufferNumber!.hasAttribute('percent')) { 428 this.bufferNumber!.removeAttribute('percent'); 429 } 430 bufferInput.style.color = 'var(--dark-color1,#000000)'; 431 bufferInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 432 bufferInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 433 if (bufferInput.value.trim() === '') { 434 bufferInput.style.color = 'red'; 435 parentElement.setAttribute('percent', '64'); 436 return; 437 } 438 let memorySize = Number(bufferInput.value); 439 if ( 440 !memorySize || 441 memorySize < this.memoryBufferSlider!.sliderStyle.minRange || 442 memorySize > this.memoryBufferSlider!.sliderStyle.maxRange 443 ) { 444 bufferInput.style.color = 'red'; 445 parentElement.setAttribute('percent', '64'); 446 } else { 447 this.memoryBufferSlider!.percent = bufferInput.value; 448 let htmlInputElement = this.memoryBufferSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 449 htmlInputElement.value = bufferInput.value; 450 this.memoryBufferSlider!.sliderStyle = { 451 minRange: 4, 452 maxRange: 512, 453 defaultValue: bufferInput.value, 454 resultUnit: 'MB', 455 stepSize: 2, 456 lineColor: 'var(--dark-color3,#46B1E3)', 457 buttonColor: '#999999', 458 }; 459 parentElement.setAttribute('percent', bufferInput.value); 460 this.lastMemoryValue = bufferInput.value; 461 } 462 } 463 464 private snapShotInputHandler(snapShotInput: HTMLInputElement, parentElement: Element): void { 465 if (this.snapShotNumber!.hasAttribute('percent')) { 466 this.snapShotNumber!.removeAttribute('percent'); 467 } 468 snapShotInput.style.color = 'var(--dark-color1,#000000)'; 469 snapShotInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 470 snapShotInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 471 if (snapShotInput.value.trim() === '') { 472 snapShotInput.style.color = 'red'; 473 parentElement.setAttribute('percent', '0'); 474 return; 475 } 476 let snapShotSize = Number(snapShotInput.value); 477 if ( 478 0 < snapShotSize && snapShotSize < 200 479 ) { 480 snapShotInput.style.color = 'red'; 481 parentElement.setAttribute('percent', '0'); 482 this.snapShotSlider!.percent = '0'; 483 let htmlInputElement = this.snapShotSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 484 htmlInputElement.value = '0'; 485 } else { 486 this.snapShotSlider!.percent = snapShotInput.value; 487 let htmlInputElement = this.snapShotSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 488 htmlInputElement.value = snapShotInput.value; 489 this.snapShotSlider!.sliderStyle = { 490 minRange: 0, 491 maxRange: 1000, 492 defaultValue: snapShotInput.value, 493 resultUnit: 'MS', 494 stepSize: 1, 495 lineColor: 'var(--dark-color3,#46B1E3)', 496 buttonColor: '#999999', 497 }; 498 parentElement.setAttribute('percent', snapShotInput.value); 499 } 500 } 501 502 initHtml(): string { 503 return SpRecordSettingHtml; 504 } 505} 506