@be-link/cls-logger 1.0.10 → 1.0.12

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 CHANGED
@@ -2,81 +2,86 @@
2
2
 
3
3
  腾讯云 CLS(`tencentcloud-cls-sdk-js-web` / `tencentcloud-cls-sdk-js-mini`)日志上报封装,支持 Web、H5 和小程序环境,提供统一的调用方式。
4
4
 
5
+ ## 特性
6
+
7
+ - 自动环境适配(Web / H5 / 小程序)
8
+ - 内存队列批量上报,减少网络请求
9
+ - 页面关闭时 `sendBeacon` 保证日志不丢失
10
+ - 支持浏览器空闲时上报(`requestIdleCallback`)
11
+ - 错误即时上报,信息日志批量上报
12
+ - 自动采集:请求监控、性能监控、错误监控、行为埋点
13
+ - 失败重试 + 本地缓存兜底
14
+
5
15
  ## 安装
6
16
 
7
17
  ```bash
8
18
  pnpm add @be-link/cls-logger
9
19
  ```
10
20
 
11
- > **注意**:
12
- >
13
- > 1. SDK 内部会自动根据运行环境加载对应的腾讯云 SDK(Web 或小程序),无需手动安装额外依赖。
14
- > 2. 如果业务对包体积有极致要求,建议使用**分环境引入方式**(见下文)。
21
+ ### 依赖说明
15
22
 
16
- ## 使用
23
+ | 入口 | 依赖 | 说明 |
24
+ | -------------------------- | -------------------------------------------- | ----------------------------------- |
25
+ | `@be-link/cls-logger` | `tencentcloud-cls-sdk-js-web` | 统一入口,自动适配环境 |
26
+ | `@be-link/cls-logger/web` | `tencentcloud-cls-sdk-js-web` + `web-vitals` | Web/H5 专用,含 Web Vitals 性能监控 |
27
+ | `@be-link/cls-logger/mini` | `tencentcloud-cls-sdk-js-mini` | 小程序专用 |
17
28
 
18
- ### 1. 统一引入方式(推荐快速接入)
29
+ > **注意**:所有依赖已内置,无需手动安装。
19
30
 
20
- 无需关心运行环境(Web 或 小程序),SDK 内部会自动识别并适配。此方式包含全量逻辑,支持动态加载 SDK。
31
+ ## 快速开始
32
+
33
+ ### 1. 统一引入方式(推荐快速接入)
21
34
 
22
35
  ```ts
23
36
  import clsLogger from '@be-link/cls-logger';
24
37
 
25
- // 初始化(建议在应用入口处调用)
26
38
  clsLogger.init({
27
39
  projectId: 'my-project',
28
40
  appId: 'my-app-id',
29
- tencentCloud: {
30
- endpoint: 'ap-shanghai.cls.tencentcs.com',
31
- topicID: 'your-topic-id',
32
- },
41
+ source: 'my-source',
33
42
  });
34
43
  ```
35
44
 
36
- ### 2. 分环境引入方式(推荐生产环境使用)
45
+ ### 2. 分环境引入方式(推荐生产环境)
37
46
 
38
- 为了获得更小的包体积(Tree Shaking)和更清晰的逻辑,建议根据项目类型引入不同的入口。此方式将物理隔离 Web 和小程序的特有逻辑(如 Web 的 `fetch` 拦截 vs 小程序的 `wx.request` 拦截)。
39
-
40
- #### Web / H5 项目:
47
+ #### Web / H5:
41
48
 
42
49
  ```ts
43
- // 仅包含 Web 相关逻辑,不再包含小程序代码
44
50
  import { clsLogger } from '@be-link/cls-logger/web';
45
51
 
46
52
  clsLogger.init({
47
53
  projectId: 'my-web-project',
48
- tencentCloud: {
49
- endpoint: 'ap-shanghai.cls.tencentcs.com',
50
- topicID: 'your-web-topic-id',
51
- },
54
+ source: 'web-source',
52
55
  });
53
56
  ```
54
57
 
55
- #### 小程序项目:
58
+ #### 小程序:
56
59
 
57
60
  ```ts
58
- // 仅包含小程序相关逻辑,不再包含 Web 代码
59
61
  import { clsLogger } from '@be-link/cls-logger/mini';
60
62
 
61
63
  clsLogger.init({
62
64
  projectId: 'my-mini-project',
63
- appId: 'wx123456789', // 小程序建议传入 appId
64
- tencentCloud: {
65
- endpoint: 'ap-shanghai.cls.tencentcs.com',
66
- topicID: 'your-mini-topic-id',
67
- },
65
+ appId: 'wx123456789',
66
+ source: 'mini-source',
68
67
  });
69
68
  ```
70
69
 
71
- ## 常用 API
70
+ ## API
72
71
 
73
- ### 开发日志
72
+ ### 日志方法
74
73
 
75
74
  ```ts
76
- // info / warn / error
75
+ // 信息日志(走批量队列)
77
76
  clsLogger.info('应用启动', { startUpTime: 120 });
78
77
 
79
- // Error 日志(支持直接传入 Error 对象,自动解析堆栈)
78
+ // 警告日志(走批量队列)
79
+ clsLogger.warn('资源加载慢', { duration: 3000 });
80
+
81
+ // 错误日志(默认即时上报)
82
+ clsLogger.error('支付失败', { orderId: '123' });
83
+
84
+ // Error 对象(自动解析堆栈)
80
85
  try {
81
86
  doSomething();
82
87
  } catch (err) {
@@ -84,7 +89,17 @@ try {
84
89
  }
85
90
  ```
86
91
 
87
- ### 自定义埋点 (Track)
92
+ ### 即时上报选项
93
+
94
+ ```ts
95
+ // info/warn 强制即时上报
96
+ clsLogger.info('重要事件', { data: 1 }, { immediate: true });
97
+
98
+ // error 走批量队列(默认是即时上报)
99
+ clsLogger.error('非关键错误', { data: 1 }, { immediate: false });
100
+ ```
101
+
102
+ ### 自定义埋点
88
103
 
89
104
  ```ts
90
105
  clsLogger.track('click_event', {
@@ -93,9 +108,7 @@ clsLogger.track('click_event', {
93
108
  });
94
109
  ```
95
110
 
96
- ### 统计埋点 (Stat)
97
-
98
- 用于简单的计数/分布统计。
111
+ ### 统计埋点
99
112
 
100
113
  ```ts
101
114
  clsLogger.stat({
@@ -106,59 +119,395 @@ clsLogger.stat({
106
119
  });
107
120
  ```
108
121
 
109
- ## 功能特性
122
+ ## 配置项
110
123
 
111
- ### 1. 自动环境适配
124
+ ### 完整配置示例
112
125
 
113
- - **Web / H5**: 自动采集浏览器环境信息(UserAgent、屏幕尺寸、网络状态等)。
114
- - **小程序**: 自动采集小程序环境信息(系统信息、微信版本、网络类型等)。
126
+ ```ts
127
+ clsLogger.init({
128
+ // 基础配置
129
+ enabled: true, // 是否启用,默认 true
130
+ projectId: 'my-project', // 项目标识
131
+ appId: 'wx123456789', // 应用 ID(小程序必填)
132
+ appVersion: '1.0.0', // 应用版本
133
+ source: 'my-source', // CLS source
134
+
135
+ // 腾讯云 CLS 配置
136
+ tencentCloud: {
137
+ endpoint: 'https://ap-shanghai.cls.tencentcs.com',
138
+ topicID: 'your-topic-id',
139
+ retry_times: 3,
140
+ },
115
141
 
116
- ### 2. 请求监控 (Request Monitor)
142
+ // 批量上报配置
143
+ batch: {
144
+ maxSize: 50, // 队列达到此数量立即发送,默认 20
145
+ intervalMs: 1000, // 定时批量发送间隔,默认 500ms
146
+ startupDelayMs: 3000, // 启动合并窗口,默认 0(不启用)
147
+ startupMaxSize: 500, // 启动窗口内的队列阈值,默认 maxSize*10(至少200)
148
+ useIdleCallback: true, // 使用浏览器空闲时间上报,默认 false
149
+ idleTimeout: 3000, // 空闲回调超时时间,默认 3000ms
150
+ },
117
151
 
118
- 默认开启。
152
+ // 请求监控配置
153
+ requestMonitor: {
154
+ enabled: true, // 是否开启,默认 true
155
+ sampleRate: 1, // 采样率 0~1,默认 1
156
+ ignoreUrls: [/localhost/], // 忽略的 URL
157
+ includeMethod: true, // 是否携带 method,默认 true
158
+ includeQuery: true, // 是否携带 query,默认 true
159
+ includeBody: true, // 是否携带 body,默认 true
160
+ maxParamLength: 2000, // 参数最大长度,默认 2000
161
+ },
119
162
 
120
- - **Web**: 拦截 `fetch` / `XMLHttpRequest`。
121
- - **小程序**: 拦截 `wx.request` / `wx.cloud.callFunction`。
163
+ // 错误监控配置
164
+ errorMonitor: {
165
+ enabled: true, // 是否开启,默认 true
166
+ sampleRate: 1, // 采样率 0~1,默认 1
167
+ captureResourceError: true, // 是否采集资源加载错误,默认 true
168
+ maxTextLength: 4000, // stack/message 最大长度,默认 4000
169
+ dedupeWindowMs: 3000, // 错误去重窗口,默认 3000ms
170
+ dedupeMaxKeys: 200, // 去重缓存最大 key 数,默认 200
171
+ ignoreMessages: [
172
+ // 忽略的错误信息(默认值)
173
+ 'Script error.',
174
+ 'Script error',
175
+ /^ResizeObserver loop/,
176
+ 'Permission was denied',
177
+ ],
178
+ },
122
179
 
123
- ### 3. 性能监控 (Performance Monitor)
180
+ // 性能监控配置
181
+ performanceMonitor: {
182
+ enabled: true, // 是否开启,默认 true
183
+ sampleRate: 1, // 采样率 0~1,默认 1
184
+ webVitals: true, // 是否采集 Web Vitals(含 TTFB),默认 true
185
+ resourceTiming: true, // 是否采集资源加载耗时,默认 true
186
+ ignoreUrls: [/localhost/], // 忽略的资源 URL
187
+ maxTextLength: 2000, // 性能指标文本最大长度,默认 2000
188
+ },
124
189
 
125
- 默认开启。
190
+ // 行为埋点配置
191
+ behaviorMonitor: {
192
+ enabled: true, // 是否开启,默认 true
193
+ pv: true, // PV 是否开启,默认 true
194
+ uv: true, // UV 是否开启,默认 true
195
+ click: true, // 点击是否开启,默认 true
196
+ sampleRate: 1, // 采样率 0~1,默认 1
197
+ uvExpireDays: 30, // UV 标识过期天数,默认 30
198
+ clickTrackIdAttr: 'data-track-id', // 点击元素埋点标识属性名
199
+ clickMaxTextLength: 120, // 点击文本最大长度,默认 120
200
+ },
126
201
 
127
- - **Web**: 采集 FCP, LCP, CLS, FID 等 Core Web Vitals 及资源加载耗时。
128
- - **小程序**: 支持采集页面首屏渲染耗时 (`firstRender`)、路由切换耗时 (`route`) 及启动耗时 (`appLaunch`)。
202
+ // 设备信息配置
203
+ deviceInfo: {
204
+ enabled: true, // 是否开启,默认 true
205
+ includeUserAgent: true, // 是否包含 UA,默认 true
206
+ includeNetwork: true, // 是否包含网络信息,默认 true
207
+ },
129
208
 
130
- ### 4. 行为埋点 (Behavior Monitor)
209
+ // 自定义基础字段
210
+ generateBaseFields: () => ({
211
+ userId: getUserId(),
212
+ userName: getUserName(),
213
+ environment: 'production',
214
+ }),
215
+ });
216
+ ```
131
217
 
132
- 默认开启,支持 PV (Page View) 和 UV (User View) 自动上报。
218
+ ## 常见场景配置
133
219
 
134
- - **UV ID**: 自动生成并持久化。小程序环境下优先尝试使用 `openid`。
135
- - **点击追踪**: 自动监听点击事件。
136
- - **Web**: 识别带 `data-track-id` 的元素。
137
- - **小程序**: 识别带 `data-track-id` 的组件(需在 `dataset` 中)。
220
+ ### 场景 1:首屏请求过多
138
221
 
139
- ## 高级用法
222
+ 页面首次加载时日志请求过多,影响其他请求:
140
223
 
141
- ### 内存队列与批量发送
224
+ ```ts
225
+ clsLogger.init({
226
+ batch: {
227
+ startupDelayMs: 3000, // 启动 3 秒内的日志合并发送
228
+ startupMaxSize: 500, // 启动窗口内允许更多日志积累(防止 maxSize 打断合并)
229
+ maxSize: 100, // 正常运行时的队列阈值
230
+ intervalMs: 2000, // 延长批量间隔
231
+ useIdleCallback: true, // 等待延迟后在浏览器空闲时上报
232
+ },
233
+ performanceMonitor: {
234
+ resourceTiming: false, // 关闭资源监控(首屏资源多时可大幅减少日志量)
235
+ },
236
+ });
237
+ ```
238
+
239
+ > **说明**:`startupMaxSize` 确保启动窗口内不会因为 `maxSize` 被频繁触发而打断日志合并。
240
+
241
+ ### 场景 2:减少资源监控日志
242
+
243
+ 开发环境资源过多,或生产环境不需要全量资源监控:
244
+
245
+ ```ts
246
+ clsLogger.init({
247
+ performanceMonitor: {
248
+ resourceTiming: false, // 关闭资源监控
249
+ // 或者采样
250
+ // sampleRate: 0.1, // 10% 采样
251
+ // 或者过滤
252
+ // ignoreUrls: [/localhost/, /node_modules/],
253
+ },
254
+ });
255
+ ```
256
+
257
+ ### 场景 3:过滤无意义的错误
258
+
259
+ 过滤第三方 SDK 的跨域错误:
260
+
261
+ ```ts
262
+ clsLogger.init({
263
+ errorMonitor: {
264
+ ignoreMessages: [
265
+ // 默认规则
266
+ 'Script error.',
267
+ 'Script error',
268
+ /^ResizeObserver loop/,
269
+ 'Permission was denied',
270
+ // 自定义规则
271
+ /火山SDK/,
272
+ /VolcEngine/,
273
+ /network error/i,
274
+ ],
275
+ },
276
+ });
277
+ ```
142
278
 
143
- SDK 默认开启内存队列,每 500ms 或达到 20 条日志时自动批量上报,以减少网络请求次数。可通过 `batch` 参数配置:
279
+ ### 场景 4:高并发场景(直播间)
144
280
 
145
281
  ```ts
146
282
  clsLogger.init({
147
283
  batch: {
148
- maxSize: 20,
149
- intervalMs: 500,
150
- startupDelayMs: 1000, // 启动阶段合并窗口
284
+ startupDelayMs: 3000, // 启动合并窗口
285
+ startupMaxSize: 500, // 启动窗口内的队列阈值
286
+ maxSize: 100, // 正常运行时的队列阈值
287
+ intervalMs: 2000, // 延长批量间隔
288
+ useIdleCallback: true, // 空闲时上报,不阻塞主线程
289
+ },
290
+ performanceMonitor: {
291
+ resourceTiming: false, // 关闭资源监控
292
+ },
293
+ requestMonitor: {
294
+ sampleRate: 0.1, // 请求监控采样 10%
295
+ ignoreUrls: [
296
+ /heartbeat/i, // 忽略心跳请求
297
+ /polling/i, // 忽略轮询请求
298
+ /danmaku|barrage/i, // 忽略弹幕请求
299
+ ],
151
300
  },
152
301
  });
153
302
  ```
154
303
 
155
- ### 失败重试与本地缓存
304
+ ## 最佳实践
305
+
306
+ ### 1. 批量配置的正确姿势
307
+
308
+ #### `useIdleCallback` 工作原理
309
+
310
+ 当 `useIdleCallback: true` 时,SDK 的上报流程为:
311
+
312
+ ```
313
+ 日志产生 → 等待 intervalMs/startupDelayMs → 等待浏览器空闲 → 发送
314
+ ↑ 最小等待时间 ↑ 在 idleTimeout 内空闲就发送
315
+ ```
316
+
317
+ **关键点**:
156
318
 
157
- 上报失败的日志会自动进入重试流程(指数退避算法)。若多次重试仍失败,日志会落盘到本地缓存(`localStorage` 或小程序 `Storage`),在下次应用启动时尝试重新上报。
319
+ - `intervalMs`/`startupDelayMs` 是**最小等待时间**,保证不会过早发送
320
+ - `idleTimeout` 是空闲等待的**最大时间**,防止浏览器一直繁忙导致日志积压
158
321
 
159
- ### 手动注入 SDK
322
+ #### `startupMaxSize` 的作用
160
323
 
161
- 在某些特殊构建环境(如某些不允许动态 require 的小程序框架)下,可以手动注入:
324
+ 启动阶段(`startupDelayMs` 窗口内)日志量通常很大(性能指标、资源加载等),如果 `maxSize` 设置过小,会频繁触发队列满而打断合并:
325
+
326
+ ```ts
327
+ // ❌ 错误配置:startupDelayMs 会被 maxSize 打断
328
+ batch: {
329
+ startupDelayMs: 3000,
330
+ maxSize: 20, // 启动期间可能产生 200+ 条日志,会触发 10+ 次发送
331
+ }
332
+
333
+ // ✅ 正确配置:使用 startupMaxSize 保护启动窗口
334
+ batch: {
335
+ startupDelayMs: 3000,
336
+ maxSize: 20,
337
+ startupMaxSize: 500, // 启动期间允许更多日志积累
338
+ }
339
+ ```
340
+
341
+ ### 2. 推荐配置模板
342
+
343
+ #### 普通 H5 页面
344
+
345
+ ```ts
346
+ clsLogger.init({
347
+ batch: {
348
+ startupDelayMs: 2000,
349
+ startupMaxSize: 300,
350
+ maxSize: 50,
351
+ intervalMs: 1000,
352
+ useIdleCallback: true,
353
+ idleTimeout: 3000,
354
+ },
355
+ });
356
+ ```
357
+
358
+ #### 首屏性能敏感(电商、活动页)
359
+
360
+ ```ts
361
+ clsLogger.init({
362
+ batch: {
363
+ startupDelayMs: 5000, // 更长的启动窗口
364
+ startupMaxSize: 500,
365
+ maxSize: 100,
366
+ intervalMs: 2000,
367
+ useIdleCallback: true,
368
+ idleTimeout: 5000,
369
+ },
370
+ performanceMonitor: {
371
+ sampleRate: 0.3, // 性能监控采样
372
+ },
373
+ });
374
+ ```
375
+
376
+ #### 高频交互页面(直播间、游戏)
377
+
378
+ ```ts
379
+ clsLogger.init({
380
+ batch: {
381
+ startupDelayMs: 3000,
382
+ startupMaxSize: 500,
383
+ maxSize: 100,
384
+ intervalMs: 3000, // 更长的间隔
385
+ useIdleCallback: true,
386
+ idleTimeout: 5000,
387
+ },
388
+ performanceMonitor: {
389
+ resourceTiming: false, // 关闭资源监控
390
+ },
391
+ requestMonitor: {
392
+ sampleRate: 0.1, // 请求监控采样
393
+ ignoreUrls: [/heartbeat/, /polling/, /danmaku/],
394
+ },
395
+ });
396
+ ```
397
+
398
+ ### 3. 日志量优化技巧
399
+
400
+ | 优化项 | 配置 | 效果 |
401
+ | ------------ | ------------------------------------------ | ------------------------- |
402
+ | 关闭资源监控 | `performanceMonitor.resourceTiming: false` | 减少 80%+ 的 perf 日志 |
403
+ | 性能采样 | `performanceMonitor.sampleRate: 0.1` | 只采集 10% 用户的性能数据 |
404
+ | 请求采样 | `requestMonitor.sampleRate: 0.1` | 只采集 10% 的请求日志 |
405
+ | 忽略高频请求 | `requestMonitor.ignoreUrls: [/heartbeat/]` | 过滤心跳等高频请求 |
406
+ | 错误去重 | `errorMonitor.dedupeWindowMs: 5000` | 5秒内相同错误只上报一次 |
407
+
408
+ ### 4. 常见问题排查
409
+
410
+ #### 问题:首屏请求过多
411
+
412
+ **现象**:页面加载时发出 10+ 个日志请求
413
+
414
+ **排查步骤**:
415
+
416
+ 1. 检查 `startupDelayMs` 是否配置
417
+ 2. 检查 `startupMaxSize` 是否足够大(建议 300-500)
418
+ 3. 检查 `resourceTiming` 是否需要开启(这是日志量最大的来源)
419
+
420
+ #### 问题:日志延迟过高
421
+
422
+ **现象**:日志上报明显滞后
423
+
424
+ **排查步骤**:
425
+
426
+ 1. 检查 `useIdleCallback` + `idleTimeout` 配置
427
+ 2. 检查 `intervalMs` 是否设置过大
428
+ 3. 考虑关闭 `useIdleCallback` 或减小 `idleTimeout`
429
+
430
+ #### 问题:页面关闭丢日志
431
+
432
+ **现象**:用户快速关闭页面时日志丢失
433
+
434
+ **说明**:SDK 已通过 `sendBeacon` 处理此场景,如仍有丢失:
435
+
436
+ 1. 检查日志是否在 `memoryQueue` 中(可能还未触发 flush)
437
+ 2. 考虑对关键日志使用 `{ immediate: true }`
438
+
439
+ ## 功能说明
440
+
441
+ ### 1. 批量上报机制
442
+
443
+ SDK 使用内存队列批量上报日志:
444
+
445
+ | 触发条件 | 说明 |
446
+ | -------- | ------------------------------------------------------- |
447
+ | 队列满 | 达到 `maxSize`(启动窗口内为 `startupMaxSize`)立即发送 |
448
+ | 定时器 | 每 `intervalMs` 毫秒发送一次 |
449
+ | 页面关闭 | `visibilitychange` + `pagehide` 触发 `sendBeacon` 发送 |
450
+ | 启动合并 | `startupDelayMs` 窗口内的日志尽量合并 |
451
+ | 空闲上报 | `useIdleCallback` 开启时,等待浏览器空闲后发送 |
452
+
453
+ ### 2. 即时上报 vs 批量上报
454
+
455
+ | 方法 | 默认行为 | 说明 |
456
+ | --------- | -------- | -------------------------------------------------------- |
457
+ | `error()` | 即时上报 | 错误需要及时发现,可通过 `{ immediate: false }` 改为批量 |
458
+ | `info()` | 批量上报 | 可通过 `{ immediate: true }` 改为即时 |
459
+ | `warn()` | 批量上报 | 可通过 `{ immediate: true }` 改为即时 |
460
+ | `track()` | 批量上报 | - |
461
+
462
+ ### 3. 页面关闭保障
463
+
464
+ 页面关闭时(`visibilitychange` / `pagehide`),SDK 会:
465
+
466
+ 1. 使用 `navigator.sendBeacon` 同步发送队列中的日志
467
+ 2. 如果 `sendBeacon` 不可用,将日志缓存到本地存储
468
+ 3. 下次启动时自动重试发送缓存的日志
469
+
470
+ ### 4. 失败重试机制
471
+
472
+ - 上报失败后使用指数退避算法重试
473
+ - 多次重试仍失败,日志落盘到本地缓存
474
+ - 下次应用启动时自动尝试重新上报
475
+ - 本地缓存最多保留 200 条(可配置 `failedCacheMax`)
476
+
477
+ ### 5. 自动采集内容
478
+
479
+ #### 请求监控
480
+
481
+ - **Web**: 拦截 `fetch` / `XMLHttpRequest`
482
+ - **小程序**: 拦截 `wx.request` / `wx.cloud.callFunction`
483
+
484
+ #### 性能监控
485
+
486
+ - **Web**: 使用 [Google web-vitals](https://github.com/GoogleChrome/web-vitals) 库实现
487
+ - **FCP** (First Contentful Paint): 首次内容渲染
488
+ - **LCP** (Largest Contentful Paint): 最大内容渲染(用户交互后自动停止)
489
+ - **CLS** (Cumulative Layout Shift): 累积布局偏移(5秒会话窗口算法)
490
+ - **INP** (Interaction to Next Paint): 交互到绘制延迟(替代 FID)
491
+ - **TTFB** (Time to First Byte): 首字节时间
492
+ - **资源加载耗时**: PerformanceResourceTiming
493
+ - 自动处理 BFCache 恢复时的指标重置
494
+ - 上报数据包含 `rating` 字段:`'good'` | `'needs-improvement'` | `'poor'`
495
+ - **小程序**: 首屏渲染、路由切换、启动耗时
496
+
497
+ #### 错误监控
498
+
499
+ - **Web**: `window.onerror`, `unhandledrejection`, 资源加载错误
500
+ - **小程序**: `wx.onError`, `wx.onUnhandledRejection`, `App.onError`
501
+
502
+ #### 行为埋点
503
+
504
+ - **PV**: 页面访问
505
+ - **UV**: 用户访问(自动生成持久化 ID)
506
+ - **点击**: 带 `data-track-id` 属性的元素点击
507
+
508
+ ## 手动注入 SDK
509
+
510
+ 在某些特殊构建环境下,可以手动注入 SDK:
162
511
 
163
512
  ```ts
164
513
  import { clsLogger } from '@be-link/cls-logger/mini';
@@ -166,6 +515,25 @@ import * as MiniSdk from 'tencentcloud-cls-sdk-js-mini';
166
515
 
167
516
  clsLogger.init({
168
517
  tencentCloud: { topicID: 'xxx', endpoint: 'xxx' },
169
- sdk: MiniSdk, // 手动传入 SDK 实例
518
+ sdk: MiniSdk,
170
519
  });
171
520
  ```
521
+
522
+ ## 类型定义
523
+
524
+ ```ts
525
+ import type {
526
+ ClsLoggerInitOptions,
527
+ BatchOptions,
528
+ ReportOptions,
529
+ RequestMonitorOptions,
530
+ ErrorMonitorOptions,
531
+ PerformanceMonitorOptions,
532
+ BehaviorMonitorOptions,
533
+ DeviceInfoOptions,
534
+ } from '@be-link/cls-logger';
535
+ ```
536
+
537
+ ## License
538
+
539
+ MIT
@@ -1,4 +1,4 @@
1
- import type { ClsLoggerInitOptions, ErrorMonitorOptions, EnvType, FlatFields, PerformanceMonitorOptions, PutOptions, QueueItem, ReportLog, RequestMonitorOptions, BehaviorMonitorOptions, DeviceInfoOptions } from './types';
1
+ import type { ClsLoggerInitOptions, ErrorMonitorOptions, EnvType, FlatFields, PerformanceMonitorOptions, PutOptions, QueueItem, ReportLog, ReportOptions, RequestMonitorOptions, BehaviorMonitorOptions, DeviceInfoOptions } from './types';
2
2
  import type { ClsSdkModule } from './clsSdkTypes';
3
3
  /**
4
4
  * CLS Logger 核心基类
@@ -38,6 +38,11 @@ export declare abstract class ClsLoggerCore {
38
38
  protected batchTimerDueAt: number | null;
39
39
  protected initTs: number;
40
40
  protected startupDelayMs: number;
41
+ protected startupMaxSize: number;
42
+ protected useIdleCallback: boolean;
43
+ protected idleTimeout: number;
44
+ protected pendingIdleCallback: number | null;
45
+ protected visibilityCleanup: (() => void) | null;
41
46
  protected failedCacheKey: string;
42
47
  protected failedCacheMax: number;
43
48
  protected requestMonitorStarted: boolean;
@@ -75,8 +80,24 @@ export declare abstract class ClsLoggerCore {
75
80
  * 子类可按需重写(默认检测 wx)
76
81
  */
77
82
  protected detectEnvType(): EnvType;
78
- init(options: ClsLoggerInitOptions): void;
83
+ init(options: ClsLoggerInitOptions): Promise<boolean>;
79
84
  private getBaseFields;
85
+ /**
86
+ * 设置页面可见性监听
87
+ * - visibilitychange: 页面隐藏时使用 sendBeacon 发送队列
88
+ * - pagehide: 作为移动端 fallback
89
+ */
90
+ private setupVisibilityListener;
91
+ /**
92
+ * 同步发送内存队列(使用 sendBeacon)
93
+ * - 用于页面关闭时确保数据发送
94
+ * - sendBeacon 不可用时降级为缓存到 localStorage
95
+ */
96
+ private flushBatchSync;
97
+ /**
98
+ * 构建 sendBeacon 的 payload
99
+ */
100
+ private buildSendBeaconPayload;
80
101
  private startRequestMonitor;
81
102
  private startErrorMonitor;
82
103
  private startPerformanceMonitor;
@@ -121,10 +142,21 @@ export declare abstract class ClsLoggerCore {
121
142
  * 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
122
143
  */
123
144
  report(log: ReportLog): void;
145
+ /**
146
+ * 调度批量发送
147
+ * - 先使用 setTimeout 保证最小延迟(desiredDelay)
148
+ * - 若开启 useIdleCallback,在延迟结束后等待浏览器空闲再执行
149
+ */
150
+ private scheduleFlush;
151
+ /**
152
+ * 取消已调度的批量发送
153
+ * - 同时清理 setTimeout 和可能的 requestIdleCallback
154
+ */
155
+ private cancelScheduledFlush;
124
156
  private getDesiredBatchFlushDueAt;
125
- info(message: string | Error, data?: FlatFields): void;
126
- warn(message: string | Error, data?: FlatFields): void;
127
- error(message: string | Error, data?: FlatFields): void;
157
+ info(message: string | Error, data?: FlatFields, options?: ReportOptions): void;
158
+ warn(message: string | Error, data?: FlatFields, options?: ReportOptions): void;
159
+ error(message: string | Error, data?: FlatFields, options?: ReportOptions): void;
128
160
  track(trackType: string, data?: FlatFields): void;
129
161
  /**
130
162
  * 立即发送内存队列
@@ -1 +1 @@
1
- {"version":3,"file":"ClsLoggerCore.d.ts","sourceRoot":"","sources":["../src/ClsLoggerCore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClsLoggerCore.d.ts","sourceRoot":"","sources":["../src/ClsLoggerCore.ts"],"names":[],"mappings":"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"}