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 this.snapShotNumber!.style.display = 'grid'; 248 } 249 250 private longTraceModelRadioHandler(rootEl: HTMLDivElement, longTraceMaxSlide: HTMLDivElement): void { 251 SpApplication.isLongTrace = true; 252 rootEl.appendChild(longTraceMaxSlide); 253 this.outputPath!.value = 'long_trace'; 254 this.snapShotNumber!.style.display = 'none'; 255 } 256 257 private maxSizeInputHandler(maxSizeSliders: LitSlider, maxSizeParentElement: Element): void { 258 maxSizeSliders!.percent = this.maxSizeInput!.value; 259 let htmlInputElement = maxSizeSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 260 htmlInputElement.value = this.maxSizeInput!.value; 261 maxSizeSliders!.sliderStyle = { 262 minRange: 200, 263 maxRange: 300, 264 defaultValue: this.maxSizeInput!.value, 265 resultUnit: 'MB', 266 stepSize: 2, 267 lineColor: 'var(--dark-color3,#46B1E3)', 268 buttonColor: '#999999', 269 }; 270 maxSizeParentElement.setAttribute('percent', this.maxSizeInput!.value); 271 } 272 273 initLitSlider(): void { 274 this.memoryBufferSlider = this.shadowRoot?.querySelector<LitSlider>('#memory-buffer') as LitSlider; 275 this.memoryBufferSlider.sliderStyle = { 276 minRange: 4, 277 maxRange: 512, 278 defaultValue: '64', 279 resultUnit: 'MB', 280 stepSize: 2, 281 lineColor: 'var(--dark-color3,#46B1E3)', 282 buttonColor: '#999999', 283 }; 284 this.lastMemoryValue = '64'; 285 this.initMemoryBufferEl(); 286 this.maxDurationSliders = this.shadowRoot?.querySelector<LitSlider>('#max-duration') as LitSlider; 287 this.maxDurationSliders.sliderStyle = { 288 minRange: 10, 289 maxRange: 3600, 290 defaultValue: '00:00:30', 291 resultUnit: 'h:m:s', 292 stepSize: 1, 293 lineColor: 'var(--dark-color4,#61CFBE)', 294 buttonColor: '#999999', 295 }; 296 this.lastDurationValue = '00:00:30'; 297 let durationParentElement = this.maxDurationSliders!.parentNode as Element; 298 let durationInput = this.shadowRoot?.querySelector('.max_duration_result') as HTMLInputElement; 299 durationInput.value = this.maxDurationSliders.sliderStyle.defaultValue; 300 this.maxDurationSliders.addEventListener('input', () => { 301 durationInput.value = this.maxDurationSliders!.formatSeconds(this.maxDur.toString()); 302 }); 303 durationInput.style.color = 'var(--dark-color1,#000000)'; 304 durationInput.addEventListener('input', () => { 305 this.maxDurationInputHandler(durationInput, durationParentElement); 306 }); 307 let maxDurationInput = this.maxDurationSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 308 maxDurationInput.addEventListener('input', () => { 309 durationInput.style.color = 'var(--dark-color1,#000000)'; 310 durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 311 durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 312 }); 313 this.snapShotSlider = this.shadowRoot?.querySelector<LitSlider>('#snapShot') as LitSlider; 314 this.snapShotSlider.sliderStyle = { 315 minRange: 0, 316 maxRange: 1000, 317 defaultValue: '0', 318 resultUnit: 'MS', 319 stepSize: 1, 320 lineColor: 'var(--dark-color3,#46B1E3)', 321 buttonColor: '#999999', 322 }; 323 this.initSnapShotEl(); 324 } 325 326 private initSnapShotEl(): void { 327 let parentElement = this.snapShotSlider!.parentNode as Element; 328 let snapShotInput = this.shadowRoot?.querySelector('.snapShot_result') as HTMLInputElement; 329 snapShotInput.value = this.snapShotSlider!.sliderStyle.defaultValue; 330 this.snapShotSlider!.addEventListener('input', () => { 331 snapShotInput.value = this.snapShot.toString(); 332 this.isUseLocalhdc(snapShotInput.value); 333 }); 334 parentElement.setAttribute('percent', '0'); 335 snapShotInput.style.color = 'var(--dark-color1,#000000)'; 336 snapShotInput.addEventListener('input', () => { 337 this.snapShotInputHandler(snapShotInput, parentElement); 338 this.isUseLocalhdc(snapShotInput.value); 339 }); 340 let memoryBufferInput = this.snapShotSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 341 memoryBufferInput.addEventListener('input', () => { 342 snapShotInput.style.color = 'var(--dark-color1,#000000)'; 343 snapShotInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 344 snapShotInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 345 }); 346 } 347 348 private isUseLocalhdc(val: string): void { 349 this.dispatchEvent(new CustomEvent('showTip', { 350 detail: { 351 value: 'snapshot', 352 isShow:!(Number(val) < 200) 353 } 354 })); 355 } 356 357 private initMemoryBufferEl(): void { 358 let parentElement = this.memoryBufferSlider!.parentNode as Element; 359 let bufferInput = this.shadowRoot?.querySelector('.memory_buffer_result') as HTMLInputElement; 360 bufferInput.value = this.memoryBufferSlider!.sliderStyle.defaultValue; 361 this.memoryBufferSlider!.addEventListener('input', () => { 362 bufferInput.value = this.bufferSize.toString(); 363 }); 364 parentElement.setAttribute('percent', '64'); 365 bufferInput.style.color = 'var(--dark-color1,#000000)'; 366 bufferInput.addEventListener('input', () => { 367 this.memoryBufferInputHandler(bufferInput, parentElement); 368 }); 369 let memoryBufferInput = this.memoryBufferSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 370 memoryBufferInput.addEventListener('input', () => { 371 bufferInput.style.color = 'var(--dark-color1,#000000)'; 372 bufferInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 373 bufferInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 374 }); 375 } 376 377 private maxDurationInputHandler(durationInput: HTMLInputElement, durationParentElement: Element): void { 378 if (this.durationNumber!.hasAttribute('percent')) { 379 this.durationNumber!.removeAttribute('percent'); 380 } 381 durationInput.style.color = 'var(--dark-color1,#000000)'; 382 durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 383 durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 384 let regExpMatchArray = durationInput.value.trim(); 385 if (regExpMatchArray === '') { 386 durationInput.style.color = 'red'; 387 durationParentElement.setAttribute('percent', '30'); 388 return; 389 } 390 let regExpMatch = durationInput.value.trim().match('^\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}$'); 391 if (regExpMatch) { 392 let durationList = regExpMatchArray.split(':'); 393 let resultDuration = 394 Number(durationList[0]) * NUM_3600 + Number(durationList[1]) * NUM_60 + Number(durationList[2]); 395 if ( 396 Number(durationList[0]) > NUM_60 || 397 Number(durationList[1]) > NUM_60 || 398 Number(durationList[2]) > NUM_60 || 399 resultDuration > this.maxDurationSliders!.sliderStyle.maxRange || 400 resultDuration < this.maxDurationSliders!.sliderStyle.minRange 401 ) { 402 durationInput.style.color = 'red'; 403 durationParentElement.setAttribute('percent', '30'); 404 } else { 405 durationInput.style.color = 'var(--dark-color1,#000000)'; 406 durationInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 407 durationInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 408 let htmlInputElement = this.maxDurationSliders!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 409 htmlInputElement.value = `${resultDuration}`; 410 this.maxDurationSliders!.sliderStyle = { 411 minRange: 10, 412 maxRange: 3600, 413 defaultValue: `${Number(durationList[0])}:${Number(durationList[1])}:${Number(durationList[2])}`, 414 resultUnit: 'h:m:s', 415 stepSize: 1, 416 lineColor: 'var(--dark-color4,#61CFBE)', 417 buttonColor: '#999999', 418 }; 419 durationParentElement.setAttribute('percent', resultDuration.toString()); 420 this.lastDurationValue = regExpMatchArray; 421 } 422 } else { 423 durationInput.style.color = 'red'; 424 durationParentElement.setAttribute('percent', '30'); 425 } 426 } 427 428 private memoryBufferInputHandler(bufferInput: HTMLInputElement, parentElement: Element): void { 429 if (this.bufferNumber!.hasAttribute('percent')) { 430 this.bufferNumber!.removeAttribute('percent'); 431 } 432 bufferInput.style.color = 'var(--dark-color1,#000000)'; 433 bufferInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 434 bufferInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 435 if (bufferInput.value.trim() === '') { 436 bufferInput.style.color = 'red'; 437 parentElement.setAttribute('percent', '64'); 438 return; 439 } 440 let memorySize = Number(bufferInput.value); 441 if ( 442 !memorySize || 443 memorySize < this.memoryBufferSlider!.sliderStyle.minRange || 444 memorySize > this.memoryBufferSlider!.sliderStyle.maxRange 445 ) { 446 bufferInput.style.color = 'red'; 447 parentElement.setAttribute('percent', '64'); 448 } else { 449 this.memoryBufferSlider!.percent = bufferInput.value; 450 let htmlInputElement = this.memoryBufferSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 451 htmlInputElement.value = bufferInput.value; 452 this.memoryBufferSlider!.sliderStyle = { 453 minRange: 4, 454 maxRange: 512, 455 defaultValue: bufferInput.value, 456 resultUnit: 'MB', 457 stepSize: 2, 458 lineColor: 'var(--dark-color3,#46B1E3)', 459 buttonColor: '#999999', 460 }; 461 parentElement.setAttribute('percent', bufferInput.value); 462 this.lastMemoryValue = bufferInput.value; 463 } 464 } 465 466 private snapShotInputHandler(snapShotInput: HTMLInputElement, parentElement: Element): void { 467 if (this.snapShotNumber!.hasAttribute('percent')) { 468 this.snapShotNumber!.removeAttribute('percent'); 469 } 470 snapShotInput.style.color = 'var(--dark-color1,#000000)'; 471 snapShotInput.parentElement!.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 472 snapShotInput.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; 473 if (snapShotInput.value.trim() === '') { 474 snapShotInput.style.color = 'red'; 475 parentElement.setAttribute('percent', '0'); 476 return; 477 } 478 let snapShotSize = Number(snapShotInput.value); 479 if ( 480 0 < snapShotSize && snapShotSize < 200 481 ) { 482 snapShotInput.style.color = 'red'; 483 parentElement.setAttribute('percent', '0'); 484 this.snapShotSlider!.percent = '0'; 485 let htmlInputElement = this.snapShotSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 486 htmlInputElement.value = '0'; 487 } else { 488 this.snapShotSlider!.percent = snapShotInput.value; 489 let htmlInputElement = this.snapShotSlider!.shadowRoot?.querySelector('#slider') as HTMLInputElement; 490 htmlInputElement.value = snapShotInput.value; 491 this.snapShotSlider!.sliderStyle = { 492 minRange: 0, 493 maxRange: 1000, 494 defaultValue: snapShotInput.value, 495 resultUnit: 'MS', 496 stepSize: 1, 497 lineColor: 'var(--dark-color3,#46B1E3)', 498 buttonColor: '#999999', 499 }; 500 parentElement.setAttribute('percent', snapShotInput.value); 501 } 502 } 503 504 initHtml(): string { 505 return SpRecordSettingHtml; 506 } 507} 508