1(function (global, factory) { 2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 3 typeof define === 'function' && define.amd ? define(['exports'], factory) : 4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.XTMonitor = {})); 5})(this, (function (exports) { 'use strict'; 6 7 var name = "@xt/monitor"; 8 var version$1 = "1.0.5"; 9 var description = "XT monitoring package"; 10 var main = "dist/index.cjs.js"; 11 var module = "dist/index.esm.js"; 12 var types = "dist/index.d.ts"; 13 var scripts = { 14 build: "npm run jest && gulp build", 15 "build:patch": "npm run jest && npm run release:patch && gulp build", 16 "build:minor": "npm run jest && npm run release:minor && gulp build", 17 "build:major": "npm run jest && npm run release:major && gulp build", 18 watch: "gulp watch", 19 jest: "jest", 20 "jest:watch": "jest --watch", 21 "serve:test": "node e2e/test-server.js", 22 "serve:test:watch": "nodemon --watch dist --watch e2e/public/dist --ext js,html,json --exec \"node e2e/test-server.js\"", 23 "dev:e2e": "concurrently \"npm run watch\" \"npm run serve:test:watch\"", 24 e2e: "playwright test", 25 "e2e:ui": "playwright test --ui", 26 "e2e:report": "playwright show-report", 27 dev: "npm run build -- --mode=local && npm run serve:test", 28 "test:server": "node e2e/test-server.js", 29 release: "standard-version", 30 "release:dry": "standard-version --dry-run", 31 "release:major": "standard-version --release-as major", 32 "release:minor": "standard-version --release-as minor", 33 "release:patch": "standard-version --release-as patch", 34 prerelease: "standard-version --prerelease alpha" 35 }; 36 var peerDependencies = { 37 }; 38 var devDependencies = { 39 "@playwright/test": "^1.55.0", 40 "@rollup/plugin-commonjs": "^22.0.2", 41 "@rollup/plugin-json": "^4.1.0", 42 "@rollup/plugin-node-resolve": "^16.0.1", 43 "@rollup/plugin-replace": "^6.0.2", 44 "@rollup/plugin-typescript": "^8.5.0", 45 "@types/jest": "^30.0.0", 46 "@types/minimatch": "^6.0.0", 47 "@types/node": "^20.4.5", 48 compression: "^1.8.1", 49 concurrently: "^9.2.1", 50 cors: "^2.8.5", 51 cros: "^1.1.0", 52 dotenv: "^17.2.1", 53 "dts-bundle": "^0.7.3", 54 express: "^5.1.0", 55 gulp: "^5.0.0", 56 "gulp-typescript": "^6.0.0-alpha.1", 57 jest: "^30.0.5", 58 "jest-environment-jsdom": "^30.0.5", 59 nodemon: "^3.1.10", 60 "npm-cli-login": "^1.0.0", 61 playwright: "^1.55.0", 62 rollup: "^2.79.2", 63 "rollup-plugin-terser": "^7.0.2", 64 shelljs: "^0.10.0", 65 "standard-version": "^9.5.0", 66 "ts-jest": "^29.4.1", 67 "ts-node": "^10.9.1", 68 tslib: "^2.6.0", 69 typescript: "^5.8.3", 70 ws: "^8.18.3", 71 yargs: "^18.0.0" 72 }; 73 var dependencies = { 74 "web-vitals": "^5.1.0", 75 dsbridge: "^3.1.4" 76 }; 77 var pkg = { 78 name: name, 79 version: version$1, 80 description: description, 81 main: main, 82 module: module, 83 types: types, 84 scripts: scripts, 85 peerDependencies: peerDependencies, 86 devDependencies: devDependencies, 87 dependencies: dependencies 88 }; 89 90 const version = pkg.version; 91 const postUrl = "https://test-trace.hmswork.space/web" ; 92 const mode = "test" ; 93 var cfg = { 94 version, 95 postUrl, 96 mode 97 }; 98 99 exports.ReportTypeEnum = void 0; 100 (function (ReportTypeEnum) { 101 ReportTypeEnum["EVENT"] = "event";
102 ReportTypeEnum["ERROR"] = "error"; 103 ReportTypeEnum["PERFORMANCE"] = "performance"; 104 ReportTypeEnum["API"] = "api"; 105 ReportTypeEnum["SOCKET"] = "web-socket"; // socket ç¸å ³ 106 })(exports.ReportTypeEnum || (exports.ReportTypeEnum = {})); 107 108 exports.ReportNameEnum = void 0; 109 (function (ReportNameEnum) { 110 // api ç¸å ³ 111 ReportNameEnum["FETCH_SUCCESS"] = "fetch_success"; 112 ReportNameEnum["FETCH_HTTP_ERROR"] = "fetch_http_error"; 113 ReportNameEnum["FETCH_NETWORK_ERROR"] = "fetch_network_error"; 114 ReportNameEnum["XHR_SUCCESS"] = "xhr_success"; 115 ReportNameEnum["XHR_HTTP_ERROR"] = "xhr_http_error"; 116 ReportNameEnum["XHR_NETWORK_ERROR"] = "xhr_network_error"; 117 ReportNameEnum["XHR_ERROR"] = "xhr_error"; 118 ReportNameEnum["XHR_TIMEOUT"] = "xhr_timeout"; 119 ReportNameEnum["XHR_DETAIL"] = "xhr_detail"; 120 ReportNameEnum["API_PERFORMANCE"] = "api_performance"; 121 // é误ç¸å ³ 122 ReportNameEnum["JS_ERROR"] = "js_error"; 123 ReportNameEnum["RESOURCE_ERROR"] = "resource_error"; 124 ReportNameEnum["PROMISE_ERROR"] = "promise_error"; 125 // 页é¢ç¸å ³ 126 ReportNameEnum["CLICK"] = "click"; 127 ReportNameEnum["VISIBILITY_CHANGE"] = "visibility_change"; 128 ReportNameEnum["PAGE_VIEW"] = "page_view"; 129 ReportNameEnum["TAB_CHANGE"] = "tab_change"; 130 ReportNameEnum["WEB_VITAL"] = "web_vital"; 131 // WebSocket ç¸å ³ 132 ReportNameEnum["WS_CONNECTING"] = "ws_connecting"; 133 ReportNameEnum["WS_CONNECT"] = "ws_connect"; 134 ReportNameEnum["WS_DISCONNECT"] = "ws_disconnect"; 135 ReportNameEnum["WS_ERROR"] = "ws_error"; 136 // WS_MESSAGE = 'ws_message', // WebSocket æ¶æ¯ 137 ReportNameEnum["WS_RECONNECT"] = "ws_reconnect"; 138 ReportNameEnum["WS_PERFORMANCE"] = "ws_performance"; 139 ReportNameEnum["WS_SEND_ERROR"] = "ws_send_error"; 140 // WS_MESSAGE_ERROR = 'ws_message_error', // WebSocket æ¶æ¯é误 141 // WS_MESSAGE_PARSE_ERROR = 'ws_message_parse_error' // WebSocket æ¶æ¯è§£æé误 142 // æ§å¶å°ç¸å ³ event ç±»å 143 ReportNameEnum["CONSOLE_ERROR"] = "console_error"; 144 ReportNameEnum["CONSOLE_WARN"] = "console_warn"; 145 ReportNameEnum["CONSOLE_INFO"] = "console_info"; 146 ReportNameEnum["CONSOLE_DEBUG"] = "console_debug"; 147 ReportNameEnum["CONSOLE_LOG"] = "console_log"; // console.log ä¿¡æ¯ 148 })(exports.ReportNameEnum || (exports.ReportNameEnum = {})); 149 150 /** 151 * èµæºå è½½é误 152 * @param error 153 */ 154 const resourceError = (error) => { 155 // åºåèµæºå è½½éè¯¯ä¸ JS è¿è¡æ¶éè¯¯ï¼ 156 // - è¿è¡æ¶éè¯¯ä¼æ error.errorï¼Error 对象ï¼ï¼ä¸åºå½ç±èµæºä¸æ¥å¤ç 157 // - èµæºé误ç event.target æ¯ HTMLElementï¼å¦ <img>, <link>, <script>ï¼ï¼ä¸ event.error é常为 undefined 158 if (error && error.error) { 159 // æ¯ JS runtime errorï¼äº¤ç± window.onerror / å ¶ä»é误å¤çå¨å¤ç 160 return; 161 } 162 const target = error === null || error === void 0 ? void 0 : error.target; 163 if (!target || !(target instanceof HTMLElement)) { 164 // 䏿¯èµæºå ç´ ï¼å¿½ç¥ 165 return; 166 } 167 const meta = { 168 tagName: target.tagName, 169 src: target.src || target.href, 170 outerHTML: target.outerHTML, 171 }; 172 // ä» å¨ç¡®è®¤ä¸ºèµæºå 载失败æ¶ä¸æ¥ 173 report(exports.ReportTypeEnum.ERROR, exports.ReportNameEnum.RESOURCE_ERROR, { 174 message: `Resource load failed: ${(meta.src) || meta.tagName}`, 175 type: "resource", 176 }, meta); 177 }; 178 /** 179 * Promise æªå¤ççæç»é误 180 * @param event 181 */ 182 const unhandledrejection = (event) => { 183 const reason = event === null || event === void 0 ? void 0 : event.reason; 184 report(exports.ReportTypeEnum.ERROR, exports.ReportNameEnum.PROMISE_ERROR, { 185 message: (reason === null || reason === void 0 ? void 0 : reason.message) || String(reason), 186 type: "promise", 187 stack: (reason === null || reason === void 0 ? void 0 : reason.stack) || null 188 }); 189 }; 190 /** åå§ç window.onerror */ 191 let oldWinError = window.onerror; 192 /** 193 * å¼å¯é误çå¬ 194 */ 195 function setupErrorListeners() { 196 /** èµæºå è½½é误 */ 197 window.addEventListener("error", resourceError, true); 198 oldWinError = window.onerror; 199 /** js è¿è¡é误 */ 200 window.onerror = function (event, source, lineno, colno, error) { 201 report(exports.ReportTypeEnum.ERROR, exports.ReportNameEnum.JS_ERROR, { 202 message: (error === null || error === void 0 ? void 0 : error.message) || String(event), 203 stack: error === null || error === void 0 ? void 0 : error.stack, 204 type: "javascript", 205 source, 206 lineno, 207 colno, 208 }); 209 }; 210 /** Promise æªå¤ççæç»é误 */ 211 window.addEventListener("unhandledrejection", unhandledrejection, false); 212 } 213 function disabledErrorListener() { 214 // 注æï¼æ³¨åæ¶ä½¿ç¨äº capture = trueï¼éè¦ä»¥ç¸ååæ°ç§»é¤ 215 window.removeEventListener("error", resourceError, true); 216 window.removeEventListener("unhandledrejection", unhandledrejection, false); 217 window.onerror = oldWinError; 218 } 219 var errorMonitor = { 220 setupErrorListeners, 221 disabledErrorListener, 222 }; 223 224 // ä¿ååå§ç console æ¹æ³ 225 let originalConsole; 226 /** 227 * è¦ç console æ¹æ³æ¥çæ§æ¥å¿è¾åº 228 */ 229 function overrideConsole() { 230 originalConsole = { 231 log: console.log, 232 warn: console.warn, 233 error: console.error, 234 info: console.info,
235 debug: console.debug, 236 }; 237 // è¦ç console.log 238 console.log = function (...args) { 239 const logData = { 240 level: "log", 241 args: args, 242 timestamp: Date.now(), 243 }; 244 // 䏿¥æ¥å¿æ°æ® 245 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.CONSOLE_LOG, logData); 246 // è°ç¨åå§æ¹æ³ 247 originalConsole.log.apply(console, args); 248 }; 249 // è¦ç console.warn 250 console.warn = function (...args) { 251 const logData = { 252 level: "warn", 253 args: args, 254 timestamp: Date.now(), 255 }; 256 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.CONSOLE_WARN, logData); 257 originalConsole.warn.apply(console, args); 258 }; 259 // è¦ç console.error 260 console.error = function (...args) { 261 const logData = { 262 level: "error", 263 args: args, 264 timestamp: Date.now(), 265 stack: new Error().stack, 266 }; 267 report(exports.ReportTypeEnum.ERROR, exports.ReportNameEnum.CONSOLE_ERROR, logData); 268 originalConsole.error.apply(console, args); 269 }; 270 // è¦ç console.info 271 console.info = function (...args) { 272 const logData = { 273 level: "info", 274 args: args, 275 timestamp: Date.now(), 276 }; 277 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.CONSOLE_INFO, logData); 278 originalConsole.info.apply(console, args); 279 }; 280 // è¦ç console.debug 281 console.debug = function (...args) { 282 const logData = { 283 level: "debug", 284 args: args, 285 timestamp: Date.now(), 286 }; 287 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.CONSOLE_DEBUG, logData); 288 originalConsole.debug.apply(console, args); 289 }; 290 } 291 /** 292 * è·ååå§ç console æ¹æ³ 293 */ 294 function getOriginalConsole() { 295 if (!originalConsole) { 296 // throw new Error('Console methods have not been overridden yet.'); 297 return { 298 log: console.log, 299 warn: console.warn, 300 error: console.error, 301 info: console.info, 302 debug: console.debug, 303 }; 304 } 305 return originalConsole; 306 } 307 308 const measureRequestMap = new Map(); // measureName -> requestId 309 // å è®¸çæ¶é´è¯¯å·®èå´ï¼æ¯«ç§ï¼ 310 let TIME_TOLERANCE = 50; 311 let performanceObservers; 312 /** 313 * æ£æµ WebView è½å 314 * @returns 315 */ 316 function detectWebViewCapabilities() { 317 const capabilities = { 318 isWebView: false, 319 supportPerformanceObserver: false, 320 supportResourceTiming: false, 321 supportUserTiming: false, 322 webViewType: 'unknown' 323 }; 324 // æ£æµ WebView ç¯å¢ 325 const ua = navigator.userAgent; 326 if (/iPhone|iPad/.test(ua)) { 327 if (/Version\/[\d.]+.*Safari/.test(ua)) { 328 capabilities.webViewType = 'safari'; 329 } 330 else { 331 capabilities.isWebView = true; 332 capabilities.webViewType = 'ios-webview'; 333 } 334 } 335 else if (/Android/.test(ua)) { 336 if (/Chrome\/[\d.]+/.test(ua) && !/wv/.test(ua)) { 337 capabilities.webViewType = 'chrome'; 338 } 339 else { 340 capabilities.isWebView = true; 341 capabilities.webViewType = 'android-webview'; 342 } 343 } 344 // æ£æµ API æ¯æ 345 capabilities.supportPerformanceObserver = 'PerformanceObserver' in window; 346 capabilities.supportResourceTiming = 'PerformanceResourceTiming' in window; 347 capabilities.supportUserTiming = 'performance' in window && 348 typeof performance.mark === 'function' && 349 typeof performance.measure === 'function'; 350 return capabilities; 351 } 352 /** 353 * çå¬ç½ç»æ§è½æ°æ® - ä½¿ç¨ User Timing API æ¹æ¡ 354 */ 355 function setupPerformanceObserver() { 356 const OControl = getOriginalConsole(); 357 const capabilities = detectWebViewCapabilities(); 358 if (!capabilities.supportPerformanceObserver) { 359 OControl.warn('PerformanceObserver not supported, using fallback'); 360 return setupFallbackPerformanceMonitor(); 361 }
362 try { 363 // èµæºçå¬å¨ 364 const resourceObserver = new PerformanceObserver((list) => { 365 const entries = list.getEntries(); 366 for (const entry of entries) { 367 if (entry.entryType === 'resource' && 368 (entry.initiatorType === 'fetch' || 369 entry.initiatorType === 'xmlhttprequest')) { 370 handleResourceTiming(entry); 371 } 372 } 373 }); 374 // æµéçå¬å¨ - å¢å é误å¤ç 375 const measureObserver = new PerformanceObserver((list) => { 376 try { 377 const entries = list.getEntries(); 378 for (const entry of entries) { 379 if (entry.entryType === 'measure' && entry.name.startsWith('api-request-')) { 380 handleApiMeasure(entry); 381 } 382 } 383 } 384 catch (error) { 385 OControl.warn('measureObserver error:', error); 386 } 387 }); 388 // å®å ¨ç observe è°ç¨ 389 try { 390 resourceObserver.observe({ entryTypes: ['resource'] }); 391 } 392 catch (error) { 393 OControl.warn('Resource observer setup failed:', error); 394 } 395 try { 396 measureObserver.observe({ entryTypes: ['measure'] }); 397 } 398 catch (error) { 399 OControl.warn('Measure observer setup failed:', error); 400 } 401 return { resourceObserver, measureObserver }; 402 } 403 catch (error) { 404 OControl.error('Failed to setup PerformanceObserver:', error); 405 return setupFallbackPerformanceMonitor(); 406 } 407 } 408 /** 409 * éçº§æ¹æ¡ - 宿¶è½®è¯¢ 410 */ 411 function setupFallbackPerformanceMonitor() { 412 const OControl = getOriginalConsole(); 413 let isRunning = true; 414 const processedResources = new Set(); 415 const processedMeasures = new Set(); 416 const pollPerformanceEntries = () => { 417 if (!isRunning) 418 return; 419 try { 420 // å¤çèµæºæ¡ç® 421 const resources = performance.getEntriesByType('resource'); 422 resources.forEach(entry => { 423 const key = `${entry.name}-${entry.startTime}`; 424 if (!processedResources.has(key) && 425 (entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest')) { 426 processedResources.add(key); 427 handleResourceTiming(entry); 428 } 429 }); 430 // å¤çæµéæ¡ç® 431 const measures = performance.getEntriesByType('measure'); 432 measures.forEach(entry => { 433 const key = `${entry.name}-${entry.startTime}`; 434 if (!processedMeasures.has(key) && entry.name.startsWith('api-request-')) { 435 processedMeasures.add(key); 436 handleApiMeasure(entry); 437 } 438 }); 439 } 440 catch (error) { 441 OControl.warn('Fallback performance monitor error:', error); 442 } 443 setTimeout(pollPerformanceEntries, 1000); // 1ç§è½®è¯¢ 444 }; 445 setTimeout(pollPerformanceEntries, 100); // å»¶è¿å¯å¨ 446 return { 447 resourceObserver: { disconnect: () => { isRunning = false; } }, 448 measureObserver: { disconnect: () => { isRunning = false; } } 449 }; 450 } 451 /** 452 * å¤çèµæºæ¶åºæ°æ® 453 */ 454 function handleResourceTiming(resourceEntry) { 455 var _a; 456 const url = resourceEntry.name; 457 // çç¥1: éåææç¸å ³ç measureï¼éè¿æ¶é´å URL å¹é 458 const allMeasures = performance.getEntriesByType('measure'); 459 const apiMeasures = allMeasures.filter(m => m.name.startsWith('api-request-')); 460 for (const measure of apiMeasures) { 461 const requestId = measureRequestMap.get(measure.name) || ((_a = measure.detail) === null || _a === void 0 ? void 0 : _a.requestId); 462 if (!requestId) 463 continue; 464 const metadata = requestMetadata.get(requestId); 465 if (!metadata) 466 continue; 467 // å¹é æ¡ä»¶ï¼URL ç¸å ä¸ å¼å§æ¶é´æ¥è¿ 468 if (metadata.url === url && 469 Math.abs(measure.startTime - resourceEntry.startTime) <= TIME_TOLERANCE) { 470 const performanceData = { 471 url: metadata.url, 472 type: metadata.type, 473 startTime: resourceEntry.startTime, 474 duration: resourceEntry.duration, 475 name: `${metadata.method} ${metadata.url}`, 476 requestId, 477 // æ§è½ç»è 478 dns: resourceEntry.domainLookupEnd - resourceEntry.domainLookupStart, 479 tcp: resourceEntry.connectEnd - resourceEntry.connectStart, 480 ssl: resourceEntry.secureConnectionStart > 0 481 ? resourceEntry.connectEnd - resourceEntry.secureConnectionStart 482 : 0, 483 ttfb: resourceEntry.responseStart - resourceEntry.requestStart, 484 responseTime: resourceEntry.responseEnd - resourceEntry.responseStart, 485 transferSize: resourceEntry.transferSize, 486 encodedBodySize: resourceEntry.encodedBodySize, 487 decodedBodySize: resourceEntry.decodedBodySize, 488 status: metadata.status, 489 success: metadata.success, 490 }; 491 // 䏿¥æ§è½æ°æ® 492 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.API_PERFORMANCE, performanceData); 493 // æ¸ çæ°æ® - æ·»å cleanup è°ç¨ 494 if (metadata.performanceMark) { 495 metadata.performanceMark.cleanup(); 496 } 497 requestMetadata.delete(requestId); 498 performance.clearMeasures(measure.name); 499 measureRequestMap.delete(measure.name); 500 return; // æ¾å°å¹é 项åéåº 501 } 502 } 503 } 504 /** 505 * å¤ç API æµéæ°æ® - æ¹è¿ç 506 */ 507 function handleApiMeasure(measure) { 508 var _a; 509 const OControl = getOriginalConsole();
510 try { 511 const requestId = measureRequestMap.get(measure.name) || ((_a = measure.detail) === null || _a === void 0 ? void 0 : _a.requestId); 512 if (!requestId) { 513 // ä» measure name è§£æ requestId 514 const prefix = 'api-request-'; 515 if (measure.name.startsWith(prefix)) { 516 const parsedRequestId = measure.name.slice(prefix.length); 517 const metadata = requestMetadata.get(parsedRequestId); 518 if (metadata) { 519 // å°è¯æ¾å°å¯¹åºç resource timing 520 tryMatchResourceTiming(measure, parsedRequestId, metadata); 521 } 522 } 523 return; 524 } 525 const metadata = requestMetadata.get(requestId); 526 if (!metadata) 527 return; 528 // å°è¯å¹é resource timing 529 tryMatchResourceTiming(measure, requestId, metadata); 530 } 531 catch (error) { 532 OControl.warn('handleApiMeasure error:', error); 533 } 534 } 535 /** 536 * å°è¯å¹é resource timing 537 */ 538 function tryMatchResourceTiming(measure, requestId, metadata) { 539 const findMatchingResource = () => { 540 const resources = performance.getEntriesByType('resource'); 541 return resources.find(r => { 542 return r.name === metadata.url && 543 Math.abs(r.startTime - measure.startTime) <= TIME_TOLERANCE && 544 (r.initiatorType === 'fetch' || r.initiatorType === 'xmlhttprequest'); 545 }); 546 }; 547 let resource = findMatchingResource(); 548 if (!resource) { 549 // çå»¶è¿åéè¯ä¸æ¬¡ 550 setTimeout(() => { 551 const r = findMatchingResource(); 552 if (r) { 553 handleResourceTiming(r); 554 } 555 }, 100); 556 } 557 else { 558 handleResourceTiming(resource); 559 } 560 } 561 /** 562 * å¢å¼ºçè¯·æ±æ è®° - WebView å ¼å®¹ 563 */ 564 function createRequestMark(requestId, url) { 565 if (!('performance' in window)) { 566 return createFallbackMark(requestId, url); 567 } 568 const OControl = getOriginalConsole(); 569 const capabilities = detectWebViewCapabilities(); 570 if (!capabilities.supportUserTiming) { 571 return createFallbackMark(requestId, url); 572 } 573 try { 574 const measureName = `api-request-${requestId}`; 575 const startMarkName = `api-start-${requestId}`; 576 const endMarkName = `api-end-${requestId}`; 577 measureRequestMap.set(measureName, requestId); 578 // å®å ¨ç mark å建 579 try { 580 performance.mark(startMarkName); 581 } 582 catch (markError) { 583 OControl.warn('Failed to create start mark:', markError); 584 return createFallbackMark(requestId, url); 585 } 586 return { 587 markEnd: () => { 588 try { 589 performance.mark(endMarkName); 590 performance.measure(measureName, startMarkName, endMarkName); 591 // å°è¯è®¾ç½® detailï¼ä½ä¸å¼ºå¶è¦æ± 592 try { 593 const measures = performance.getEntriesByName(measureName, 'measure'); 594 if (measures.length > 0) { 595 measures[0].detail = { requestId, url }; 596 } 597 } 598 catch (detailError) { 599 // å¿½ç¥ detail 设置失败 600 } 601 } 602 catch (error) { 603 OControl.warn('Failed to create performance measure:', error); 604 } 605 }, 606 cleanup: () => { 607 var _a, _b, _c; 608 try { 609 (_a = performance.clearMarks) === null || _a === void 0 ? void 0 : _a.call(performance, startMarkName); 610 (_b = performance.clearMarks) === null || _b === void 0 ? void 0 : _b.call(performance, endMarkName); 611 (_c = performance.clearMeasures) === null || _c === void 0 ? void 0 : _c.call(performance, measureName); 612 measureRequestMap.delete(measureName); 613 } 614 catch (error) { 615 // å¿½ç¥æ¸ çé误 616 } 617 } 618 }; 619 } 620 catch (error) { 621 OControl.warn('Failed to create performance mark:', error); 622 return createFallbackMark(requestId, url); 623 } 624 } 625 /** 626 * é级æ è®°æ¹æ¡ - 使ç¨ç®åæ¶é´è®°å½ 627 */ 628 function createFallbackMark(requestId, url) { 629 const startTime = performance.now(); 630 return { 631 markEnd: () => { 632 const endTime = performance.now(); 633 const duration = endTime - startTime; 634 // ç´æ¥è§¦åå¤çï¼ä¸ä¾èµ PerformanceObserver 635 setTimeout(() => { 636 handleFallbackTiming(requestId, url, startTime, duration); 637 }, 0); 638 }, 639 cleanup: () => { 640 // æ¸ ç requestMetadata 641 requestMetadata.delete(requestId); 642 } 643 }; 644 } 645 /** 646 * é级æ¶åºå¤ç 647 */ 648 function handleFallbackTiming(requestId, url, startTime, duration) { 649 const metadata = requestMetadata.get(requestId); 650 if (!metadata) 651 return; 652 // å建åºç¡æ§è½æ°æ®ï¼æ²¡æè¯¦ç»çç½ç»æ¶åºï¼ 653 const performanceData = { 654 url: metadata.url, 655 type: metadata.type, 656 startTime, 657 duration, 658 name: `${metadata.method} ${metadata.url}`, 659 requestId, 660 status: metadata.status, 661 success: metadata.success, 662 // WebView ä¸å¯è½æ æ³è·åçè¯¦ç»æ¶åºï¼è®¾ä¸º 0 æ undefined 663 dns: 0, 664 tcp: 0, 665 ssl: 0, 666 ttfb: 0, 667 responseTime: duration, // ä½¿ç¨æ»æ¶é¿ä½ä¸ºååºæ¶é´
668 }; 669 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.API_PERFORMANCE, performanceData); 670 // æ¸ çæ°æ® - æ·»å cleanup è°ç¨ 671 if (metadata.performanceMark) { 672 metadata.performanceMark.cleanup(); 673 } 674 requestMetadata.delete(requestId); 675 } 676 function setupApiPerformanceMonitoring() { 677 const capabilities = detectWebViewCapabilities(); 678 // æ ¹æ®ç¯å¢è°æ´é ç½® 679 if (capabilities.isWebView) { 680 // WebView ç¯å¢ï¼ä½¿ç¨æ´ä¿å®çé ç½® 681 TIME_TOLERANCE = 200; // å¢å æ¶é´å®¹é 682 } 683 performanceObservers = setupPerformanceObserver(); 684 } 685 function disableApiPerformanceMonitoring() { 686 if (performanceObservers) { 687 performanceObservers.resourceObserver.disconnect(); 688 performanceObservers.measureObserver.disconnect(); 689 performanceObservers = undefined; 690 } 691 // æ¸ ç请æ±å æ°æ®åæ§è½æ è®° 692 for (const [requestId, metadata] of requestMetadata) { 693 if (metadata.performanceMark) { 694 metadata.performanceMark.cleanup(); 695 } 696 } 697 requestMetadata.clear(); 698 measureRequestMap.clear(); // æ¸ çæ å° 699 } 700 701 var PlatformTypeEnum; 702 (function (PlatformTypeEnum) { 703 PlatformTypeEnum["WEB"] = "web"; 704 PlatformTypeEnum["H5"] = "h5"; 705 PlatformTypeEnum["XT_DESKTOP"] = "X-Desktop"; 706 })(PlatformTypeEnum || (PlatformTypeEnum = {})); 707 708 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; 709 710 var bridge = { 711 default:commonjsGlobal,// for typescript 712 call: function (method, args, cb) { 713 var ret = ''; 714 if (typeof args == 'function') { 715 cb = args; 716 args = {}; 717 } 718 var arg={data:args===undefined?null:args}; 719 if (typeof cb == 'function') { 720 var cbName = 'dscb' + window.dscb++; 721 window[cbName] = cb; 722 arg['_dscbstub'] = cbName; 723 } 724 arg = JSON.stringify(arg); 725 726 //if in webview that dsBridge provided, call! 727 if(window._dsbridge){ 728 ret= _dsbridge.call(method, arg); 729 }else if(window._dswk||navigator.userAgent.indexOf("_dsbridge")!=-1){ 730 ret = prompt("_dsbridge=" + method, arg); 731 } 732 733 return JSON.parse(ret||'{}').data 734 }, 735 register: function (name, fun, asyn) { 736 var q = asyn ? window._dsaf : window._dsf; 737 if (!window._dsInit) { 738 window._dsInit = true; 739 //notify native that js apis register successfully on next event loop 740 setTimeout(function () { 741 bridge.call("_dsb.dsinit"); 742 }, 0); 743 } 744 if (typeof fun == "object") { 745 q._obs[name] = fun; 746 } else { 747 q[name] = fun; 748 } 749 }, 750 registerAsyn: function (name, fun) { 751 this.register(name, fun, true); 752 }, 753 hasNativeMethod: function (name, type) { 754 return this.call("_dsb.hasNativeMethod", {name: name, type:type||"all"}); 755 }, 756 disableJavascriptDialogBlock: function (disable) { 757 this.call("_dsb.disableJavascriptDialogBlock", { 758 disable: disable !== false 759 }); 760 } 761 }; 762 763 !function () { 764 if (window._dsf) return; 765 var ob = { 766 _dsf: { 767 _obs: {} 768 }, 769 _dsaf: { 770 _obs: {} 771 }, 772 dscb: 0, 773 dsBridge: bridge, 774 close: function () { 775 bridge.call("_dsb.closePage"); 776 }, 777 _handleMessageFromNative: function (info) { 778 var arg = JSON.parse(info.data); 779 var ret = { 780 id: info.callbackId, 781 complete: true 782 }; 783 var f = this._dsf[info.method]; 784 var af = this._dsaf[info.method]; 785 var callSyn = function (f, ob) { 786 ret.data = f.apply(ob, arg); 787 bridge.call("_dsb.returnValue", ret); 788 }; 789 var callAsyn = function (f, ob) { 790 arg.push(function (data, complete) { 791 ret.data = data; 792 ret.complete = complete!==false; 793 bridge.call("_dsb.returnValue", ret); 794 }); 795 f.apply(ob, arg); 796 }; 797 if (f) { 798 callSyn(f, this._dsf); 799 } else if (af) { 800 callAsyn(af, this._dsaf); 801 } else { 802 //with namespace 803 var name = info.method.split('.'); 804 if (name.length<2) return; 805 var method=name.pop(); 806 var namespace=name.join('.'); 807 var obs = this._dsf._obs; 808 var ob = obs[namespace] || {}; 809 var m = ob[method]; 810 if (m && typeof m == "function") { 811 callSyn(m, ob); 812 return; 813 } 814 obs = this._dsaf._obs; 815 ob = obs[namespace] || {}; 816 m = ob[method]; 817 if (m && typeof m == "function") { 818 callAsyn(m, ob); 819 return; 820 } 821 } 822 } 823 }; 824 for (var attr in ob) { 825 window[attr] = ob[attr]; 826 } 827 bridge.register("_hasJavascriptMethod", function (method, tag) { 828 var name = method.split('.'); 829 if(name.length<2) {
830 return !!(_dsf[name]||_dsaf[name]) 831 }else { 832 // with namespace 833 var method=name.pop(); 834 var namespace=name.join('.'); 835 var ob=_dsf._obs[namespace]||_dsaf._obs[namespace]; 836 return ob&&!!ob[method] 837 } 838 }); 839 }(); 840 841 var dsbridge = bridge; 842 843 var NativeAPI; 844 (function (NativeAPI) { 845 NativeAPI["SESSION_ID"] = "sessionId"; 846 NativeAPI["CLIENT_ID"] = "clientId"; 847 })(NativeAPI || (NativeAPI = {})); 848 function call(api, params, callback) { 849 const oControl = getOriginalConsole(); 850 if (typeof window == "undefined") 851 return; 852 try { 853 if (dsbridge.hasNativeMethod(api)) { 854 return dsbridge.call(api, params, callback); 855 } 856 else { 857 oControl.warn("ãlogErrãæ²¡ææ¾å°å¯¹åºçNativeæ¹æ³ï¼%s", api); 858 } 859 } 860 catch (e) { 861 oControl.error("ãlogErrãcall %sï¼%o", api, e); 862 } 863 } 864 function getSessionId() { 865 return call(NativeAPI.SESSION_ID) || ""; 866 } 867 function getClientId() { 868 return call(NativeAPI.CLIENT_ID) || ""; 869 } 870 var jsbridge = { 871 getSessionId, 872 getClientId, 873 call, 874 }; 875 876 var OSTypeEnum; 877 (function (OSTypeEnum) { 878 OSTypeEnum["IOS"] = "ios"; 879 OSTypeEnum["ANDROID"] = "android"; 880 OSTypeEnum["MAC"] = "mac"; 881 OSTypeEnum["WINDOWS"] = "windows"; 882 OSTypeEnum["UNKNOWN"] = "unknown"; 883 })(OSTypeEnum || (OSTypeEnum = {})); 884 885 function getDeviceInfo() { 886 const ua = navigator === null || navigator === void 0 ? void 0 : navigator.userAgent; 887 if (!ua) 888 return {}; 889 return { 890 userAgent: ua, 891 language: navigator === null || navigator === void 0 ? void 0 : navigator.language, 892 os: getOS(), 893 }; 894 } 895 function getOS() { 896 const ua = window.navigator.userAgent.toLowerCase(); 897 if (ua.includes("iphone") || ua.includes("ipad") || ua.includes("ipod")) { 898 return OSTypeEnum.IOS; 899 } 900 if (ua.includes("android")) { 901 return OSTypeEnum.ANDROID; 902 } 903 if (ua.includes("macintosh")) { 904 return OSTypeEnum.MAC; 905 } 906 if (ua.includes("windows")) { 907 return OSTypeEnum.WINDOWS; 908 } 909 return OSTypeEnum.UNKNOWN; 910 } 911 function isDesktop() { 912 var _a, _b; 913 const ua = ((_b = (_a = window === null || window === void 0 ? void 0 : window.navigator) === null || _a === void 0 ? void 0 : _a.userAgent) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || ""; 914 if (ua.includes("xt-desktop")) { 915 return true; 916 } 917 return false; 918 } 919 function getPlatform() { 920 const os = getOS(); 921 if (os === OSTypeEnum.IOS || os === OSTypeEnum.ANDROID) { 922 return PlatformTypeEnum.H5; 923 } 924 if (isDesktop()) { 925 return PlatformTypeEnum.XT_DESKTOP; 926 } 927 return PlatformTypeEnum.WEB; 928 } 929 930 const _CLIENT_CODE_KEY = "__xt_client_code__"; 931 const generateUniqueIdentifier = function () { 932 // å¢å¼ºçï¼æ¶é´æ³ + æ´é¿éæºå符串 + 计æ°å¨ 933 const timestamp = Date.now().toString(36); 934 const random = Math.random().toString(36).substring(2, 15); // 13ä½éæºå符 935 const counter = ((Math.random() * 1000) | 0).toString(36); // 3ä½è®¡æ°å¨ 936 return `${timestamp}-${random}-${counter}`; 937 }; 938 const createClientCode = function () { 939 let code = ""; 940 if (window.localStorage) { 941 code = window.localStorage.getItem(_CLIENT_CODE_KEY) || ""; 942 if (!code) { 943 code = generateUniqueIdentifier(); 944 window.localStorage.setItem(_CLIENT_CODE_KEY, code); 945 } 946 } 947 return code; 948 }; 949 const getUserId = () => { 950 getUserId.userId = getUserId.userId || 0; 951 // æ£æ¥æ¯å¦å¨æµè§å¨ç¯å¢ä¸ 952 if (typeof window === "undefined" || typeof document === "undefined") { 953 return getUserId.userId; 954 } 955 try { 956 var cookie = (document === null || document === void 0 ? void 0 : document.cookie) || ""; 957 if (getUserId.cookie === cookie) 958 return getUserId.userId; 959 getUserId.cookie = cookie; 960 var tokenPart = cookie.split("token=")[1]; 961 if (!tokenPart) 962 return getUserId.userId; 963 getUserId.userId = JSON.parse(atob(tokenPart.split(".")[1])).userId || 0; 964 return getUserId.userId; 965 } 966 catch (e) { 967 return getUserId.userId; 968 } 969 }; 970 function getClientCode() { 971 let clientCode = ""; 972 // æ£æ¥æ¯å¦å¨æµè§å¨ç¯å¢ä¸ 973 if (typeof window === "undefined" || typeof document === "undefined") { 974 return ""; 975 } 976 // native ä¼å éè¿ jsbridge è·å clientId 977 if (getPlatform() === PlatformTypeEnum.H5) { 978 const clientId = jsbridge.getClientId(); 979 if (clientId) { 980 return clientId; 981 } 982 } 983 // 妿䏿¯ H5 平尿æªè½ä» H5 容å¨è·å clientIdï¼åç
983ææ°çå¯ä¸æ è¯ç¬¦ 984 try { 985 clientCode = document.cookie.split("clientCode=")[1].split(";")[0]; 986 if (!clientCode) { 987 clientCode = createClientCode(); 988 } 989 } 990 catch (e) { 991 clientCode = createClientCode(); 992 } 993 return clientCode; 994 } 995 996 /** 997 * çå¬ fetch è¯·æ± 998 */ 999 function overrideFetch() { 1000 if (!window.fetch) 1001 return; 1002 const originFetch = window.fetch; 1003 window.fetch = function (input, init) { 1004 const url = typeof input === "string" ? input : input.toString(); 1005 const method = (init === null || init === void 0 ? void 0 : init.method) || "GET"; 1006 const requestId = generateUniqueIdentifier(); 1007 // å建æ§è½æ è®° 1008 const performanceMark = createRequestMark(requestId, url); 1009 // åå¨è¯·æ±ä¿¡æ¯ 1010 requestMetadata.set(requestId, { 1011 url, 1012 method, 1013 type: API_TYPE.FETCH, 1014 startTime: performance.now(), 1015 performanceMark, 1016 }); 1017 return originFetch 1018 .call(this, input, init) 1019 .then((response) => { 1020 // ç»ææ§è½æ è®° 1021 const metadata = requestMetadata.get(requestId); 1022 if (metadata === null || metadata === void 0 ? void 0 : metadata.performanceMark) { 1023 metadata.performanceMark.markEnd(); 1024 } 1025 // æ´æ°è¯·æ±ç»æä¿¡æ¯ 1026 if (metadata) { 1027 metadata.status = response.status; 1028 metadata.success = response.ok; 1029 } 1030 // 䏿¥åºç¡æåä¿¡æ¯ï¼æ§è½æ°æ®ç± PerformanceObserver å¤çï¼ 1031 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.FETCH_SUCCESS, { 1032 url, 1033 type: API_TYPE.FETCH, 1034 name: `${method} ${url}`, 1035 status: response.status, 1036 statusText: response.statusText, 1037 success: response.ok, 1038 requestId, 1039 }); 1040 // å¦æç¶æç 表示é误ï¼ä¹è¦è®°å½ 1041 if (!response.ok) { 1042 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.FETCH_HTTP_ERROR, { 1043 url, 1044 type: API_TYPE.FETCH, 1045 name: `${method} ${url}`, 1046 status: response.status, 1047 statusText: response.statusText, 1048 message: `HTTP ${response.status}: ${response.statusText}`, 1049 requestId, 1050 }); 1051 } 1052 return response; 1053 }) 1054 .catch((error) => { 1055 // ç»ææ§è½æ è®° 1056 const metadata = requestMetadata.get(requestId); 1057 if (metadata === null || metadata === void 0 ? void 0 : metadata.performanceMark) { 1058 metadata.performanceMark.markEnd(); 1059 } 1060 // æ´æ°è¯·æ±ç»æä¿¡æ¯ 1061 if (metadata) { 1062 metadata.success = false; 1063 } 1064 // è®°å½ç½ç»é误æå ¶ä»å¼å¸¸ 1065 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.FETCH_NETWORK_ERROR, { 1066 url, 1067 type: API_TYPE.FETCH, 1068 name: `${method} ${url}`, 1069 error: error.message, 1070 stack: error.stack, 1071 success: false, 1072 requestId, 1073 }); 1074 throw error; // éæ°æåºé误ï¼ä¿æåæè¡ä¸º 1075 }); 1076 }; 1077 } 1078 /** 1079 * çå¬ XMLHttpRequest è¯·æ± 1080 */ 1081 function overrideXHR() { 1082 if (!window.XMLHttpRequest) 1083 return; 1084 const OriginalXHR = window.XMLHttpRequest; 1085 function MonitorXMLHttpRequest() { 1086 const xhr = new OriginalXHR(); 1087 let url; 1088 let method; 1089 let requestId; 1090 let performanceMark; 1091 // éå open æ¹æ³æ¥è·å请æ±ä¿¡æ¯ 1092 const originalOpen = xhr.open; 1093 xhr.open = function (method_, url_, ...args) { 1094 method = method_; 1095 url = typeof url_ === "string" ? url_ : url_.toString(); 1096 requestId = generateUniqueIdentifier(); 1097 // å建æ§è½æ è®° 1098 performanceMark = createRequestMark(requestId, url); 1099 // åå¨è¯·æ±ä¿¡æ¯ 1100 requestMetadata.set(requestId, { 1101 url, 1102 method, 1103 type: API_TYPE.XHR, 1104 startTime: performance.now(), 1105 performanceMark, 1106 }); 1107 return originalOpen.apply(this, [method_, url_, ...args]); 1108 }; 1109 // æ°å¢ï¼éå send æ¹æ³ï¼è®°å½è¯·æ±ä½ 1110 const originalSend = xhr.send; 1111 xhr.send = function (body) { 1112 // è®°å½è¯·æ±åæ° 1113 xhr._requestBody = body; 1114 return originalSend.apply(this, [body]); 1115 }; 1116 // çå¬ç¶æåå 1117 xhr.addEventListener("readystatechange", function () { 1118 if (xhr.readyState === 4) { 1119 // 请æ±å®æ 1120 // ç»ææ§è½æ è®° 1121 if (performanceMark) { 1122 performanceMark.markEnd(); 1123 } 1124 // æ´æ°è¯·æ±ç»æä¿¡æ¯ 1125 const metadata = requestMetadata.get(requestId); 1126 if (metadata) { 1127 metadata.status = xhr.status; 1128 metadata.success = xhr.status >= 200 && xhr.status < 400; 1129 } 1130 const apiInfo = { 1131 url, 1132 type: API_TYPE.XHR, 1133 name: `${method} ${url}`, 1134 method, 1135 status: xhr.status, 1136 statusText: xhr.statusText, 1137 requestId, 1138 }; 1139 if (xhr.status === 0) { 1140 // ç½ç»é误æè¯·æ±è¢«åæ¶ 1141 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.XHR_NETWORK_E
1141RROR, Object.assign(Object.assign({}, apiInfo), { message: "Network error or request cancelled", success: false })); 1142 } 1143 else if (xhr.status >= 400) { 1144 // HTTP é误 1145 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.XHR_HTTP_ERROR, Object.assign(Object.assign({}, apiInfo), { message: `HTTP ${xhr.status}: ${xhr.statusText}` })); 1146 } 1147 else { 1148 try { 1149 // è·å请æ±åæ° 1150 const requestParams = xhr._requestBody; 1151 // è·åååºå å®¹ï¼æ³¨æï¼å¯è½æ¯ææ¬æjsonï¼ä¸å¤§å¯¹è±¡ä¸å»ºè®®ç´æ¥ä¸æ¥ï¼ 1152 let response = undefined; 1153 const [, queryString] = xhr.responseURL.split("?"); 1154 try { 1155 response = 1156 xhr.responseType === "" || xhr.responseType === "text" 1157 ? xhr.responseText 1158 : xhr.response; 1159 } 1160 catch (_a) { } 1161 let responseObject = undefined; 1162 if (typeof response === "string" && response) { 1163 try { 1164 responseObject = JSON.parse(response); 1165 } 1166 catch (_b) { 1167 responseObject = response; 1168 } 1169 } 1170 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.XHR_DETAIL, Object.assign(Object.assign({}, apiInfo), { requestParams, response: responseObject, queryString, success: true })); 1171 } 1172 catch (e) { 1173 // 忽ç¥åºååæè¯»åå¼å¸¸ 1174 } 1175 // æåè¯·æ± 1176 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.XHR_SUCCESS, Object.assign(Object.assign({}, apiInfo), { success: true })); 1177 } 1178 } 1179 }); 1180 // çå¬é误äºä»¶ 1181 xhr.addEventListener("error", function (error) { 1182 if (performanceMark) { 1183 performanceMark.markEnd(); 1184 } 1185 const metadata = requestMetadata.get(requestId); 1186 if (metadata) { 1187 metadata.success = false; 1188 } 1189 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.XHR_ERROR, { 1190 url, 1191 type: API_TYPE.XHR, 1192 name: `${method} ${url}`, 1193 method, 1194 message: "XMLHttpRequest error", 1195 success: false, 1196 requestId, 1197 error, 1198 }); 1199 }); 1200 // çå¬è¶ æ¶äºä»¶ 1201 xhr.addEventListener("timeout", function () { 1202 if (performanceMark) { 1203 performanceMark.markEnd(); 1204 } 1205 const metadata = requestMetadata.get(requestId); 1206 if (metadata) { 1207 metadata.success = false; 1208 } 1209 report(exports.ReportTypeEnum.API, exports.ReportNameEnum.XHR_TIMEOUT, { 1210 url, 1211 type: API_TYPE.XHR, 1212 name: `${method} ${url}`, 1213 method, 1214 message: "XMLHttpRequest timeout", 1215 success: false, 1216 requestId, 1217 }); 1218 }); 1219 return xhr; 1220 } 1221 // ä¿æååé¾åéæå±æ§ 1222 MonitorXMLHttpRequest.prototype = OriginalXHR.prototype; 1223 Object.setPrototypeOf(MonitorXMLHttpRequest, OriginalXHR); 1224 // å®å ¨å¤å¶éæå±æ§ï¼ä½¿ç¨æè¿°ç¬¦å¹¶è·³è¿ä¸å¯åæä¼æ¥éç屿§ 1225 Object.getOwnPropertyNames(OriginalXHR).forEach((prop) => { 1226 // è·³è¿ prototype/name/length çä¸åºè¢«è¦ççå ç½®å±æ§ 1227 if (prop === "prototype" || prop === "name" || prop === "length") 1228 return; 1229 const desc = Object.getOwnPropertyDescriptor(OriginalXHR, prop); 1230 if (!desc) 1231 return; 1232 // 妿屿§æ¯ä¸å¯é ç½®ä¸ç®æ å·²æååä¸å¯é ç½®å±æ§ï¼è·³è¿ 1233 try { 1234 Object.defineProperty(MonitorXMLHttpRequest, prop, desc); 1235 } 1236 catch (e) {
1237 // å¿½ç¥æ æ³å®ä¹ç屿§ï¼å¦åªè¯»å ç½®å±æ§ï¼ 1238 } 1239 }); 1240 window.XMLHttpRequest = MonitorXMLHttpRequest; 1241 } 1242 1243 var API_TYPE; 1244 (function (API_TYPE) { 1245 API_TYPE["FETCH"] = "fetch"; 1246 API_TYPE["XHR"] = "xhr"; 1247 })(API_TYPE || (API_TYPE = {})); 1248 // åå¨è¯·æ±çé¢å¤ä¿¡æ¯ï¼ä½¿ç¨ requestId ä½ä¸º key 1249 const requestMetadata = new Map(); 1250 function setupListenerApi() { 1251 setupApiPerformanceMonitoring(); 1252 overrideFetch(); 1253 overrideXHR(); 1254 } 1255 // å¨ restoreAPI 䏿¸ çæ å° 1256 function disableListenerApi() { 1257 disableApiPerformanceMonitoring(); 1258 } 1259 var apiMonitor = { 1260 setupListenerApi, 1261 disableListenerApi, 1262 }; 1263 1264 const SESSION_KEY = "__xt_tracker_session_id__"; 1265 const SESSION_EXPIRE_MINUTES = 30; // è¿ææ¶é´ 1266 function createSessionId() { 1267 // ä¼å ä» H5 容å¨è·å sessionId 1268 if (PlatformTypeEnum.H5 === getPlatform()) { 1269 const sessionId = jsbridge.getSessionId(); 1270 if (sessionId) { 1271 return sessionId; 1272 } 1273 } 1274 // 妿䏿¯ H5 平尿æªè½ä» H5 容å¨è·å sessionIdï¼åçææ°çå¯ä¸æ è¯ç¬¦ 1275 return generateUniqueIdentifier(); 1276 } 1277 /** 1278 * åå»ºææ´æ°ä¼è¯ 1279 * @returns {SessionInfo} ä¼è¯ä¿¡æ¯ 1280 */ 1281 function createOrUpdateSession() { 1282 const now = Date.now(); 1283 const sessionStr = sessionStorage.getItem(SESSION_KEY); 1284 let sessionData = { 1285 sessionId: "", 1286 sessionStartTime: now, 1287 sessionDuration: 0, 1288 lastActive: now, 1289 }; 1290 if (sessionStr) { 1291 try { 1292 sessionData = JSON.parse(sessionStr); 1293 const inactiveTime = (now - sessionData.lastActive) / (1000 * 60); 1294 // 妿ä¼è¯å¨è¿ææ¶é´å ï¼åæ´æ°ä¼è¯ 1295 if (inactiveTime < SESSION_EXPIRE_MINUTES) { 1296 sessionData.sessionDuration = now - sessionData.sessionStartTime || 0; 1297 sessionData.lastActive = now; 1298 localStorage.setItem(SESSION_KEY, JSON.stringify(sessionData)); 1299 return sessionData; 1300 } 1301 } 1302 catch (e) { 1303 // ignore 1304 } 1305 } 1306 // å建æ°ä¼è¯, 妿ä¼è¯å·²è¿æä¹ä¼å建æ°çä¼è¯ 1307 const newSession = { 1308 sessionId: createSessionId(), 1309 sessionStartTime: now, 1310 sessionDuration: 0, 1311 lastActive: now, 1312 }; 1313 sessionStorage.setItem(SESSION_KEY, JSON.stringify(newSession)); 1314 return newSession; 1315 } 1316 1317 /****************************************************************************** 1318 Copyright (c) Microsoft Corporation. 1319 1320 Permission to use, copy, modify, and/or distribute this software for any 1321 purpose with or without fee is hereby granted. 1322 1323 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 1324 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1325 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 1326 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 1327 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 1328 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 1329 PERFORMANCE OF THIS SOFTWARE. 1330 ***************************************************************************** */ 1331 1332 function __awaiter(thisArg, _arguments, P, generator) { 1333 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1334 return new (P || (P = Promise))(function (resolve, reject) { 1335 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1336 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1337 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1338 step((generator = generator.apply(thisArg, _arguments || [])).next()); 1339 }); 1340 } 1341 1342 typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { 1343 var e = new Error(message); 1344 return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; 1345 }; 1346 1347 let lastPageUrl = window.location.href; 1348 function getPageInfo() { 1349 var _a; 1350 const page = { 1351 url: (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.href, 1352 title: document === null || document === void 0 ? void 0 : document.title, 1353 referrer: document.referrer 1354 ? document.referrer 1355 : lastPageUrl !== window.location.href 1356 ? lastPageUrl 1357 : "", 1358 }; 1359 lastPageUrl = window.location.href; 1360 return page; 1361 } 1362 /** 1363 * çå¬é¡µé¢å¸è½½äºä»¶, å·æ° & å ³é 1364 * @param event 1365 */ 1366 const beforeunloadHandler = (event) => { 1367 flushImmediateReports(); 1368 apiMonitor.disableListenerApi(); 1369 errorMonitor.disabledErrorListener(); 1370 window.removeEventListener("beforeunload", beforeunloadHandler, true); 1371 window.removeEventListener("visibilitychange", visibilitychangeHandler, true); 1372 window.removeEventListener("blur", blurHandler, true); 1373 window.removeEventListener("focus", focusHandler, true); 1374 document.removeEventListener("click", onClick, true); 1375 }; 1376 const visibilitychangeHandler = (event) => { 1377 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.VISIBILITY_CHANGE, { 1378 state: document.visibilityState, 1379 }); 1380 if (!document.hidden) { 1381 flushImmediateReports(); 1382 } 1383 }; 1384 /** 䏿¥ pv */ 1385 const pv = function (args) { 1386 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.PAGE_VIEW, { args }, undefined, true); 1387 }; 1388 /** çæ§ pv 䏿¥ */ 1389 const pvListener = function () { 1390 const { history } = window || {}; 1391 const originalPushState = history === null || history === void 0 ? void 0 : history.pushState; 1392 const originalReplaceState = history === null || history === void 0 ? void 0 : history.replaceState; 1393 if (!originalPushState || !originalReplaceState) 1394 return; 1395 history.pushState = function (...args) { 1396 // å¤ç pushState é»è¾ 1397 originalPushState.apply(this, args); 1398 pv(args); 1399 }; 1400 history.replaceState = function (...args) { 1401 // å¤ç replaceState é»è¾ 1402 originalReplaceState.apply(this, args); 1403 const pageInfo = getPageInfo(); 1404 if (pageInfo.url !== lastPageUrl) { 1405 pv(args); 1406 } 1407 }; 1408 }; 1409 const blurHandler = function (event) { 1410 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.TAB_CHANGE, { type: "blur" }); 1411 }; 1412 const focusHandler = function (event) { 1413 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.TAB_CHANGE, { type: "focus" }); 1414 }; 1415 const onClick = (e) => __awaiter(void 0, void 0, void 0, function* () { 1416 const target = e.target; 1417 if (!target) 1418 return; 1419 if (target === document.documentElement) { 1420 // target æ¯ html æ ¹ç®å½ 1421 return; 1422 } 1423 if (target === document.body) { 1424 // target æ¯ body å ç´ 1425 return; 1426 } 1427 let outerHTML = target.outerHTML; 1428 if (outerHTML && outerHTML.length > 1000) { 1429 outerHTML = outerHTML.substring(0, 1000); 1430 } 1431 const meta = { 1432 tagName: target.tagName, 1433 id: target.id, 1434 className: target.className, 1435 outerHTML, 1436 }; 1437 report(exports.ReportTypeEnum.EVENT, exports.ReportNameEnum.CLICK, e, meta); 1438 }); 1439 function setupListenerPage() { 1440 // "beforeunload" å¨é¡µé¢å·æ°ãå ³éã跳转æ¶è§¦åï¼éåå离å¼ä¸æ¥ï¼ä½é¨åæµè§å¨å¯è½éå¶å¼æ¥æä½ 1441 window === null || window === void 0 ? void 0 : window.addEventListener("beforeunload", beforeunloadHandler, true); 1442 // "visibilitychange" 主è¦ç¨äºé¡µé¢å¯è§æ§ååï¼ä¸ä¸å®ä»£è¡¨ç¦»å¼é¡µé¢ï¼ä¸å»ºè®®åç¬ç¨äºç¦»å¼ä¸æ¥ 1443 window === null || window === void 0 ? void 0 : window.addEventListener("visibilitychange", visibilitychangeHandler, true); 1444 // tab 忢çå¬ 1445 window.addEventListener("blur", blurHandler, true); 1446 window.addEventListener("focus", focusHandler, true); 1447 /** çå¬é¡µé¢ä¸çç¹å»äºä»¶ */ 1448 document.addEventListener("click", onClick, true); 1449 // çå¬ pv 䏿¥ 1450 pvListener(); 1451 } 1452 var page = { 1453 setupListenerPage, 1454 getPageInfo, 1455 pv, 1456 }; 1457 1458 // src/monitor/socket.ts 1459 // WebSocket è¿æ¥æ å°ï¼ç¨äºè·è¸ªæ¯ä¸ªè¿æ¥çç¶æ 1460 const socketConnections = new Map(); 1461 /** 1462 * è®¡ç®æ¶æ¯å¤§å°ï¼åèï¼ 1463 */
1464 function getMessageSize(data) { 1465 if (typeof data === "string") { 1466 return new Blob([data]).size; 1467 } 1468 if (data instanceof ArrayBuffer) { 1469 return data.byteLength; 1470 } 1471 if (data instanceof Blob) { 1472 return data.size; 1473 } 1474 return 0; 1475 } 1476 /** 1477 * 计ç®å»¶è¿ 1478 */ 1479 function calculateLatency(connectionData) { 1480 const { latencyHistory } = connectionData; 1481 if (latencyHistory.length === 0) 1482 return 0; 1483 const sum = latencyHistory.reduce((a, b) => a + b, 0); 1484 return Math.round(sum / latencyHistory.length); 1485 } 1486 /** 1487 * è¦çåç WebSocket 1488 */ 1489 function overrideWebSocket() { 1490 if (!window.WebSocket) 1491 return; 1492 const OriginalWebSocket = window.WebSocket; 1493 const OControl = getOriginalConsole(); 1494 function MonitorWebSocket(url, protocols) { 1495 const socketUrl = url.toString(); 1496 const socketProtocol = Array.isArray(protocols) 1497 ? protocols.join(",") 1498 : protocols || ""; 1499 const socketId = generateUniqueIdentifier(); 1500 const connectStartTime = Date.now(); 1501 // åå§åè¿æ¥æ°æ® 1502 const connectionData = { 1503 url: socketUrl, 1504 protocol: socketProtocol, 1505 connectTime: connectStartTime, 1506 messageCount: 0, 1507 sentBytes: 0, 1508 receivedBytes: 0, 1509 reconnectCount: 0, 1510 latencyHistory: [], 1511 }; 1512 // å建åå§ WebSocket å®ä¾ 1513 const ws = new OriginalWebSocket(url, protocols); 1514 const connectingInfo = Object.assign(Object.assign({}, connectionData), { readyState: ws.readyState }); 1515 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_CONNECTING, connectingInfo); 1516 // ç«å³è®¾ç½®è¿æ¥æ°æ®æ å° 1517 socketConnections.set(ws, connectionData); 1518 // çå¬è¿æ¥æå¼ 1519 ws.addEventListener("open", function (event) { 1520 const connectTime = Date.now() - connectStartTime; 1521 const socketInfo = { 1522 url: socketUrl, 1523 protocol: socketProtocol, 1524 readyState: ws.readyState, 1525 connectTime, 1526 duration: connectTime, 1527 messageCount: 0, 1528 sentBytes: 0, 1529 receivedBytes: 0, 1530 socketId, 1531 }; 1532 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_CONNECT, socketInfo); 1533 }); 1534 // çå¬è¿æ¥å ³é 1535 ws.addEventListener("close", function (event) { 1536 const data = socketConnections.get(ws); 1537 if (data) { 1538 const totalDuration = Date.now() - data.connectTime; 1539 const socketInfo = { 1540 url: socketUrl, 1541 protocol: socketProtocol, 1542 readyState: ws.readyState, 1543 duration: totalDuration, 1544 messageCount: data.messageCount, 1545 sentBytes: data.sentBytes, 1546 receivedBytes: data.receivedBytes, 1547 reconnectCount: data.reconnectCount, 1548 latency: calculateLatency(data), 1549 // ä» CloseEvent.code 读åå ³éç ï¼è¥æªæä¾å为 undefined 1550 errorCode: typeof event.code === "number" ? event.code : undefined, 1551 errorMessage: event.reason || getCloseReasonText(event.code), 1552 socketId, 1553 wasClean: event.wasClean, 1554 closeCode: event.code, 1555 closeReason: event.reason, 1556 }; 1557 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_DISCONNECT, socketInfo); 1558 socketConnections.delete(ws); 1559 } 1560 }); 1561 // ç嬿¶æ¯æ¥æ¶ 1562 ws.addEventListener("message", function (event) { 1563 const data = socketConnections.get(ws); 1564 if (data) { 1565 const messageSize = getMessageSize(event.data); 1566 data.messageCount++; 1567 data.receivedBytes += messageSize; 1568 // æ£æµ pong ååºè®¡ç®å»¶è¿ 1569 if (event.data === "pong" && data.lastPingTime) { 1570 const latency = Date.now() - data.lastPingTime; 1571 data.latencyHistory.push(latency); 1572 if (data.latencyHistory.length > 10) { 1573 data.latencyHistory.shift(); 1574 } 1575 data.lastPingTime = undefined; 1576 } 1577 } 1578 }); 1579 // çå¬é误 - å¢å¼ºé误å¤ç 1580 ws.addEventListener("error", function (event) { 1581 const data = socketConnections.get(ws); 1582 // å°è¯ä»äºä»¶ä¸è·åæ´å¤éè¯¯ä¿¡æ¯ 1583 let errorMessage = "WebSocket connection error"; 1584 let errorType = "connection"; 1585 // æ£æ¥ä¸åç±»åçé误 1586 if (ws.readyState === WebSocket.CONNECTING) { 1587 errorType = "connection_failed"; 1588 errorMessage = "Failed to establish WebSocket connection"; 1589 } 1590 else if (ws.readyState === WebSocket.OPEN) { 1591 errorType = "runtime_error"; 1592 errorMessage = "WebSocket runtime error"; 1593 } 1594 else if (ws.readyState === WebSocket.CLOSING || 1595 ws.readyState === WebSocket.CLOSED) { 1596 errorType = "disconnection_error"; 1597 errorMessage = "WebSocket disconnection error"; 1598 } 1599 // æ£æ¥ç½ç»é误 1600 if (navigator.onLine === false) { 1601 errorType = "network_offline"; 1602 errorMessage = "Network is offline"; 1603 } 1604 const socketInfo = { 1605 url: socketUrl, 1606 protocol: socketProtocol, 1607 readyState: ws.readyState, 1608 errorType, 1609 errorMessage, 1610 messageCount: (data === null || data === void 0 ? void 0 : data.messageCount) || 0, 1611 sentBytes: (data === null || data === void 0 ? void 0 : data.sentBytes) || 0, 1612 receivedBytes: (data === null || data === void 0 ? void 0 : data.receivedBytes) || 0, 1613 reconnectCount: (data === null || data === void 0 ? void 0 : data.reconnectCount) || 0, 1614 }; 1615 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_ER
1615ROR, socketInfo); 1616 }); 1617 // éå send æ¹æ³ï¼æ·»å åéé误å¤ç 1618 const originalSend = ws.send.bind(ws); 1619 ws.send = function (data) { 1620 var _a, _b; 1621 const connectionData = socketConnections.get(ws); 1622 // Transparency rule: behave EXACTLY like the native WebSocket.send(), never 1623 // adding or removing an exception. 1624 // - CLOSING / CLOSED: native silently DISCARDS the message (no throw). The 1625 // original wrapper threw here, turning a normally-silent no-op into an 1626 // exception that escaped to window.onerror (a trade-page heartbeat firing 1627 // on a backgrounded app webview) â the bulk of the "WebSocket is 1628 // CLOSING/CLOSED" reports. Record telemetry and return, matching native. 1629 // - CONNECTING: native THROWS InvalidStateError; we deliberately do NOT 1630 // intercept it (it falls through to originalSend below) so that behavior 1631 // is preserved unchanged. Heartbeats start on 'open', so this is rarely hit. 1632 if (ws.readyState === WebSocket.CLOSING || 1633 ws.readyState === WebSocket.CLOSED) { 1634 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_SEND_ERROR, { 1635 url: socketUrl, 1636 protocol: socketProtocol, 1637 readyState: ws.readyState, 1638 errorMessage: `Send skipped: WebSocket is ${getReadyStateText(ws.readyState)}`, 1639 messageCount: (connectionData === null || connectionData === void 0 ? void 0 : connectionData.messageCount) || 0, 1640 sentBytes: (connectionData === null || connectionData === void 0 ? void 0 : connectionData.sentBytes) || 0, 1641 socketId, 1642 // Do NOT log the raw frame: trade login frames carry token/apiKey/sign as 1643 // a JSON string that sensitive() cannot scrub. Report only shape + size. 1644 dataType: typeof data === "string" 1645 ? "string" 1646 : ((_a = data === null || data === void 0 ? void 0 : data.constructor) === null || _a === void 0 ? void 0 : _a.name) || typeof data, 1647 byteLength: getMessageSize(data), 1648 }); 1649 return; 1650 } 1651 try { 1652 if (connectionData) { 1653 const messageSize = getMessageSize(data); 1654 connectionData.sentBytes += messageSize; 1655 connectionData.messageCount++; 1656 // æ£æµ ping æ¶æ¯ 1657 if (data === "ping") { 1658 connectionData.lastPingTime = Date.now(); 1659 } 1660 } 1661 return originalSend.call(this, data); 1662 } 1663 catch (error) { 1664 // Reached for a CONNECTING send (native InvalidStateError) or a genuine 1665 // OPEN-state send failure â both are native behavior; report + re-throw. 1666 const cd = socketConnections.get(ws); 1667 const socketInfo = { 1668 url: socketUrl, 1669 protocol: socketProtocol, 1670 readyState: ws.readyState, 1671 errorMessage: `Send message failed: ${error === null || error === void 0 ? void 0 : error.message}`, 1672 messageCount: (cd === null || cd === void 0 ? void 0 : cd.messageCount) || 0, 1673 sentBytes: (cd === null || cd === void 0 ? void 0 : cd.sentBytes) || 0, 1674 socketId, 1675 error: error.message, 1676 // Do NOT log the raw frame (token/apiKey/sign leak); report shape + size. 1677 dataType: typeof data === "string" 1678 ? "string" 1679 : ((_b = data === null || data === void 0 ? void 0 : data.constructor) === null || _b === void 0 ? void 0 : _b.name) || typeof data, 1680 byteLength: getMessageSize(data), 1681 }; 1682 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_SEND_ERROR, socketInfo); 1683 throw error; 1684 } 1685 }; 1686 return ws; 1687 } 1688 // å¤å¶éæå±æ§ 1689 Object.setPrototypeOf(MonitorWebSocket, OriginalWebSocket); 1690 MonitorWebSocket.prototype = OriginalWebSocket.prototype; 1691 // å®å ¨å¤å¶éæå¸¸é
1692 try { 1693 Object.defineProperty(MonitorWebSocket, "CONNECTING", { 1694 value: OriginalWebSocket.CONNECTING, 1695 writable: false, 1696 }); 1697 Object.defineProperty(MonitorWebSocket, "OPEN", { 1698 value: OriginalWebSocket.OPEN, 1699 writable: false, 1700 }); 1701 Object.defineProperty(MonitorWebSocket, "CLOSING", { 1702 value: OriginalWebSocket.CLOSING, 1703 writable: false, 1704 }); 1705 Object.defineProperty(MonitorWebSocket, "CLOSED", { 1706 value: OriginalWebSocket.CLOSED, 1707 writable: false, 1708 }); 1709 } 1710 catch (e) { 1711 // å¦ææ æ³å®ä¹ï¼è·³è¿ 1712 } 1713 // å®å ¨å¤å¶å ¶ä»éæå±æ§ 1714 Object.getOwnPropertyNames(OriginalWebSocket).forEach((prop) => { 1715 if (prop === "prototype" || prop === "name" || prop === "length") 1716 return; 1717 if (prop === "CONNECTING" || 1718 prop === "OPEN" || 1719 prop === "CLOSING" || 1720 prop === "CLOSED") 1721 return; 1722 const desc = Object.getOwnPropertyDescriptor(OriginalWebSocket, prop); 1723 if (!desc) 1724 return; 1725 try { 1726 Object.defineProperty(MonitorWebSocket, prop, desc); 1727 } 1728 catch (e) { 1729 // å¿½ç¥æ æ³å®ä¹ç屿§ 1730 } 1731 }); 1732 window.WebSocket = MonitorWebSocket; 1733 OControl.log("WebSocket monitoring enabled"); 1734 } 1735 /** 1736 * è·å WebSocket å ³éç 对åºçææ¬æè¿° 1737 */ 1738 function getCloseReasonText(code) { 1739 const closeCodeMap = { 1740 1000: "Normal Closure", 1741 1001: "Going Away", 1742 1002: "Protocol Error", 1743 1003: "Unsupported Data", 1744 1004: "Reserved", 1745 1005: "No Status Received", 1746 1006: "Abnormal Closure", 1747 1007: "Invalid Frame Payload Data", 1748 1008: "Policy Violation", 1749 1009: "Message Too Big", 1750 1010: "Mandatory Extension", 1751 1011: "Internal Server Error", 1752 1015: "TLS Handshake", 1753 }; 1754 return closeCodeMap[code] || `Unknown Code: ${code}`; 1755 } 1756 /** 1757 * è·å WebSocket ç¶æå¯¹åºçææ¬æè¿° 1758 */ 1759 function getReadyStateText(readyState) { 1760 const stateMap = { 1761 0: "CONNECTING", 1762 1: "OPEN", 1763 2: "CLOSING", 1764 3: "CLOSED", 1765 }; 1766 return stateMap[readyState] || `Unknown State: ${readyState}`; 1767 } 1768 /** 1769 * æå¨ä¸æ¥ WebSocket éè¿äºä»¶ 1770 */ 1771 function reportWebSocketReconnect$1(url, reconnectCount, reconnectInterval) { 1772 const socketInfo = { 1773 url, 1774 protocol: "", 1775 readyState: WebSocket.CONNECTING, 1776 reconnectCount, 1777 reconnectInterval, 1778 }; 1779 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_RECONNECT, socketInfo); 1780 } 1781 /** 1782 * 䏿¥ WebSocket æ§è½æ°æ® 1783 */ 1784 function reportWebSocketPerformance$1() { 1785 for (const [ws, data] of socketConnections) { 1786 if (ws.readyState === WebSocket.OPEN) { 1787 const currentTime = Date.now(); 1788 const totalDuration = currentTime - data.connectTime; 1789 const socketInfo = { 1790 url: data.url, 1791 protocol: data.protocol, 1792 readyState: ws.readyState, 1793 bufferedAmount: ws.bufferedAmount, 1794 duration: totalDuration, 1795 messageCount: data.messageCount, 1796 sentBytes: data.sentBytes, 1797 receivedBytes: data.receivedBytes, 1798 reconnectCount: data.reconnectCount, 1799 latency: calculateLatency(data), 1800 }; 1801 report(exports.ReportTypeEnum.SOCKET, exports.ReportNameEnum.WS_PERFORMANCE, socketInfo); 1802 } 1803 } 1804 } 1805 /** 1806 * æ¸ ç WebSocket çæ§ 1807 */ 1808 function disableWebSocketMonitoring() { 1809 socketConnections.clear(); 1810 } 1811 /** 1812 * å¯å¨ WebSocket çæ§ 1813 */ 1814 function setupWebSocketMonitoring() { 1815 overrideWebSocket(); 1816 // 宿䏿¥æ§è½æ°æ®ï¼å¯éï¼ 1817 setInterval(() => { 1818 reportWebSocketPerformance$1(); 1819 }, 30000); // æ¯30ç§ä¸æ¥ä¸æ¬¡æ§è½æ°æ® 1820 } 1821 var socket = { 1822 setupWebSocketMonitoring, 1823 disableWebSocketMonitoring, 1824 overrideWebSocket, 1825 reportWebSocketReconnect: reportWebSocketReconnect$1, 1826 reportWebSocketPerformance: reportWebSocketPerformance$1, 1827 }; 1828 1829 const initData = { 1830 initialized: false, 1831 projectName: "default", 1832 postUrl: cfg.postUrl, // 䏿¥å°å 1833 enableConsoleMonitor: false, 1834 enableSocketMonitor: false, 1835 env: "", 1836 }; 1837 /** 1838 * åå§åçæ§ SDK 1839 * 1840 * è¯¥å½æ°ç¨äºåå§åçæ§ç³»ç»ï¼å æ¬è®¾ç½®é¡¹ç®åæ°ãç¨æ·ä¿¡æ¯ã䏿¥å°åãæ§å¶å°å WebSocket çæ§çã 1841 * ä¼èªå¨é²æ¢éå¤åå§åï¼å¹¶å¨é¡µé¢å è½½å®æåæ§è¡åå§åæµç¨ã 1842 * 1843 * @param initDataParam åå§ååæ°ï¼å¯å å«é¡¹ç®åã䏿¥å°åãç¨æ· IDã客æ·ç«¯ IDãæ¯å¦å¯ç¨æ§å¶å°/Socket çæ§ç 1844 * 1845 * - projectName: 项ç®åç§° 1846 * - postUrl: æ¥å¿ä¸æ¥å°å 1847 * - uid: ç¨æ· ID 1848 * - clientId: 客æ·ç«¯ ID 1849 * - enableConsoleMonitor: æ¯å¦å¯ç¨æ§å¶å°çæ§ 1850 * - enableSocketMonitor: æ¯å¦å¯ç¨ WebSocket çæ§ 1851 * 1852 * åå§åå å®¹å æ¬ï¼ 1853 * - è®¾ç½®å ¨å±åæ° 1854 * - å¯ç¨æ§å¶å°çæ§ï¼å¯éï¼ 1855 * - åå§å session 1856 * - å¯å¨é误ãAPIãWebSocket çæ§ 1857 * - 馿¬¡ä¸æ¥ PV 1858 * - ç»å®é¡µé¢äº¤äºäºä»¶ 1859 * 1860 * åªæå¨ document.readyState 为 complete æ¶æä¼æ§è¡åå§åï¼å¦åä¼çå¾ é¡µé¢å è½½å®æã 1861 */ 1862 function initMonitor(initDataParam) {
1863 function doInit() { 1864 // 鲿¢éå¤åå§å 1865 if (initData.initialized) 1866 return; 1867 initData.projectName = initDataParam.projectName || "default"; // 项ç®åç§° 1868 initData.postUrl = initDataParam.postUrl || cfg.postUrl; // 䏿¥å°å 1869 initData.uid = initDataParam.uid || getUserId(); // ç¨æ· ID 1870 initData.clientId = initDataParam.clientId || getClientCode(); // 客æ·ç«¯ ID 1871 initData.enableConsoleMonitor = initDataParam.enableConsoleMonitor || false; 1872 initData.enableSocketMonitor = initDataParam.enableSocketMonitor || false; 1873 initData.env = initDataParam.env || ""; 1874 // å¯ç¨ console çæ§ 1875 if (initData.enableConsoleMonitor) { 1876 overrideConsole(); 1877 } 1878 const OConsole = getOriginalConsole(); 1879 // åå§å session 1880 createOrUpdateSession(); 1881 errorMonitor.setupErrorListeners(); // éè¯¯çæ§å¼å¯ 1882 apiMonitor.setupListenerApi(); // apiçæ§ 1883 if (initData.enableSocketMonitor) { 1884 socket.setupWebSocketMonitoring(); // WebSocketçæ§ 1885 } 1886 report$1.initBeforeQueue(); 1887 page.pv(); // ç¬¬ä¸æ¬¡è¿æ¥ä¸æ¥ pv 1888 page.setupListenerPage(); // 页é¢äº¤äºçæ§ 1889 OConsole.info("Monitor SDK version is:", cfg.version); 1890 OConsole.info("Initializing monitor with project:", initDataParam.projectName); 1891 initData.initialized = true; 1892 } 1893 if (document.readyState === "loading") { 1894 // DOM è¿å¨å è½½ä¸,çå¾ DOMContentLoaded 1895 document.addEventListener("DOMContentLoaded", doInit, { once: true }); 1896 } 1897 else { 1898 // DOM å·²ç»å è½½å®æ(interactive æ complete),ç«å³åå§å 1899 doInit(); 1900 } 1901 } 1902 function getMonitorInitData() { 1903 return initData; 1904 } 1905 1906 /** 1907 * æå»ºçæ§ä¿¡æ¯ 1908 * @param type çæ§ç±»å 1909 * @param name çæ§åç§° 1910 * @param params çæ§åæ° 1911 * @param metadata çæ§å æ°æ® 1912 * @param immediately æ¯å¦ç«å³ä¸æ¥ 1913 */ 1914 function buildMintor(type, name, params = {}, metadata = {}, immediately = false) { 1915 var _a, _b; 1916 const initialMonitorData = getMonitorInitData(); 1917 const preMonitorInfo = { 1918 projectName: initialMonitorData.projectName || "", 1919 ct: Date.now(), 1920 timezone: (_b = (_a = Intl === null || Intl === void 0 ? void 0 : Intl.DateTimeFormat()) === null || _a === void 0 ? void 0 : _a.resolvedOptions()) === null || _b === void 0 ? void 0 : _b.timeZone, 1921 version: cfg.version, 1922 platform: getPlatform(), 1923 immediately, 1924 type, 1925 env: initialMonitorData.env || "", 1926 }; 1927 preMonitorInfo.session = createOrUpdateSession(); // æ´æ°æè å建 session 1928 preMonitorInfo.page = page.getPageInfo(); // è·åå½å页é¢ä¿¡æ¯ 1929 preMonitorInfo.device = getDeviceInfo(); // è·åå½å设å¤ä¿¡æ¯ 1930 if (!initialMonitorData.uid) { 1931 initialMonitorData.uid = getUserId(); 1932 } 1933 if (!initialMonitorData.clientId) { 1934 initialMonitorData.clientId = getClientCode(); 1935 } 1936 preMonitorInfo.user = { 1937 uid: initialMonitorData.uid || "", 1938 clientId: initialMonitorData.clientId || "", 1939 }; 1940 const baseEvent = { 1941 name: name, 1942 params, 1943 metadata, 1944 }; 1945 if (type === exports.ReportTypeEnum.EVENT) { 1946 preMonitorInfo.event = baseEvent; 1947 } 1948 if (type === exports.ReportTypeEnum.PERFORMANCE) { 1949 preMonitorInfo.performance = Object.assign(Object.assign({}, baseEvent), { params: params }); 1950 } 1951 if (type === exports.ReportTypeEnum.ERROR) { 1952 preMonitorInfo.error = Object.assign(Object.assign({}, baseEvent), { params: params }); 1953 } 1954 if (type === exports.ReportTypeEnum.API) { 1955 preMonitorInfo.api = Object.assign(Object.assign({}, baseEvent), { params: params }); 1956 } 1957 // æ·»å WebSocket æ¯æ 1958 if (type === exports.ReportTypeEnum.SOCKET) { 1959 preMonitorInfo.socket = Object.assign(Object.assign({}, baseEvent), { params: params }); 1960 } 1961 return preMonitorInfo; 1962 } 1963 1964 /** 1965 * ç§»é¤å¯¹è±¡ä¸çææä¿¡æ¯ï¼å¦ tokenãauthorizationãpasswordï¼ï¼å¹¶é¿å 循ç¯å¼ç¨ 1966 * @param data éè¦å¤ççæ°æ®å¯¹è±¡ 1967 * @returns å¤çåç对象 1968 */ 1969 function sensitive(data) { 1970 if (!data || typeof data !== "object") 1971 return data; 1972 const cache = typeof WeakMap !== "undefined" 1973 ? new WeakMap() 1974 : new Map(); 1975 function isSensitiveKey(lcKey) { 1976 // ç²¾åä¸å¸¸è§åä½å¹é ï¼é¿å è¿åº¦å¹é æ®éåæ®µï¼ 1977 if (lcKey === "authorization" || lcKey === "password" || lcKey === "token") 1978 return true; 1979 if (/access[_-]?token$/.test(lcKey)) 1980 return true; // access_token, access-token 1981 if (/^auth(?:orization|token)?$/.test(lcKey)) 1982 return true; // auth, authToken, authorization 1983 return false;
1984 } 1985 function walk(obj) { 1986 if (obj === null || typeof obj !== "object") 1987 return obj; 1988 // ç¹æ®ç±»åå¤ç 1989 if (obj instanceof Date) 1990 return obj.toISOString(); 1991 if (obj instanceof Error) 1992 return { name: obj.name, message: obj.message, stack: obj.stack }; 1993 if (cache.has(obj)) 1994 return cache.get(obj); 1995 // Map / Set å¤ç 1996 if (obj instanceof Map) { 1997 const o = {}; 1998 cache.set(obj, o); 1999 for (const [k, v] of obj.entries()) { 2000 o[k] = walk(v); 2001 } 2002 return o; 2003 } 2004 if (obj instanceof Set) { 2005 const arr = []; 2006 cache.set(obj, arr); 2007 for (const v of obj) 2008 arr.push(walk(v)); 2009 return arr; 2010 } 2011 const res = Array.isArray(obj) ? [] : {}; 2012 cache.set(obj, res); 2013 for (const k in obj) { 2014 if (!Object.prototype.hasOwnProperty.call(obj, k)) 2015 continue; 2016 const val = obj[k]; 2017 const lcKey = k.toLowerCase(); 2018 if (isSensitiveKey(lcKey)) { 2019 res[k] = "***"; 2020 continue; 2021 } 2022 if (lcKey === "data") { 2023 // ä» å½ data æ¯å¯¹è±¡æ¶æ stringifyï¼åç¬¦ä¸²ä¿æåæ · 2024 if (val && typeof val === "object") { 2025 try { 2026 // éå½å¤çåå stringifyï¼é¿å æªè±æåµå¥ 2027 res[k] = JSON.stringify(walk(val)); 2028 } 2029 catch (e) { 2030 res[k] = "[unserializable data]"; 2031 } 2032 } 2033 else { 2034 res[k] = val; 2035 } 2036 continue; 2037 } 2038 if (val && typeof val === "object") { 2039 res[k] = walk(val); 2040 } 2041 else { 2042 res[k] = val; 2043 } 2044 } 2045 return res; 2046 } 2047 return walk(data); 2048 } 2049 2050 const writeListConfig = { 2051 uidList: [], 2052 cidList: [], 2053 pathList: [], 2054 }; 2055 let intervalID = 0; 2056 let loading = false; 2057 const GAP_TIME = 60000; 2058 const DEBUG_INFO_URL = "https://json.static-global.com/public-json-config/web/acc/debugInfo.json"; 2059 /** 2060 * èªå¨åæ¥ç½åå 2061 * @returns 2062 */ 2063 const onSync = () => { 2064 if (intervalID) 2065 return; 2066 const OConsole = getOriginalConsole(); 2067 if (window.localStorage.getItem("__xt_write_list_config__")) { 2068 const localConfig = window.localStorage.getItem("__xt_write_list_config__"); 2069 if (localConfig) { 2070 Object.assign(writeListConfig, JSON.parse(localConfig)); 2071 } 2072 } 2073 const loadList = function () { 2074 const url = DEBUG_INFO_URL; 2075 if (loading) 2076 return; 2077 loading = true; 2078 fetch(url, { method: "GET" }) 2079 .then((response) => response.json()) 2080 .then((data) => { 2081 writeListConfig.uidList = Array.isArray(data.uidList) 2082 ? data.uidList 2083 : []; 2084 writeListConfig.cidList = Array.isArray(data.cidList) 2085 ? data.cidList 2086 : []; 2087 writeListConfig.pathList = Array.isArray(data.pathList) 2088 ? data.pathList 2089 : []; 2090 window.localStorage.setItem("__xt_write_list_config__", JSON.stringify(writeListConfig)); 2091 }) 2092 .catch((error) => { 2093 OConsole.error("Error loading list:", error); 2094 }) 2095 .finally(() => { 2096 loading = false; 2097 }); 2098 }; 2099 intervalID = window.setInterval(() => { 2100 loadList(); 2101 }, GAP_TIME); // æ¯60ç§åæ¥ä¸æ¬¡ 2102 loadList(); 2103 }; 2104 const closeSync = () => { 2105 if (intervalID) { 2106 clearInterval(intervalID); 2107 intervalID = 0; 2108 } 2109 }; 2110 const getWriteListConfig = () => { 2111 const clonedConfig = JSON.parse(JSON.stringify(writeListConfig)); 2112 return clonedConfig; 2113 }; 2114 var writeList = { 2115 onSync, 2116 closeSync, 2117 getWriteListConfig, 2118 DEBUG_INFO_URL, 2119 }; 2120 2121 const reportQueue = []; 2122 const postSize = 7; 2123 let scheduleId = null; 2124 const scheduleGap = 3000; 2125 // /** 䏿¥è°åº¦ */ 2126 // let scheduleFlush: Function = () => { 2127 // const monitorInitData = getMonitorInitData(); 2128 // const { initialized } = monitorInitData || {}; 2129 // if (!initialized) return; 2130 // const executeFlush = () => { 2131 // flush(); // æ§è¡åé 2132 // secheduleID = null; 2133 // // 妿éåè¿ææ°æ®ï¼ç»§ç»è°åº¦ 2134 // if (reportQueue.length > 0) scheduleFlush(); 2135 // }; 2136 // // ä½¿ç¨ requestIdleCallback è¿è¡è°åº¦ 2137 // const idleCallbackWay = () => { 2138 // if (secheduleID) window.cancelIdleCallback(secheduleID); 2139 // if (reportQueue.length === 0) return; 2140 // secheduleID = window.requestIdleCallback(executeFlush); 2141 // }; 2142 // // ä½¿ç¨ Promise è¿è¡è°åº¦ 2143 // const promiseWay = () => { 2144 // if (secheduleID) return; 2145 // secheduleID = 1; 2146 // Promise.resolve().then(executeFlush); 2147 // }; 2148 // scheduleFlush = 2149 // typeof window?.requestIdleCallback === "function" 2150 // ? idleCallbackWay 2151 // : promiseWay; 2152 // scheduleFlush(); 2153 // }; 2154 const scheduleFlush = () => { 2155 if (scheduleId) 2156 return; 2157 scheduleId = setInterval(() => { 2158 flush(); 2159 }, scheduleGap); 2160 }; 2161 /** 2162 * éè¯ä¸æ¥ 2163 * @param batch 2164 * @param attempt 2165 * @returns 2166 */ 2167 function retryReport(batch, attempt = 1) { 2168 /** åå§æ§å¶å° */ 2169 const OControl = getOriginalConsole(); 2170 const tryTime = 3; 2171 if (attempt > tryTime) { 2172 OControl.error("Report failed after maximum retries"); 2173 return; 2174 }
2175 // ææ¶ä¸éè¦å®éå 2176 // const delay = Math.pow(2, attempt - 1) * 1000; // ææ°éé¿ 2177 // setTimeout(() => {}, delay); 2178 const initialMonitorData = getMonitorInitData(); 2179 const url = initialMonitorData.postUrl || ""; 2180 // ä½¿ç¨ FormData æ URLSearchParams é¿å 颿£ 2181 const formData = new FormData(); 2182 formData.append("data", JSON.stringify(batch)); 2183 window === null || window === void 0 ? void 0 : window.fetch(url, { 2184 method: "POST", 2185 body: formData, // ä¸è®¾ç½® Content-Typeï¼è®©æµè§å¨èªå¨å¤ç 2186 keepalive: true, 2187 }).catch((error) => { 2188 OControl.error(`Report retry ${attempt} failed:`, error); 2189 retryReport(batch, attempt + 1); 2190 }); 2191 } 2192 function postQueue(batch) { 2193 /** åå§æ§å¶å° */ 2194 const OControl = getOriginalConsole(); 2195 const initialMonitorData = getMonitorInitData(); 2196 const url = initialMonitorData.postUrl || ""; 2197 if (!url || (batch === null || batch === void 0 ? void 0 : batch.length) === 0) { 2198 return; 2199 } 2200 for (const item of batch || []) { 2201 // è¡¥å ¨é¡¹ç®ä¿¡æ¯ 2202 item.projectName = initialMonitorData === null || initialMonitorData === void 0 ? void 0 : initialMonitorData.projectName; 2203 item.env = initialMonitorData === null || initialMonitorData === void 0 ? void 0 : initialMonitorData.env; 2204 } 2205 if (navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) { 2206 const blob = new Blob([JSON.stringify(batch)], { 2207 type: "text/plain", 2208 }); 2209 navigator.sendBeacon(url, blob); 2210 } 2211 else { 2212 // ä½¿ç¨ FormData æ URLSearchParams é¿å 颿£ 2213 const formData = new FormData(); 2214 formData.append("data", JSON.stringify(batch)); 2215 window === null || window === void 0 ? void 0 : window.fetch(url, { 2216 method: "POST", 2217 body: formData, // ä¸è®¾ç½® Content-Typeï¼è®©æµè§å¨èªå¨å¤ç 2218 keepalive: true, 2219 }).catch((error) => { 2220 OControl.error("Report failed:", error); 2221 // æ¹æ¡1 - 使ç¨éè¯æºå¶ 2222 retryReport(batch); 2223 // if (immediately) { 2224 // retryReport(batch); 2225 // } else { 2226 // // æ¹æ¡2 - éæ°å å ¥éåï¼åå¤éè¯ 2227 // reportQueue.unshift(...batch); 2228 // scheduleFlush(); 2229 // } 2230 }); 2231 } 2232 } 2233 /** 2234 * æ¨é䏿¥ 2235 * @param immediately 2236 * @returns 2237 */ 2238 function flush(immediately = false) { 2239 /** 没æåå§åä¸è½ä¸æ¥ */ 2240 const monitorInitData = getMonitorInitData(); 2241 const { initialized } = monitorInitData || {}; 2242 if (!initialized) 2243 return; 2244 /** åå§æ§å¶å° */ 2245 const OControl = getOriginalConsole(); 2246 if (immediately) { 2247 const needPostLength = reportQueue.length; 2248 OControl.debug("[Mint]", "ç«å³ä¸æ¥", needPostLength, "æ¡æ°æ®"); 2249 while (reportQueue.length > 0) { 2250 let batch = reportQueue.splice(0, postSize); 2251 postQueue(batch); 2252 } 2253 } 2254 else { 2255 let batch = reportQueue.splice(0, postSize); 2256 postQueue(batch); 2257 } 2258 } 2259 /** 2260 * 䏿¥çæ§ä¿¡æ¯ 2261 * @param type çæ§ç±»å 2262 * @param name çæ§åç§° 2263 * @param params çæ§åæ° 2264 * @param metadata çæ§å æ°æ® 2265 * @param immediately æ¯å¦ç«å³ä¸æ¥ 2266 */ 2267 function report(type = exports.ReportTypeEnum.EVENT, name, params, metadata, immediately = false) { 2268 var _a, _b; 2269 // å¤æç±»åï¼å¦æç±»åä¸å¯¹ä¸ä¸æ¥ 2270 if (!Object.values(exports.ReportTypeEnum).includes(type)) { 2271 console.warn(`[Mint] report type ${type} is not supported`); 2272 return; 2273 } 2274 /** 没æåå§åä¸è½ä¸æ¥ */ 2275 const monitorInitData = getMonitorInitData(); 2276 /** è¿æ»¤ä¸æ¥æ¥å£æ¬èº«çæ¥æº */ 2277 if (type === exports.ReportTypeEnum.API || type === exports.ReportTypeEnum.ERROR) { 2278 if ((params === null || params === void 0 ? void 0 : params.url) === monitorInitData.postUrl) { 2279 return; 2280 } 2281 if (params.url === writeList.DEBUG_INFO_URL) { 2282 return; 2283 } 2284 } 2285 // æ£æ¥ç½åå䏿¥ response 详æ 2286 if (name === exports.ReportNameEnum.XHR_DETAIL) { 2287 if (!params || !params.response) 2288 return; 2289 const { uid = 0, clientId = "" } = getMonitorInitData(); 2290 const { uidList, cidList, pathList } = writeList.getWriteListConfig(); 2291 const interDebugIds = [ 2292 7514700383137, 8244871495780, 7819888689620, 8402971001641, 8402981946048, 2293 ]; 2294 // åªè¦å¨ uidList æ cidList ç½ååï¼ç´æ¥å è®¸ä¸æ¥ 2295 if (uidList.includes(Number(uid)) || 2296 cidList.includes(clientId) || 2297 interDebugIds.includes(Number(uid))) ; 2298 else if (pathList.length > 0) { 2299 // ä¸å¨ç½ååï¼æ£æ¥è·¯å¾ç½åå 2300 const drp = (_b = (_a = params === null || params === void 0 ? void 0 : params.response) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.url; 2301 if (!drp) 2302 return; 2303 const matched = pathList.some((p) => drp.endsWith(p)); 2304 // console.log("matched:", pathList, "drp:", drp, "matched:", matched); 2305 if (!matched) 2306 return; 2307 // å è®¸ä¸æ¥ 2308 } 2309 else { 2310 // ä¸å¨ä»»ä½ç½åå䏿²¡æè·¯å¾ç½ååï¼ç´æ¥è·³è¿ 2311 return; 2312 } 2313 } 2314 // æå»ºçæ§ä¿¡æ¯ 2315 const preMonitorInfo = buildMintor(type, name, params, metadata, immediately); 2316 /** æ°æ®è±æ */ 2317 const monitorInfo = type !== exports.ReportTypeEnum.PERFORMANCE 2318 ? sensitive(preMonitorInfo) 2319 : preMonitorInfo; 2320 if (immediately) { 2321 // ç«å»ä¸æ¥ 2322 postQueue([monitorInfo]); 2323 } 2324 else { 2325 reportQueue.push(monitorInfo); 2326 scheduleFlush(); 2327 } 2328 } 2329 /** 2330 * å¨åå§å忣æ¥ä¸æ¥å表 2331 * ä¾å¦ web - vitals å¨åå§åä¹åå°±å¼å§ç§¯æä¸æ¥æ°æ®äºï¼æä»¥è¿ééè¦å¨åå§ååè¿è¡ä¸æ¬¡æ£æ¥ 2332 * */ 2333 function initBeforeQueue() { 2334 const monitorInitData = getMonitorInitData(); 2335 const { initialized } = monitorInitData || {}; 2336 if (!initialized) 2337 return; 2338 reportQueue === null || reportQueue === void 0 ? void 0 : reportQueue.forEach((item) => { 2339 // è¿è¡ä¸æ¥æ£æ¥ 2340 item.projectName = monitorInitData === null || monitorInitData === void 0 ? void 0 : monitorInitData.projectName; 2341 item.env = monitorInitData === null || monitorInitData === void 0 ? void 0 : monitorInitData.env; 2342 }); 2343 } 2344 /** ç«å»ä¸æ¥ */ 2345 function flushImmediateReports() { 2346 /** 没æåå§åä¸è½ä¸æ¥ */ 2347 const oControl = getOriginalConsole(); 2348 if (oControl) { 2349 oControl === null || oControl === void 0 ? void 0 : oControl.warn("[Mint] Immediate flush triggered"); 2350 } 2351 stopSchedule(); 2352 flush(true); 2353 } 2354 /** 忢䏿¥è°åº¦ */ 2355 function stopSchedule() { 2356 if (scheduleId) { 2357 clearInterval(scheduleId); 2358 } 2359 scheduleId = null; 2360 } 2361 var report$1 = { 2362 initBeforeQueue, 2363 }; 2364 2365 const reportWebSocketPerformance = socket.reportWebSocketPerformance; 2366 const reportWebSocketReconnect = socket.reportWebSocketReconnect;
2367 function reportEvent(name, prams = {}, metadata = {}, immediate = false) { 2368 report(exports.ReportTypeEnum.EVENT, name, prams, metadata, immediate); 2369 } 2370 // èªå¨åæ¥ç½ååé ç½® 2371 writeList.onSync(); 2372 2373 exports.initMonitor = initMonitor; 2374 exports.report = report; 2375 exports.reportEvent = reportEvent; 2376 exports.reportWebSocketPerformance = reportWebSocketPerformance; 2377 exports.reportWebSocketReconnect = reportWebSocketReconnect; 2378 2379 Object.defineProperty(exports, '__esModule', { value: true }); 2380 2381}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.