@be-link/cls-logger 1.0.1-beta.8 → 1.0.3
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/README.md +63 -29
- package/dist/ClsLogger.d.ts.map +1 -1
- package/dist/ClsLoggerCore.d.ts +3 -3
- package/dist/ClsLoggerCore.d.ts.map +1 -1
- package/dist/behaviorMonitor.d.ts.map +1 -1
- package/dist/errorMonitor.d.ts.map +1 -1
- package/dist/index.esm.js +192 -156
- package/dist/index.js +192 -156
- package/dist/index.umd.js +192 -156
- package/dist/mini.esm.js +127 -131
- package/dist/mini.js +127 -131
- package/dist/performanceMonitor.d.ts.map +1 -1
- package/dist/web.esm.js +127 -131
- package/dist/web.js +127 -131
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -564,6 +564,19 @@
|
|
|
564
564
|
return '';
|
|
565
565
|
}
|
|
566
566
|
}
|
|
567
|
+
function getMpPagePath() {
|
|
568
|
+
try {
|
|
569
|
+
const pages = globalThis.getCurrentPages?.();
|
|
570
|
+
if (Array.isArray(pages) && pages.length > 0) {
|
|
571
|
+
const page = pages[pages.length - 1];
|
|
572
|
+
return page.route || page.__route__ || '';
|
|
573
|
+
}
|
|
574
|
+
return '';
|
|
575
|
+
}
|
|
576
|
+
catch {
|
|
577
|
+
return '';
|
|
578
|
+
}
|
|
579
|
+
}
|
|
567
580
|
function normalizeErrorLike(err, maxTextLength) {
|
|
568
581
|
if (err && typeof err === 'object') {
|
|
569
582
|
const anyErr = err;
|
|
@@ -723,6 +736,7 @@
|
|
|
723
736
|
return;
|
|
724
737
|
const e = normalizeErrorLike(msg, options.maxTextLength);
|
|
725
738
|
const payload = {
|
|
739
|
+
pagePath: getMpPagePath(),
|
|
726
740
|
source: 'wx.onError',
|
|
727
741
|
message: e.message,
|
|
728
742
|
errorName: e.name,
|
|
@@ -749,6 +763,7 @@
|
|
|
749
763
|
return;
|
|
750
764
|
const e = normalizeErrorLike(res?.reason, options.maxTextLength);
|
|
751
765
|
const payload = {
|
|
766
|
+
pagePath: getMpPagePath(),
|
|
752
767
|
source: 'wx.onUnhandledRejection',
|
|
753
768
|
message: e.message,
|
|
754
769
|
errorName: e.name,
|
|
@@ -780,6 +795,7 @@
|
|
|
780
795
|
if (sampleHit$1(options.sampleRate)) {
|
|
781
796
|
const e = normalizeErrorLike(args?.[0], options.maxTextLength);
|
|
782
797
|
const payload = {
|
|
798
|
+
pagePath: getMpPagePath(),
|
|
783
799
|
source: 'App.onError',
|
|
784
800
|
message: e.message,
|
|
785
801
|
errorName: e.name,
|
|
@@ -803,6 +819,7 @@
|
|
|
803
819
|
const reason = args?.[0]?.reason ?? args?.[0];
|
|
804
820
|
const e = normalizeErrorLike(reason, options.maxTextLength);
|
|
805
821
|
const payload = {
|
|
822
|
+
pagePath: getMpPagePath(),
|
|
806
823
|
source: 'App.onUnhandledRejection',
|
|
807
824
|
message: e.message,
|
|
808
825
|
errorName: e.name,
|
|
@@ -1090,140 +1107,68 @@
|
|
|
1090
1107
|
}
|
|
1091
1108
|
}
|
|
1092
1109
|
}
|
|
1093
|
-
function wrapMiniProgramRouteApi(report, reportType, apiName, options) {
|
|
1094
|
-
const wxAny = globalThis.wx;
|
|
1095
|
-
if (!wxAny || typeof wxAny[apiName] !== 'function')
|
|
1096
|
-
return;
|
|
1097
|
-
const flagKey = `__beLinkClsLoggerMpRouteWrapped__${apiName}`;
|
|
1098
|
-
if (wxAny[flagKey])
|
|
1099
|
-
return;
|
|
1100
|
-
wxAny[flagKey] = true;
|
|
1101
|
-
const raw = wxAny[apiName].bind(wxAny);
|
|
1102
|
-
wxAny[apiName] = (opts) => {
|
|
1103
|
-
const start = Date.now();
|
|
1104
|
-
const url = opts?.url ? String(opts.url) : '';
|
|
1105
|
-
const wrapCb = (cb, success) => {
|
|
1106
|
-
return (...args) => {
|
|
1107
|
-
try {
|
|
1108
|
-
if (sampleHit(options.sampleRate)) {
|
|
1109
|
-
report(reportType, {
|
|
1110
|
-
metric: 'route',
|
|
1111
|
-
api: apiName,
|
|
1112
|
-
url,
|
|
1113
|
-
duration: Date.now() - start,
|
|
1114
|
-
success: success ? 1 : 0,
|
|
1115
|
-
error: success ? '' : truncate$1(stringifyLogValue(args?.[0]), options.maxTextLength),
|
|
1116
|
-
unit: 'ms',
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
catch {
|
|
1121
|
-
// ignore
|
|
1122
|
-
}
|
|
1123
|
-
if (typeof cb === 'function')
|
|
1124
|
-
return cb(...args);
|
|
1125
|
-
return undefined;
|
|
1126
|
-
};
|
|
1127
|
-
};
|
|
1128
|
-
const next = { ...(opts ?? {}) };
|
|
1129
|
-
next.success = wrapCb(next.success, true);
|
|
1130
|
-
next.fail = wrapCb(next.fail, false);
|
|
1131
|
-
return raw(next);
|
|
1132
|
-
};
|
|
1133
|
-
}
|
|
1134
|
-
function installMiniProgramPageRenderMonitor(report, reportType, options) {
|
|
1135
|
-
const g = globalThis;
|
|
1136
|
-
if (typeof g.Page !== 'function')
|
|
1137
|
-
return;
|
|
1138
|
-
if (g.__beLinkClsLoggerPageWrapped__)
|
|
1139
|
-
return;
|
|
1140
|
-
g.__beLinkClsLoggerPageWrapped__ = true;
|
|
1141
|
-
const rawPage = g.Page;
|
|
1142
|
-
g.Page = (pageOptions) => {
|
|
1143
|
-
const next = { ...(pageOptions ?? {}) };
|
|
1144
|
-
const rawOnLoad = next.onLoad;
|
|
1145
|
-
const rawOnReady = next.onReady;
|
|
1146
|
-
next.onLoad = function (...args) {
|
|
1147
|
-
try {
|
|
1148
|
-
this.__beLinkClsLoggerPageLoadTs__ = Date.now();
|
|
1149
|
-
}
|
|
1150
|
-
catch {
|
|
1151
|
-
// ignore
|
|
1152
|
-
}
|
|
1153
|
-
if (typeof rawOnLoad === 'function')
|
|
1154
|
-
return rawOnLoad.apply(this, args);
|
|
1155
|
-
return undefined;
|
|
1156
|
-
};
|
|
1157
|
-
next.onReady = function (...args) {
|
|
1158
|
-
try {
|
|
1159
|
-
const start = this.__beLinkClsLoggerPageLoadTs__;
|
|
1160
|
-
if (typeof start === 'number' && sampleHit(options.sampleRate)) {
|
|
1161
|
-
report(reportType, {
|
|
1162
|
-
metric: 'page-render',
|
|
1163
|
-
route: this?.route ? String(this.route) : '',
|
|
1164
|
-
duration: Date.now() - start,
|
|
1165
|
-
unit: 'ms',
|
|
1166
|
-
});
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
catch {
|
|
1170
|
-
// ignore
|
|
1171
|
-
}
|
|
1172
|
-
if (typeof rawOnReady === 'function')
|
|
1173
|
-
return rawOnReady.apply(this, args);
|
|
1174
|
-
return undefined;
|
|
1175
|
-
};
|
|
1176
|
-
return rawPage(next);
|
|
1177
|
-
};
|
|
1178
|
-
}
|
|
1179
1110
|
function installMiniProgramPerformanceMonitor(report, options) {
|
|
1180
1111
|
const g = globalThis;
|
|
1112
|
+
const ctx = g.wx || g.Taro;
|
|
1113
|
+
if (!ctx || typeof ctx.getPerformance !== 'function')
|
|
1114
|
+
return;
|
|
1181
1115
|
if (g.__beLinkClsLoggerMpPerfInstalled__)
|
|
1182
1116
|
return;
|
|
1183
1117
|
g.__beLinkClsLoggerMpPerfInstalled__ = true;
|
|
1184
|
-
// 路由切换耗时(用 API 回调近似)
|
|
1185
|
-
for (const apiName of ['navigateTo', 'redirectTo', 'switchTab', 'reLaunch']) {
|
|
1186
|
-
try {
|
|
1187
|
-
wrapMiniProgramRouteApi(report, options.reportType, apiName, options);
|
|
1188
|
-
}
|
|
1189
|
-
catch {
|
|
1190
|
-
// ignore
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
// 页面渲染耗时(onLoad -> onReady)
|
|
1194
1118
|
try {
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
const entries = typeof perf.getEntries === 'function'
|
|
1212
|
-
? perf.getEntries()
|
|
1213
|
-
: typeof perf.getEntriesByType === 'function'
|
|
1214
|
-
? perf.getEntriesByType('navigation')
|
|
1215
|
-
: [];
|
|
1119
|
+
const perf = ctx.getPerformance();
|
|
1120
|
+
if (!perf || typeof perf.createObserver !== 'function')
|
|
1121
|
+
return;
|
|
1122
|
+
const observer = perf.createObserver((entryList) => {
|
|
1123
|
+
try {
|
|
1124
|
+
const entries = entryList.getEntries();
|
|
1125
|
+
for (const entry of entries) {
|
|
1126
|
+
if (!sampleHit(options.sampleRate))
|
|
1127
|
+
continue;
|
|
1128
|
+
// Page Render: firstRender
|
|
1129
|
+
if (entry.entryType === 'render' && entry.name === 'firstRender') {
|
|
1130
|
+
const duration = typeof entry.duration === 'number'
|
|
1131
|
+
? entry.duration
|
|
1132
|
+
: typeof entry.startTime === 'number' && typeof entry.endTime === 'number'
|
|
1133
|
+
? entry.endTime - entry.startTime
|
|
1134
|
+
: 0;
|
|
1216
1135
|
report(options.reportType, {
|
|
1217
|
-
metric: '
|
|
1218
|
-
|
|
1136
|
+
metric: 'page-render',
|
|
1137
|
+
duration,
|
|
1138
|
+
pagePath: entry.path || '',
|
|
1139
|
+
unit: 'ms',
|
|
1219
1140
|
});
|
|
1220
1141
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1142
|
+
// Route Switch: route
|
|
1143
|
+
else if (entry.entryType === 'navigation' && entry.name === 'route') {
|
|
1144
|
+
const duration = typeof entry.duration === 'number'
|
|
1145
|
+
? entry.duration
|
|
1146
|
+
: typeof entry.startTime === 'number' && typeof entry.endTime === 'number'
|
|
1147
|
+
? entry.endTime - entry.startTime
|
|
1148
|
+
: 0;
|
|
1149
|
+
report(options.reportType, {
|
|
1150
|
+
metric: 'route',
|
|
1151
|
+
duration,
|
|
1152
|
+
pagePath: entry.path || '',
|
|
1153
|
+
unit: 'ms',
|
|
1154
|
+
});
|
|
1223
1155
|
}
|
|
1224
|
-
|
|
1156
|
+
// App Launch: appLaunch (Cold)
|
|
1157
|
+
else if (entry.entryType === 'navigation' && entry.name === 'appLaunch') {
|
|
1158
|
+
report(options.reportType, {
|
|
1159
|
+
metric: 'app-launch',
|
|
1160
|
+
duration: entry.duration,
|
|
1161
|
+
launchType: 'cold',
|
|
1162
|
+
unit: 'ms',
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1225
1166
|
}
|
|
1226
|
-
|
|
1167
|
+
catch {
|
|
1168
|
+
// ignore
|
|
1169
|
+
}
|
|
1170
|
+
});
|
|
1171
|
+
observer.observe({ entryTypes: ['navigation', 'render'] });
|
|
1227
1172
|
}
|
|
1228
1173
|
catch {
|
|
1229
1174
|
// ignore
|
|
@@ -1547,7 +1492,7 @@
|
|
|
1547
1492
|
const tag = (el.tagName || '').toLowerCase();
|
|
1548
1493
|
const trackId = getAttr(el, clickTrackIdAttr);
|
|
1549
1494
|
// 过滤无效点击:白名单 tag + 没有 trackId
|
|
1550
|
-
if (clickWhiteList.includes(tag)
|
|
1495
|
+
if (clickWhiteList.includes(tag) || !trackId)
|
|
1551
1496
|
return;
|
|
1552
1497
|
void uvStatePromise.then(({ uvId, meta }) => {
|
|
1553
1498
|
if (destroyed)
|
|
@@ -1588,8 +1533,12 @@
|
|
|
1588
1533
|
g.Page = function patchedPage(conf) {
|
|
1589
1534
|
const originalOnShow = conf?.onShow;
|
|
1590
1535
|
conf.onShow = function (...args) {
|
|
1591
|
-
if (pvEnabled)
|
|
1592
|
-
|
|
1536
|
+
if (pvEnabled) {
|
|
1537
|
+
const pagePath = getPagePath();
|
|
1538
|
+
if (pagePath?.length > 0) {
|
|
1539
|
+
reportPv(pagePath);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1593
1542
|
return typeof originalOnShow === 'function' ? originalOnShow.apply(this, args) : undefined;
|
|
1594
1543
|
};
|
|
1595
1544
|
// 点击:wrap 页面 methods(bindtap 等会调用到这里的 handler)
|
|
@@ -1973,9 +1922,14 @@
|
|
|
1973
1922
|
* 子类可按需重写(默认检测 wx)
|
|
1974
1923
|
*/
|
|
1975
1924
|
detectEnvType() {
|
|
1976
|
-
const
|
|
1977
|
-
|
|
1925
|
+
const g = globalThis;
|
|
1926
|
+
// 微信、支付宝、字节跳动、UniApp 等小程序环境通常都有特定全局变量
|
|
1927
|
+
if ((g.wx && typeof g.wx.getSystemInfoSync === 'function') ||
|
|
1928
|
+
(g.my && typeof g.my.getSystemInfoSync === 'function') ||
|
|
1929
|
+
(g.tt && typeof g.tt.getSystemInfoSync === 'function') ||
|
|
1930
|
+
(g.uni && typeof g.uni.getSystemInfoSync === 'function')) {
|
|
1978
1931
|
return 'miniprogram';
|
|
1932
|
+
}
|
|
1979
1933
|
return 'browser';
|
|
1980
1934
|
}
|
|
1981
1935
|
init(options) {
|
|
@@ -2348,15 +2302,57 @@
|
|
|
2348
2302
|
return nowTs + this.batchIntervalMs;
|
|
2349
2303
|
}
|
|
2350
2304
|
info(message, data = {}) {
|
|
2351
|
-
|
|
2305
|
+
let msg = '';
|
|
2306
|
+
let extra = {};
|
|
2307
|
+
if (message instanceof Error) {
|
|
2308
|
+
msg = message.message;
|
|
2309
|
+
extra = {
|
|
2310
|
+
stack: message.stack,
|
|
2311
|
+
name: message.name,
|
|
2312
|
+
...data,
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
else {
|
|
2316
|
+
msg = String(message);
|
|
2317
|
+
extra = data;
|
|
2318
|
+
}
|
|
2319
|
+
const payload = normalizeFlatFields({ message: msg, ...extra }, 'info');
|
|
2352
2320
|
this.report({ type: 'info', data: payload, timestamp: Date.now() });
|
|
2353
2321
|
}
|
|
2354
2322
|
warn(message, data = {}) {
|
|
2355
|
-
|
|
2323
|
+
let msg = '';
|
|
2324
|
+
let extra = {};
|
|
2325
|
+
if (message instanceof Error) {
|
|
2326
|
+
msg = message.message;
|
|
2327
|
+
extra = {
|
|
2328
|
+
stack: message.stack,
|
|
2329
|
+
name: message.name,
|
|
2330
|
+
...data,
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
else {
|
|
2334
|
+
msg = String(message);
|
|
2335
|
+
extra = data;
|
|
2336
|
+
}
|
|
2337
|
+
const payload = normalizeFlatFields({ message: msg, ...extra }, 'warn');
|
|
2356
2338
|
this.report({ type: 'warn', data: payload, timestamp: Date.now() });
|
|
2357
2339
|
}
|
|
2358
2340
|
error(message, data = {}) {
|
|
2359
|
-
|
|
2341
|
+
let msg = '';
|
|
2342
|
+
let extra = {};
|
|
2343
|
+
if (message instanceof Error) {
|
|
2344
|
+
msg = message.message;
|
|
2345
|
+
extra = {
|
|
2346
|
+
stack: message.stack,
|
|
2347
|
+
name: message.name,
|
|
2348
|
+
...data,
|
|
2349
|
+
};
|
|
2350
|
+
}
|
|
2351
|
+
else {
|
|
2352
|
+
msg = String(message);
|
|
2353
|
+
extra = data;
|
|
2354
|
+
}
|
|
2355
|
+
const payload = normalizeFlatFields({ message: msg, ...extra }, 'error');
|
|
2360
2356
|
this.report({ type: 'error', data: payload, timestamp: Date.now() });
|
|
2361
2357
|
}
|
|
2362
2358
|
track(trackType, data = {}) {
|
|
@@ -2578,38 +2574,78 @@
|
|
|
2578
2574
|
}
|
|
2579
2575
|
}
|
|
2580
2576
|
const isMini = this.envType === 'miniprogram';
|
|
2581
|
-
//
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2577
|
+
// 3) 尝试 require / 全局变量
|
|
2578
|
+
// Mini Program: 尝试直接 require
|
|
2579
|
+
if (isMini) {
|
|
2580
|
+
// 显式使用字面量 require,帮助打包工具识别依赖(尤其是 CJS 构建模式下)
|
|
2581
|
+
try {
|
|
2582
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
2583
|
+
const req = typeof require === 'function' ? require('tencentcloud-cls-sdk-js-mini') : null;
|
|
2584
|
+
const reqSdk = normalizeSdk(req);
|
|
2585
|
+
if (reqSdk) {
|
|
2586
|
+
this.sdk = reqSdk;
|
|
2587
|
+
return reqSdk;
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
catch {
|
|
2591
|
+
// ignore
|
|
2592
|
+
}
|
|
2593
|
+
// 尝试使用 tryRequire(作为补充)
|
|
2594
|
+
const reqMod = tryRequire('tencentcloud-cls-sdk-js-mini');
|
|
2595
|
+
const reqSdk = normalizeSdk(reqMod);
|
|
2596
|
+
if (reqSdk) {
|
|
2597
|
+
this.sdk = reqSdk;
|
|
2598
|
+
return reqSdk;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
else {
|
|
2602
|
+
// Web: 优先读全局变量 (UMD)
|
|
2586
2603
|
const g = readGlobal('tencentcloudClsSdkJsWeb');
|
|
2587
2604
|
const sdk = normalizeSdk(g);
|
|
2588
2605
|
if (sdk) {
|
|
2589
2606
|
this.sdk = sdk;
|
|
2590
2607
|
return sdk;
|
|
2591
2608
|
}
|
|
2609
|
+
// Web: 尝试 require
|
|
2610
|
+
const reqMod = tryRequire('tencentcloud-cls-sdk-js-web');
|
|
2611
|
+
const reqSdk = normalizeSdk(reqMod);
|
|
2612
|
+
if (reqSdk) {
|
|
2613
|
+
this.sdk = reqSdk;
|
|
2614
|
+
return reqSdk;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
// 4) 动态 import
|
|
2618
|
+
// 使用字符串字面量,确保 Bundler 能正确识别并进行 Code Splitting
|
|
2619
|
+
if (isMini) {
|
|
2620
|
+
this.sdkPromise = import('tencentcloud-cls-sdk-js-mini')
|
|
2621
|
+
.then((m) => {
|
|
2622
|
+
const sdk = normalizeSdk(m);
|
|
2623
|
+
if (!sdk)
|
|
2624
|
+
throw new Error(`ClsLogger.loadSdk: invalid sdk module for mini`);
|
|
2625
|
+
this.sdk = sdk;
|
|
2626
|
+
return sdk;
|
|
2627
|
+
})
|
|
2628
|
+
.catch((err) => {
|
|
2629
|
+
this.sdkPromise = null;
|
|
2630
|
+
console.error('[ClsLogger] Failed to load mini sdk:', err);
|
|
2631
|
+
throw err;
|
|
2632
|
+
});
|
|
2633
|
+
}
|
|
2634
|
+
else {
|
|
2635
|
+
this.sdkPromise = import('tencentcloud-cls-sdk-js-web')
|
|
2636
|
+
.then((m) => {
|
|
2637
|
+
const sdk = normalizeSdk(m);
|
|
2638
|
+
if (!sdk)
|
|
2639
|
+
throw new Error(`ClsLogger.loadSdk: invalid sdk module for web`);
|
|
2640
|
+
this.sdk = sdk;
|
|
2641
|
+
return sdk;
|
|
2642
|
+
})
|
|
2643
|
+
.catch((err) => {
|
|
2644
|
+
this.sdkPromise = null;
|
|
2645
|
+
console.error('[ClsLogger] Failed to load web sdk:', err);
|
|
2646
|
+
throw err;
|
|
2647
|
+
});
|
|
2592
2648
|
}
|
|
2593
|
-
// 尽量同步 require
|
|
2594
|
-
const reqMod = tryRequire(isMini ? MINI_SDK : WEB_SDK);
|
|
2595
|
-
const reqSdk = normalizeSdk(reqMod);
|
|
2596
|
-
if (reqSdk) {
|
|
2597
|
-
this.sdk = reqSdk;
|
|
2598
|
-
return reqSdk;
|
|
2599
|
-
}
|
|
2600
|
-
// 动态 import
|
|
2601
|
-
this.sdkPromise = (isMini ? import(MINI_SDK) : import(WEB_SDK))
|
|
2602
|
-
.then((m) => {
|
|
2603
|
-
const sdk = normalizeSdk(m);
|
|
2604
|
-
if (!sdk)
|
|
2605
|
-
throw new Error(`ClsLogger.loadSdk: invalid sdk module for ${isMini ? MINI_SDK : WEB_SDK}`);
|
|
2606
|
-
this.sdk = sdk;
|
|
2607
|
-
return sdk;
|
|
2608
|
-
})
|
|
2609
|
-
.catch((err) => {
|
|
2610
|
-
this.sdkPromise = null;
|
|
2611
|
-
throw err;
|
|
2612
|
-
});
|
|
2613
2649
|
return this.sdkPromise;
|
|
2614
2650
|
}
|
|
2615
2651
|
}
|