@be-link/cls-logger 1.0.1-beta.9 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -562,6 +562,19 @@ function getPagePath$1() {
562
562
  return '';
563
563
  }
564
564
  }
565
+ function getMpPagePath() {
566
+ try {
567
+ const pages = globalThis.getCurrentPages?.();
568
+ if (Array.isArray(pages) && pages.length > 0) {
569
+ const page = pages[pages.length - 1];
570
+ return page.route || page.__route__ || '';
571
+ }
572
+ return '';
573
+ }
574
+ catch {
575
+ return '';
576
+ }
577
+ }
565
578
  function normalizeErrorLike(err, maxTextLength) {
566
579
  if (err && typeof err === 'object') {
567
580
  const anyErr = err;
@@ -721,6 +734,7 @@ function installMiniProgramErrorMonitor(report, options) {
721
734
  return;
722
735
  const e = normalizeErrorLike(msg, options.maxTextLength);
723
736
  const payload = {
737
+ pagePath: getMpPagePath(),
724
738
  source: 'wx.onError',
725
739
  message: e.message,
726
740
  errorName: e.name,
@@ -747,6 +761,7 @@ function installMiniProgramErrorMonitor(report, options) {
747
761
  return;
748
762
  const e = normalizeErrorLike(res?.reason, options.maxTextLength);
749
763
  const payload = {
764
+ pagePath: getMpPagePath(),
750
765
  source: 'wx.onUnhandledRejection',
751
766
  message: e.message,
752
767
  errorName: e.name,
@@ -778,6 +793,7 @@ function installMiniProgramErrorMonitor(report, options) {
778
793
  if (sampleHit$1(options.sampleRate)) {
779
794
  const e = normalizeErrorLike(args?.[0], options.maxTextLength);
780
795
  const payload = {
796
+ pagePath: getMpPagePath(),
781
797
  source: 'App.onError',
782
798
  message: e.message,
783
799
  errorName: e.name,
@@ -801,6 +817,7 @@ function installMiniProgramErrorMonitor(report, options) {
801
817
  const reason = args?.[0]?.reason ?? args?.[0];
802
818
  const e = normalizeErrorLike(reason, options.maxTextLength);
803
819
  const payload = {
820
+ pagePath: getMpPagePath(),
804
821
  source: 'App.onUnhandledRejection',
805
822
  message: e.message,
806
823
  errorName: e.name,
@@ -1108,18 +1125,28 @@ function installMiniProgramPerformanceMonitor(report, options) {
1108
1125
  continue;
1109
1126
  // Page Render: firstRender
1110
1127
  if (entry.entryType === 'render' && entry.name === 'firstRender') {
1128
+ const duration = typeof entry.duration === 'number'
1129
+ ? entry.duration
1130
+ : typeof entry.startTime === 'number' && typeof entry.endTime === 'number'
1131
+ ? entry.endTime - entry.startTime
1132
+ : 0;
1111
1133
  report(options.reportType, {
1112
1134
  metric: 'page-render',
1113
- duration: entry.duration,
1135
+ duration,
1114
1136
  pagePath: entry.path || '',
1115
1137
  unit: 'ms',
1116
1138
  });
1117
1139
  }
1118
1140
  // Route Switch: route
1119
1141
  else if (entry.entryType === 'navigation' && entry.name === 'route') {
1142
+ const duration = typeof entry.duration === 'number'
1143
+ ? entry.duration
1144
+ : typeof entry.startTime === 'number' && typeof entry.endTime === 'number'
1145
+ ? entry.endTime - entry.startTime
1146
+ : 0;
1120
1147
  report(options.reportType, {
1121
1148
  metric: 'route',
1122
- duration: entry.duration,
1149
+ duration,
1123
1150
  pagePath: entry.path || '',
1124
1151
  unit: 'ms',
1125
1152
  });
@@ -1463,7 +1490,7 @@ function installBehaviorMonitor(report, envType, options = {}) {
1463
1490
  const tag = (el.tagName || '').toLowerCase();
1464
1491
  const trackId = getAttr(el, clickTrackIdAttr);
1465
1492
  // 过滤无效点击:白名单 tag + 没有 trackId
1466
- if (clickWhiteList.includes(tag) && !trackId)
1493
+ if (clickWhiteList.includes(tag) || !trackId)
1467
1494
  return;
1468
1495
  void uvStatePromise.then(({ uvId, meta }) => {
1469
1496
  if (destroyed)
@@ -1504,8 +1531,12 @@ function installBehaviorMonitor(report, envType, options = {}) {
1504
1531
  g.Page = function patchedPage(conf) {
1505
1532
  const originalOnShow = conf?.onShow;
1506
1533
  conf.onShow = function (...args) {
1507
- if (pvEnabled)
1508
- reportPv(getPagePath());
1534
+ if (pvEnabled) {
1535
+ const pagePath = getPagePath();
1536
+ if (pagePath?.length > 0) {
1537
+ reportPv(pagePath);
1538
+ }
1539
+ }
1509
1540
  return typeof originalOnShow === 'function' ? originalOnShow.apply(this, args) : undefined;
1510
1541
  };
1511
1542
  // 点击:wrap 页面 methods(bindtap 等会调用到这里的 handler)
@@ -1859,6 +1890,7 @@ class ClsLoggerCore {
1859
1890
  this.endpoint = 'ap-shanghai.cls.tencentcs.com';
1860
1891
  this.retryTimes = 10;
1861
1892
  this.source = '127.0.0.1';
1893
+ this.enabled = true;
1862
1894
  this.projectId = '';
1863
1895
  this.projectName = '';
1864
1896
  this.appId = '';
@@ -1889,9 +1921,14 @@ class ClsLoggerCore {
1889
1921
  * 子类可按需重写(默认检测 wx)
1890
1922
  */
1891
1923
  detectEnvType() {
1892
- const wxAny = globalThis.wx;
1893
- if (wxAny && typeof wxAny.getSystemInfoSync === 'function')
1924
+ const g = globalThis;
1925
+ // 微信、支付宝、字节跳动、UniApp 等小程序环境通常都有特定全局变量
1926
+ if ((g.wx && typeof g.wx.getSystemInfoSync === 'function') ||
1927
+ (g.my && typeof g.my.getSystemInfoSync === 'function') ||
1928
+ (g.tt && typeof g.tt.getSystemInfoSync === 'function') ||
1929
+ (g.uni && typeof g.uni.getSystemInfoSync === 'function')) {
1894
1930
  return 'miniprogram';
1931
+ }
1895
1932
  return 'browser';
1896
1933
  }
1897
1934
  init(options) {
@@ -1929,6 +1966,7 @@ class ClsLoggerCore {
1929
1966
  this.appId = options.appId ?? this.appId;
1930
1967
  this.appVersion = options.appVersion ?? this.appVersion;
1931
1968
  this.envType = nextEnvType;
1969
+ this.enabled = options.enabled ?? true;
1932
1970
  // 可选:外部注入 SDK(优先级:sdkLoader > sdk)
1933
1971
  this.sdkLoaderOverride = options.sdkLoader ?? this.sdkLoaderOverride;
1934
1972
  this.sdkOverride = options.sdk ?? this.sdkOverride;
@@ -1945,15 +1983,17 @@ class ClsLoggerCore {
1945
1983
  void this.getInstance().catch(() => {
1946
1984
  // ignore
1947
1985
  });
1948
- // 启动时尝试发送失败缓存
1949
- this.flushFailed();
1950
- // 初始化后立即启动请求监听
1951
- this.startRequestMonitor(options.requestMonitor);
1952
- // 初始化后立即启动错误监控/性能监控
1953
- this.startErrorMonitor(options.errorMonitor);
1954
- this.startPerformanceMonitor(options.performanceMonitor);
1955
- // 初始化后立即启动行为埋点(PV/UV/点击)
1956
- this.startBehaviorMonitor(options.behaviorMonitor);
1986
+ if (this.enabled) {
1987
+ // 启动时尝试发送失败缓存
1988
+ this.flushFailed();
1989
+ // 初始化后立即启动请求监听
1990
+ this.startRequestMonitor(options.requestMonitor);
1991
+ // 初始化后立即启动错误监控/性能监控
1992
+ this.startErrorMonitor(options.errorMonitor);
1993
+ this.startPerformanceMonitor(options.performanceMonitor);
1994
+ // 初始化后立即启动行为埋点(PV/UV/点击)
1995
+ this.startBehaviorMonitor(options.behaviorMonitor);
1996
+ }
1957
1997
  }
1958
1998
  getBaseFields() {
1959
1999
  let auto = undefined;
@@ -2078,6 +2118,8 @@ class ClsLoggerCore {
2078
2118
  * - 最终会把 fields 展开成 CLS 的 content(key/value 都会转成 string)
2079
2119
  */
2080
2120
  put(fields, options = {}) {
2121
+ if (!this.enabled)
2122
+ return;
2081
2123
  if (!fields)
2082
2124
  return;
2083
2125
  if (!this.topicId) {
@@ -2136,6 +2178,8 @@ class ClsLoggerCore {
2136
2178
  * - 埋点入参必须是一维(扁平)Object,非原始值会被 stringify
2137
2179
  */
2138
2180
  enqueue(fields, options = {}) {
2181
+ if (!this.enabled)
2182
+ return;
2139
2183
  if (!fields)
2140
2184
  return;
2141
2185
  const time = Date.now();
@@ -2174,6 +2218,8 @@ class ClsLoggerCore {
2174
2218
  * 批量上报(每条 item.data 展开为 log content)
2175
2219
  */
2176
2220
  putBatch(queue) {
2221
+ if (!this.enabled)
2222
+ return;
2177
2223
  if (!queue || queue.length === 0)
2178
2224
  return;
2179
2225
  if (!this.topicId) {
@@ -2217,6 +2263,8 @@ class ClsLoggerCore {
2217
2263
  * 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
2218
2264
  */
2219
2265
  report(log) {
2266
+ if (!this.enabled)
2267
+ return;
2220
2268
  if (!log?.type)
2221
2269
  return;
2222
2270
  if (!this.topicId) {
@@ -2264,15 +2312,57 @@ class ClsLoggerCore {
2264
2312
  return nowTs + this.batchIntervalMs;
2265
2313
  }
2266
2314
  info(message, data = {}) {
2267
- const payload = normalizeFlatFields({ message, ...data }, 'info');
2315
+ let msg = '';
2316
+ let extra = {};
2317
+ if (message instanceof Error) {
2318
+ msg = message.message;
2319
+ extra = {
2320
+ stack: message.stack,
2321
+ name: message.name,
2322
+ ...data,
2323
+ };
2324
+ }
2325
+ else {
2326
+ msg = String(message);
2327
+ extra = data;
2328
+ }
2329
+ const payload = normalizeFlatFields({ message: msg, ...extra }, 'info');
2268
2330
  this.report({ type: 'info', data: payload, timestamp: Date.now() });
2269
2331
  }
2270
2332
  warn(message, data = {}) {
2271
- const payload = normalizeFlatFields({ message, ...data }, 'warn');
2333
+ let msg = '';
2334
+ let extra = {};
2335
+ if (message instanceof Error) {
2336
+ msg = message.message;
2337
+ extra = {
2338
+ stack: message.stack,
2339
+ name: message.name,
2340
+ ...data,
2341
+ };
2342
+ }
2343
+ else {
2344
+ msg = String(message);
2345
+ extra = data;
2346
+ }
2347
+ const payload = normalizeFlatFields({ message: msg, ...extra }, 'warn');
2272
2348
  this.report({ type: 'warn', data: payload, timestamp: Date.now() });
2273
2349
  }
2274
2350
  error(message, data = {}) {
2275
- const payload = normalizeFlatFields({ message, ...data }, 'error');
2351
+ let msg = '';
2352
+ let extra = {};
2353
+ if (message instanceof Error) {
2354
+ msg = message.message;
2355
+ extra = {
2356
+ stack: message.stack,
2357
+ name: message.name,
2358
+ ...data,
2359
+ };
2360
+ }
2361
+ else {
2362
+ msg = String(message);
2363
+ extra = data;
2364
+ }
2365
+ const payload = normalizeFlatFields({ message: msg, ...extra }, 'error');
2276
2366
  this.report({ type: 'error', data: payload, timestamp: Date.now() });
2277
2367
  }
2278
2368
  track(trackType, data = {}) {
@@ -2379,6 +2469,8 @@ class ClsLoggerCore {
2379
2469
  writeStringStorage(this.failedCacheKey, JSON.stringify(next));
2380
2470
  }
2381
2471
  flushFailed() {
2472
+ if (!this.enabled)
2473
+ return;
2382
2474
  const raw = readStringStorage(this.failedCacheKey);
2383
2475
  if (!raw)
2384
2476
  return;
@@ -2494,38 +2586,78 @@ class ClsLogger extends ClsLoggerCore {
2494
2586
  }
2495
2587
  }
2496
2588
  const isMini = this.envType === 'miniprogram';
2497
- // 静态字面量,方便打包器识别(但在此兼容入口里,仍然可能被一起分析)
2498
- const WEB_SDK = 'tencentcloud-cls-sdk-js-web';
2499
- const MINI_SDK = 'tencentcloud-cls-sdk-js-mini';
2500
- // UMD(浏览器脚本)优先读全局变量
2501
- if (!isMini) {
2589
+ // 3) 尝试 require / 全局变量
2590
+ // Mini Program: 尝试直接 require
2591
+ if (isMini) {
2592
+ // 显式使用字面量 require,帮助打包工具识别依赖(尤其是 CJS 构建模式下)
2593
+ try {
2594
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
2595
+ const req = typeof require === 'function' ? require('tencentcloud-cls-sdk-js-mini') : null;
2596
+ const reqSdk = normalizeSdk(req);
2597
+ if (reqSdk) {
2598
+ this.sdk = reqSdk;
2599
+ return reqSdk;
2600
+ }
2601
+ }
2602
+ catch {
2603
+ // ignore
2604
+ }
2605
+ // 尝试使用 tryRequire(作为补充)
2606
+ const reqMod = tryRequire('tencentcloud-cls-sdk-js-mini');
2607
+ const reqSdk = normalizeSdk(reqMod);
2608
+ if (reqSdk) {
2609
+ this.sdk = reqSdk;
2610
+ return reqSdk;
2611
+ }
2612
+ }
2613
+ else {
2614
+ // Web: 优先读全局变量 (UMD)
2502
2615
  const g = readGlobal('tencentcloudClsSdkJsWeb');
2503
2616
  const sdk = normalizeSdk(g);
2504
2617
  if (sdk) {
2505
2618
  this.sdk = sdk;
2506
2619
  return sdk;
2507
2620
  }
2621
+ // Web: 尝试 require
2622
+ const reqMod = tryRequire('tencentcloud-cls-sdk-js-web');
2623
+ const reqSdk = normalizeSdk(reqMod);
2624
+ if (reqSdk) {
2625
+ this.sdk = reqSdk;
2626
+ return reqSdk;
2627
+ }
2628
+ }
2629
+ // 4) 动态 import
2630
+ // 使用字符串字面量,确保 Bundler 能正确识别并进行 Code Splitting
2631
+ if (isMini) {
2632
+ this.sdkPromise = import('tencentcloud-cls-sdk-js-mini')
2633
+ .then((m) => {
2634
+ const sdk = normalizeSdk(m);
2635
+ if (!sdk)
2636
+ throw new Error(`ClsLogger.loadSdk: invalid sdk module for mini`);
2637
+ this.sdk = sdk;
2638
+ return sdk;
2639
+ })
2640
+ .catch((err) => {
2641
+ this.sdkPromise = null;
2642
+ console.error('[ClsLogger] Failed to load mini sdk:', err);
2643
+ throw err;
2644
+ });
2645
+ }
2646
+ else {
2647
+ this.sdkPromise = import('tencentcloud-cls-sdk-js-web')
2648
+ .then((m) => {
2649
+ const sdk = normalizeSdk(m);
2650
+ if (!sdk)
2651
+ throw new Error(`ClsLogger.loadSdk: invalid sdk module for web`);
2652
+ this.sdk = sdk;
2653
+ return sdk;
2654
+ })
2655
+ .catch((err) => {
2656
+ this.sdkPromise = null;
2657
+ console.error('[ClsLogger] Failed to load web sdk:', err);
2658
+ throw err;
2659
+ });
2508
2660
  }
2509
- // 尽量同步 require
2510
- const reqMod = tryRequire(isMini ? MINI_SDK : WEB_SDK);
2511
- const reqSdk = normalizeSdk(reqMod);
2512
- if (reqSdk) {
2513
- this.sdk = reqSdk;
2514
- return reqSdk;
2515
- }
2516
- // 动态 import
2517
- this.sdkPromise = (isMini ? import(MINI_SDK) : import(WEB_SDK))
2518
- .then((m) => {
2519
- const sdk = normalizeSdk(m);
2520
- if (!sdk)
2521
- throw new Error(`ClsLogger.loadSdk: invalid sdk module for ${isMini ? MINI_SDK : WEB_SDK}`);
2522
- this.sdk = sdk;
2523
- return sdk;
2524
- })
2525
- .catch((err) => {
2526
- this.sdkPromise = null;
2527
- throw err;
2528
- });
2529
2661
  return this.sdkPromise;
2530
2662
  }
2531
2663
  }