@pluve/logger-sdk 0.0.6 → 0.0.8
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 +139 -432
- package/dist/cjs/capture/jsError.js +48 -0
- package/dist/cjs/capture/promiseError.js +49 -0
- package/dist/cjs/capture/resourceError.js +48 -0
- package/dist/cjs/capture/wechatError.js +95 -0
- package/dist/cjs/compress/compression.js +84 -0
- package/dist/cjs/config/index.js +55 -0
- package/dist/cjs/core/fingerprint.js +36 -0
- package/dist/cjs/core/httpClient.js +96 -0
- package/dist/cjs/core/loggerSDK.js +641 -0
- package/dist/cjs/core/queueManager.js +249 -0
- package/dist/cjs/core/retryManager.js +127 -0
- package/dist/cjs/index.js +29 -0
- package/dist/cjs/logger-sdk.mermaid +84 -0
- package/dist/cjs/logger-sdk.svg +1 -0
- package/dist/cjs/stack/stacktrace.js +48 -0
- package/dist/cjs/transport/beaconTransport.js +64 -0
- package/dist/cjs/transport/pixelImageTransport.js +100 -0
- package/dist/cjs/transport/transport.js +17 -0
- package/dist/cjs/transport/transportAdapter.js +56 -0
- package/dist/cjs/transport/wechatTransport.js +103 -0
- package/dist/cjs/types/api.js +17 -0
- package/dist/cjs/types/env.js +17 -0
- package/dist/cjs/types/external.d.ts +21 -0
- package/dist/cjs/types/logEvent.js +17 -0
- package/dist/cjs/types/logEventLevel.js +17 -0
- package/dist/cjs/types/sdkOptions.js +17 -0
- package/dist/cjs/types/trackOptions.js +17 -0
- package/dist/cjs/utils/environment.js +183 -0
- package/dist/cjs/utils/session.js +31 -0
- package/dist/cjs/utils/tools.js +82 -0
- package/dist/cjs/utils/uuid.js +35 -0
- package/dist/esm/capture/jsError.js +45 -0
- package/dist/esm/capture/promiseError.js +46 -0
- package/dist/esm/capture/resourceError.js +24 -0
- package/dist/esm/capture/wechatError.js +92 -0
- package/dist/esm/compress/compression.js +82 -0
- package/dist/esm/config/index.js +28 -0
- package/dist/esm/core/fingerprint.js +12 -0
- package/dist/esm/core/httpClient.js +95 -0
- package/dist/esm/core/loggerSDK.js +650 -0
- package/dist/esm/core/queueManager.js +269 -0
- package/dist/esm/core/retryManager.js +129 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/logger-sdk.mermaid +84 -0
- package/dist/esm/logger-sdk.svg +1 -0
- package/dist/esm/stack/stacktrace.js +37 -0
- package/dist/esm/transport/beaconTransport.js +81 -0
- package/dist/esm/transport/pixelImageTransport.js +99 -0
- package/dist/esm/transport/transport.js +0 -0
- package/dist/esm/transport/transportAdapter.js +32 -0
- package/dist/esm/transport/wechatTransport.js +120 -0
- package/dist/esm/types/api.js +0 -0
- package/dist/esm/types/env.js +0 -0
- package/dist/esm/types/external.d.ts +21 -0
- package/dist/esm/types/logEvent.js +0 -0
- package/dist/esm/types/logEventLevel.js +0 -0
- package/dist/esm/types/sdkOptions.js +0 -0
- package/dist/esm/types/trackOptions.js +0 -0
- package/dist/esm/utils/environment.js +154 -0
- package/dist/esm/utils/session.js +7 -0
- package/dist/esm/utils/tools.js +76 -0
- package/dist/esm/utils/uuid.js +11 -0
- package/dist/types/capture/jsError.d.ts +2 -0
- package/dist/types/capture/promiseError.d.ts +2 -0
- package/dist/types/capture/resourceError.d.ts +2 -0
- package/dist/types/capture/wechatError.d.ts +3 -0
- package/dist/types/compress/compression.d.ts +10 -0
- package/dist/types/config/index.d.ts +9 -0
- package/dist/types/core/fingerprint.d.ts +8 -0
- package/dist/types/core/httpClient.d.ts +11 -0
- package/dist/{loggerSDK.d.ts → types/core/loggerSDK.d.ts} +32 -14
- package/dist/{queueManager.d.ts → types/core/queueManager.d.ts} +9 -5
- package/dist/{retryManager.d.ts → types/core/retryManager.d.ts} +2 -6
- package/dist/types/index.d.ts +1 -0
- package/dist/types/stack/stacktrace.d.ts +2 -0
- package/dist/types/transport/beaconTransport.d.ts +11 -0
- package/dist/types/transport/pixelImageTransport.d.ts +11 -0
- package/dist/types/transport/transport.d.ts +14 -0
- package/dist/types/transport/transportAdapter.d.ts +10 -0
- package/dist/types/transport/wechatTransport.d.ts +11 -0
- package/dist/types/types/api.d.ts +12 -0
- package/dist/types/types/env.d.ts +14 -0
- package/dist/types/types/logEvent.d.ts +57 -0
- package/dist/types/types/logEventLevel.d.ts +2 -0
- package/dist/types/types/sdkOptions.d.ts +61 -0
- package/dist/types/types/trackOptions.d.ts +7 -0
- package/dist/types/utils/environment.d.ts +21 -0
- package/dist/types/utils/session.d.ts +1 -0
- package/dist/types/utils/tools.d.ts +12 -0
- package/dist/types/utils/uuid.d.ts +7 -0
- package/dist/umd/logger-sdk.min.js +1 -0
- package/package.json +30 -6
- package/README.html +0 -982
- package/dist/index.d.ts +0 -10
- package/dist/index.js +0 -13
- package/dist/loggerSDK.js +0 -573
- package/dist/queueManager.js +0 -201
- package/dist/retryManager.js +0 -223
- package/dist/transportAdapter.d.ts +0 -51
- package/dist/transportAdapter.js +0 -315
- package/dist/types.d.ts +0 -70
- package/dist/types.js +0 -1
- package/dist/utils.d.ts +0 -47
- package/dist/utils.js +0 -306
package/README.md
CHANGED
|
@@ -1,501 +1,208 @@
|
|
|
1
1
|
# @pluve/logger-sdk 使用说明
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 概览
|
|
4
4
|
|
|
5
|
-
- 轻量级前端日志采集 SDK
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
5
|
+
- 轻量级前端日志采集 SDK,支持浏览器与微信小程序
|
|
6
|
+
- 传输优先级:Beacon(页面卸载可靠)→ Image(像素降级);小程序使用 wx.request
|
|
7
|
+
- 支持:批量上报(默认关闭)、重试与指数退避、持久化队列、自动卸载刷新
|
|
8
|
+
- 会话锁定:init 时生成并锁定 sessionId,destroy 前所有日志使用同一会话
|
|
9
9
|
|
|
10
10
|
## 安装与引入
|
|
11
11
|
|
|
12
|
-
- 安装:`
|
|
13
|
-
- ESM:`import LoggerSDK from '@pluve/logger-sdk'`
|
|
12
|
+
- 安装:`yarn add @pluve/logger-sdk`
|
|
13
|
+
- ESM:`import { LoggerSDK } from '@pluve/logger-sdk'`
|
|
14
14
|
- UMD:构建后全局为 `LoggerSDK`
|
|
15
15
|
|
|
16
16
|
## 快速开始(单例 + init)
|
|
17
17
|
|
|
18
18
|
```ts
|
|
19
|
-
import LoggerSDK from '@pluve/logger-sdk';
|
|
19
|
+
import { LoggerSDK } from '@pluve/logger-sdk';
|
|
20
20
|
|
|
21
|
-
// 推荐使用单例
|
|
22
21
|
const sdk = LoggerSDK.getInstance();
|
|
23
22
|
sdk.init({
|
|
24
23
|
endpoint: '/api/log',
|
|
25
24
|
appId: 'web-shop',
|
|
26
25
|
env: 'prod', // prod/stage/dev
|
|
27
26
|
debug: true,
|
|
28
|
-
//
|
|
29
|
-
// enableBatch: true,
|
|
27
|
+
// enableBatch: true, // 默认 false,如需开启批量
|
|
30
28
|
});
|
|
31
29
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// 记录错误日志
|
|
36
|
-
await sdk.track('error', 'TypeError: Cannot read property', undefined, {
|
|
37
|
-
level: 'error',
|
|
38
|
-
stack: 'Error stack trace...',
|
|
39
|
-
userId: '123',
|
|
40
|
-
tags: {
|
|
41
|
-
component: 'checkout',
|
|
42
|
-
},
|
|
43
|
-
});
|
|
30
|
+
// 可选:设置用户与店铺编码,后续上报自动携带
|
|
31
|
+
sdk.identify('user_123');
|
|
32
|
+
sdk.setStoreCode('STORE_001');
|
|
44
33
|
|
|
45
|
-
//
|
|
46
|
-
await sdk.track(
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
// 记录错误(推荐传入 Error,提高定位能力)
|
|
35
|
+
await sdk.track({
|
|
36
|
+
message: 'TypeError: Cannot read property',
|
|
37
|
+
error: new Error('TypeError: Cannot read property'),
|
|
38
|
+
traceId: 'trace-abc-123', // 可选
|
|
39
|
+
logLevel: 'error', // 可选,默认 'info'
|
|
49
40
|
});
|
|
50
41
|
|
|
51
|
-
//
|
|
52
|
-
await sdk.track(
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
// 记录普通信息
|
|
43
|
+
await sdk.track({
|
|
44
|
+
message: 'User clicked submit',
|
|
45
|
+
logLevel: 'info',
|
|
55
46
|
});
|
|
56
47
|
```
|
|
57
48
|
|
|
58
|
-
##
|
|
59
|
-
|
|
60
|
-
上报的日志数据遵循以下标准格式:
|
|
49
|
+
## 事件数据结构(实际实现)
|
|
61
50
|
|
|
62
|
-
```
|
|
51
|
+
```ts
|
|
63
52
|
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
53
|
+
// 唯一日志标识:由 appId + UUID + 时间戳组成(非纯 v4)
|
|
54
|
+
logId: "web-shop24f8d7ef-1ed4-41fc-8aa8-c1c01cfa5b291767079629320",
|
|
55
|
+
traceId: "trace-123456", // 可选
|
|
56
|
+
appId: "web-shop",
|
|
57
|
+
stage: "prod", // prod/stage/dev
|
|
58
|
+
level: "error", // info/warn/error/fatal
|
|
59
|
+
message: "TypeError: ...",
|
|
60
|
+
stack: "...", // 可选
|
|
61
|
+
url: "https://...", // 当前页面
|
|
62
|
+
userId: "123", // 可选(建议脱敏)
|
|
63
|
+
frontendId: "session_xxx", // init 时锁定的会话标识(同 sessionId)
|
|
64
|
+
tags: { // 环境标签(init 时收集)
|
|
65
|
+
platform: "browser",
|
|
66
|
+
browser: "Chrome",
|
|
67
|
+
os: "macOS",
|
|
68
|
+
screenWidth: 1920,
|
|
69
|
+
screenHeight: 1080,
|
|
70
|
+
language: "zh-CN"
|
|
79
71
|
}
|
|
80
72
|
}
|
|
81
73
|
```
|
|
82
74
|
|
|
83
|
-
## API
|
|
75
|
+
## API 与行为
|
|
84
76
|
|
|
85
77
|
### 单例与初始化
|
|
86
78
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
#### `init(options: SDKOptions)`
|
|
79
|
+
- `LoggerSDK.getInstance(): LoggerSDK` 获取全局唯一实例
|
|
80
|
+
- `init(options: SDKOptions)` 初始化、锁定 `sessionId`、收集环境标签
|
|
81
|
+
- `new LoggerSDK(options?: SDKOptions)` 构造时传入 options 会自动 init
|
|
92
82
|
|
|
93
|
-
|
|
94
|
-
注意:锁定的 sessionId 将在销毁前用于所有日志上报。
|
|
83
|
+
### SDKOptions(实际默认值)
|
|
95
84
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
创建 SDK 实例;如果传入 `options`,会在构造时自动调用 `init(options)`。
|
|
99
|
-
|
|
100
|
-
**配置项:**
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
85
|
+
```ts
|
|
103
86
|
interface SDKOptions {
|
|
104
|
-
endpoint: string; //
|
|
105
|
-
appId: string; //
|
|
106
|
-
env?:
|
|
107
|
-
debug?: boolean; //
|
|
108
|
-
pixelParam?: string; //
|
|
109
|
-
maxPixelUrlLen?: number; //
|
|
110
|
-
enableGzip?: boolean; //
|
|
111
|
-
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// 重试配置
|
|
123
|
-
enableRetry?: boolean; // 是否启用重试,默认 true
|
|
124
|
-
maxRetries?: number; // 最大重试次数,默认 3
|
|
125
|
-
retryDelay?: number; // 重试基础延迟时间(毫秒),默认 1000
|
|
126
|
-
retryBackoff?: boolean; // 是否使用指数退避策略,默认 true
|
|
87
|
+
endpoint: string; // 必填
|
|
88
|
+
appId: string; // 必填
|
|
89
|
+
env?: 'prod' | 'stage' | 'dev'; // 默认 'dev'
|
|
90
|
+
debug?: boolean; // 默认 false
|
|
91
|
+
pixelParam?: string; // 默认 'data'
|
|
92
|
+
maxPixelUrlLen?: number; // 默认 4096
|
|
93
|
+
enableGzip?: boolean; // 默认 true(传输适配器内部处理)
|
|
94
|
+
enableBatch?: boolean; // 默认 false(需显式开启)
|
|
95
|
+
batchSize?: number; // 默认 10
|
|
96
|
+
batchInterval?: number; // 默认 5000 ms
|
|
97
|
+
maxQueueSize?: number; // 默认 100
|
|
98
|
+
enableStorage?: boolean; // 默认 true(队列持久化)
|
|
99
|
+
storagePrefix?: string; // 默认 'logger_sdk'
|
|
100
|
+
enableRetry?: boolean; // 默认 true
|
|
101
|
+
maxRetries?: number; // 默认 3
|
|
102
|
+
retryDelay?: number; // 默认 1000 ms
|
|
103
|
+
retryBackoff?: boolean; // 默认 true(指数退避 + 0-30% 抖动,上限 30s)
|
|
127
104
|
}
|
|
128
105
|
```
|
|
129
106
|
|
|
130
|
-
###
|
|
131
|
-
|
|
132
|
-
记录事件日志。每条日志会自动生成唯一的 `logId`(UUID v4 格式)。
|
|
133
|
-
|
|
134
|
-
**参数:**
|
|
135
|
-
|
|
136
|
-
- `eventType`: 事件类型(`'error' | 'crash' | 'pageview' | 'custom'`)
|
|
137
|
-
- `message`: 摘要信息
|
|
138
|
-
- `traceId`: (可选) 追踪 ID,用于关联多个相关日志
|
|
139
|
-
- `options`: 可选配置
|
|
140
|
-
- `level?`: 日志级别(`'info' | 'warn' | 'error' | 'fatal'`),默认 `'info'`
|
|
141
|
-
- `stack?`: 堆栈信息
|
|
142
|
-
- `userId?`: 用户 ID
|
|
143
|
-
- `tags?`: 额外的结构化信息
|
|
144
|
-
|
|
145
|
-
**示例:**
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
// 记录错误
|
|
149
|
-
sdk.track('error', 'Failed to load resource', {
|
|
150
|
-
level: 'error',
|
|
151
|
-
stack: error.stack,
|
|
152
|
-
userId: '123',
|
|
153
|
-
tags: { resource: 'image.png' },
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// 记录带 traceId 的错误(用于关联多个日志)
|
|
157
|
-
sdk.track('error', 'API request failed', 'trace-xyz-789', {
|
|
158
|
-
level: 'error',
|
|
159
|
-
tags: { endpoint: '/api/users', statusCode: 500 },
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// 记录页面浏览
|
|
163
|
-
sdk.track('pageview', 'User viewed product page', {
|
|
164
|
-
level: 'info',
|
|
165
|
-
tags: { productId: 'P123' },
|
|
166
|
-
});
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### 日志 ID 和追踪 ID
|
|
170
|
-
|
|
171
|
-
- **logId**: 每条日志自动生成的唯一标识符(UUID v4 格式),用于全局唯一定位日志
|
|
172
|
-
- **traceId**: 可选的追踪 ID,用于关联同一请求链路上的多个日志(例如:前端请求、后端处理、数据库查询等)
|
|
107
|
+
### 事件上报
|
|
173
108
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
109
|
+
- `track(options: TrackOptions)`
|
|
110
|
+
- `message: string`(必填)
|
|
111
|
+
- `error?: Error`(推荐在错误场景传入)
|
|
112
|
+
- `traceId?: string`
|
|
113
|
+
- `logLevel?: 'info' | 'warn' | 'error' | 'fatal'`(默认 'info')
|
|
114
|
+
- `logId` 由 `appId + UUID + now()` 组成,保证唯一
|
|
115
|
+
- `identify(userId: string)` 设置用户标识(自动随事件上报)
|
|
116
|
+
- `setStoreCode(storeCode: string)` 设置店铺编码(自动随事件上报)
|
|
117
|
+
- `flush()` 在批量开启时立即上报队列内容
|
|
118
|
+
- `destroy()` 停止定时器与重试,刷新队列,清理单例并重置会话锁定
|
|
177
119
|
|
|
178
|
-
|
|
179
|
-
sdk.track('custom', 'Request started', traceId, {
|
|
180
|
-
level: 'info',
|
|
181
|
-
tags: { endpoint: '/api/checkout' },
|
|
182
|
-
});
|
|
120
|
+
### 自动采集
|
|
183
121
|
|
|
184
|
-
|
|
122
|
+
- 浏览器:visibilitychange/pagehide/beforeunload 触发 `flush()`,确保卸载时尽量发送
|
|
123
|
+
- 微信小程序:建议在 App 生命周期中调用(SDK 内部识别环境)
|
|
185
124
|
|
|
186
|
-
|
|
187
|
-
level: 'error',
|
|
188
|
-
tags: { endpoint: '/api/checkout', error: 'Network timeout' },
|
|
189
|
-
});
|
|
190
|
-
```
|
|
125
|
+
## 传输适配器
|
|
191
126
|
|
|
192
|
-
|
|
127
|
+
- 默认选择:
|
|
128
|
+
- 小程序:`wx.request`
|
|
129
|
+
- 浏览器:`navigator.sendBeacon` → 降级到 Image 像素
|
|
130
|
+
- Content-Type:
|
|
131
|
+
- Beacon:`application/json`;启用 gzip 时为 `application/json; charset=utf-8`
|
|
132
|
+
- 小程序:`application/json`;启用 gzip 时为 `application/json; charset=utf-8`
|
|
133
|
+
- Image:通过 query 拼接,受 URL 长度限制(默认 4096)
|
|
193
134
|
|
|
194
|
-
|
|
135
|
+
## 重试策略(实际实现)
|
|
195
136
|
|
|
196
|
-
|
|
137
|
+
- 启用时对单事件与批量发送采用统一重试
|
|
138
|
+
- 指数退避:`baseDelay * (2 ** (attempt - 1))`
|
|
139
|
+
- 抖动:`delay * [0, 0.3]`,最大不超过 30000ms
|
|
140
|
+
- 防重复:同一 taskId 重试中会拒绝重复执行
|
|
197
141
|
|
|
198
|
-
|
|
142
|
+
## 场景示例
|
|
199
143
|
|
|
200
144
|
```ts
|
|
201
|
-
|
|
202
|
-
throw new Error('Network Error');
|
|
203
|
-
} catch (e) {
|
|
204
|
-
await sdk.trace(e as Error, { userId: 'u123', traceId: 'req-1' });
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### `destroy()`
|
|
209
|
-
|
|
210
|
-
销毁 SDK 实例,停止所有监听。
|
|
211
|
-
|
|
212
|
-
销毁后单例会被清理;如需新会话,重新调用 `init()` 即可生成新的 sessionId。
|
|
213
|
-
|
|
214
|
-
### 会话管理
|
|
215
|
-
|
|
216
|
-
- 在 `init()` 时生成并锁定 `sessionId`
|
|
217
|
-
- 在调用 `destroy()` 前,所有日志都会使用该 `sessionId`
|
|
218
|
-
- 重新 `init()` 将开始新的会话(新的 `sessionId`)
|
|
219
|
-
|
|
220
|
-
## 自动采集
|
|
221
|
-
|
|
222
|
-
SDK 会自动监听以下页面事件并上报:
|
|
223
|
-
|
|
224
|
-
- **页面隐藏**(`visibilitychange`):当页面变为隐藏状态时
|
|
225
|
-
- **页面卸载**(`pagehide`, `beforeunload`):当用户离开页面时
|
|
226
|
-
|
|
227
|
-
这些事件使用 Beacon API 上报,确保在页面关闭时仍能成功发送。
|
|
228
|
-
|
|
229
|
-
## 上报方式
|
|
230
|
-
|
|
231
|
-
SDK 使用两种上报方式,按优先级自动选择:
|
|
232
|
-
|
|
233
|
-
### 1. Beacon API(优先)
|
|
234
|
-
|
|
235
|
-
- **兼容性**:Chrome 39+, Firefox 31+, Edge 14+
|
|
236
|
-
- **特点**:页面卸载时可靠传输,不阻塞页面关闭
|
|
237
|
-
- **限制**:无法获取响应,队列大小限制(通常 64KB)
|
|
238
|
-
|
|
239
|
-
### 2. Image 像素上报(降级)
|
|
240
|
-
|
|
241
|
-
- **兼容性**:所有浏览器
|
|
242
|
-
- **特点**:轻量级,无跨域限制
|
|
243
|
-
- **限制**:URL 长度限制(默认 1900 字符)
|
|
244
|
-
|
|
245
|
-
如果 Beacon 失败,会自动降级到 Image 方式。
|
|
246
|
-
|
|
247
|
-
### 微信小程序适配器
|
|
248
|
-
|
|
249
|
-
- 环境:微信小程序
|
|
250
|
-
- 支持:请求成功/失败/非 2xx 状态码与超时控制
|
|
251
|
-
- Header Content-Type 会根据是否启用 gzip 自动调整
|
|
252
|
-
|
|
253
|
-
## 使用场景
|
|
254
|
-
|
|
255
|
-
### 错误监控
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
// 全局错误捕获
|
|
145
|
+
// 错误监控(浏览器)
|
|
259
146
|
window.addEventListener('error', (event) => {
|
|
260
|
-
sdk.track(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
lineno: event.lineno,
|
|
266
|
-
colno: event.colno,
|
|
267
|
-
},
|
|
147
|
+
sdk.track({
|
|
148
|
+
message: event.message,
|
|
149
|
+
error: event.error,
|
|
150
|
+
logLevel: 'error',
|
|
151
|
+
traceId: `err-${Date.now()}`,
|
|
268
152
|
});
|
|
269
153
|
});
|
|
270
154
|
|
|
271
|
-
// Promise
|
|
155
|
+
// Promise 未捕获
|
|
272
156
|
window.addEventListener('unhandledrejection', (event) => {
|
|
273
|
-
sdk.track(
|
|
274
|
-
|
|
275
|
-
|
|
157
|
+
sdk.track({
|
|
158
|
+
message: 'Unhandled Promise Rejection',
|
|
159
|
+
error: new Error(String(event.reason)),
|
|
160
|
+
logLevel: 'error',
|
|
276
161
|
});
|
|
277
162
|
});
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### 页面浏览统计
|
|
281
163
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
path: window.location.pathname,
|
|
288
|
-
referrer: document.referrer,
|
|
289
|
-
},
|
|
164
|
+
// 页面浏览
|
|
165
|
+
sdk.track({
|
|
166
|
+
message: `Pageview: ${document.title}`,
|
|
167
|
+
logLevel: 'info',
|
|
168
|
+
traceId: `pv-${Date.now()}`,
|
|
290
169
|
});
|
|
291
170
|
```
|
|
292
171
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
// 记录用户点击
|
|
297
|
-
button.addEventListener('click', () => {
|
|
298
|
-
sdk.track('custom', 'Button clicked', {
|
|
299
|
-
level: 'info',
|
|
300
|
-
userId: currentUserId,
|
|
301
|
-
tags: {
|
|
302
|
-
buttonId: button.id,
|
|
303
|
-
page: 'checkout',
|
|
304
|
-
},
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
## 最佳实践
|
|
310
|
-
|
|
311
|
-
1. **设置正确的环境标识**:确保在不同环境(prod/stage/dev)使用正确的配置
|
|
312
|
-
2. **使用有意义的 message**:摘要信息应简洁明了,便于快速定位问题
|
|
313
|
-
3. **合理使用 tags**:将额外的结构化信息放在 tags 中,便于分析和过滤
|
|
314
|
-
4. **用户隐私保护**:userId 应该经过脱敏处理
|
|
315
|
-
5. **控制日志量**:避免在高频操作中记录过多日志
|
|
316
|
-
|
|
317
|
-
## 调试
|
|
318
|
-
|
|
319
|
-
开启调试模式查看控制台输出:
|
|
172
|
+
## 最佳实践与安全
|
|
320
173
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
debug: true, // 开启调试
|
|
325
|
-
});
|
|
326
|
-
```
|
|
174
|
+
- 初始化后统一设置用户与店铺信息(`identify`/`setStoreCode`)
|
|
175
|
+
- userId/message/stack/tags 建议在业务侧脱敏与裁剪
|
|
176
|
+
- 避免在 tags 中上传 cookie/localStorage 原始值、账户/手机号/身份证等敏感信息
|
|
327
177
|
|
|
328
|
-
##
|
|
329
|
-
|
|
330
|
-
### 批量上报
|
|
331
|
-
|
|
332
|
-
SDK 支持批量上报功能,可以显著减少网络请求次数,提高性能:
|
|
333
|
-
|
|
334
|
-
- **队列缓存**:日志先缓存到内存队列,达到条件后批量发送
|
|
335
|
-
- **智能触发**:支持按数量阈值和时间间隔触发上报
|
|
336
|
-
- **手动控制**:提供 `flush()` 方法可手动立即上报
|
|
337
|
-
|
|
338
|
-
### 异常重试
|
|
339
|
-
|
|
340
|
-
为确保日志可靠上报,SDK 提供了自动重试机制:
|
|
341
|
-
|
|
342
|
-
- **自动重试**:上报失败时自动重试(默认最多3次)
|
|
343
|
-
- **指数退避**:采用指数退避策略(1秒→2秒→4秒...)
|
|
344
|
-
- **随机抖动**:添加0-30%随机延迟避免惊群效应
|
|
345
|
-
|
|
346
|
-
### 持久化存储
|
|
347
|
-
|
|
348
|
-
为了防止因页面意外关闭导致日志丢失,SDK 支持持久化存储:
|
|
349
|
-
|
|
350
|
-
- **自动保存**:队列数据自动保存到 localStorage(浏览器)或 Storage(微信小程序)
|
|
351
|
-
- **自动恢复**:页面刷新后自动恢复未上报的日志
|
|
352
|
-
|
|
353
|
-
## 核心流程
|
|
354
|
-
|
|
355
|
-
```mermaid
|
|
356
|
-
graph TB
|
|
357
|
-
A[用户调用 track() 方法] --> B{SDK是否已销毁?}
|
|
358
|
-
B -- 是 --> C[直接返回,不处理]
|
|
359
|
-
B -- 否 --> D[生成标准化日志对象]
|
|
360
|
-
D --> E{是否启用批量上报?}
|
|
361
|
-
E -- 否 --> F[直接上报日志]
|
|
362
|
-
E -- 是 --> G[将日志加入队列]
|
|
363
|
-
G --> H{队列大小是否达到批处理阈值?}
|
|
364
|
-
H -- 是 --> I[立即触发批量上报]
|
|
365
|
-
H -- 否 --> J[等待下次触发]
|
|
366
|
-
|
|
367
|
-
F --> K{是否启用重试机制?}
|
|
368
|
-
K -- 是 --> L[使用重试管理器发送]
|
|
369
|
-
K -- 否 --> M[直接发送请求]
|
|
370
|
-
|
|
371
|
-
L --> N[重试管理器执行发送任务]
|
|
372
|
-
N --> O{发送是否成功?}
|
|
373
|
-
O -- 是 --> P[上报完成]
|
|
374
|
-
O -- 否 --> Q[是否达到最大重试次数?]
|
|
375
|
-
Q -- 否 --> R[计算延迟时间<br/>(指数退避+随机抖动)]
|
|
376
|
-
R --> S[等待后重试]
|
|
377
|
-
S --> N
|
|
378
|
-
Q -- 是 --> T[上报失败,记录错误]
|
|
379
|
-
|
|
380
|
-
M --> U{发送是否成功?}
|
|
381
|
-
U -- 是 --> P
|
|
382
|
-
U -- 否 --> T
|
|
383
|
-
|
|
384
|
-
I --> V[执行批量上报]
|
|
385
|
-
V --> W[从队列获取待发送日志]
|
|
386
|
-
W --> X[调用重试管理器发送批量日志]
|
|
387
|
-
X --> Y{批量发送是否成功?}
|
|
388
|
-
Y -- 是 --> Z[从队列中移除已发送日志]
|
|
389
|
-
Y -- 否 --> AA[保留队列中的日志,下次重试]
|
|
390
|
-
|
|
391
|
-
J --> AB{定时器是否触发?}
|
|
392
|
-
AB -- 是 --> AC[执行批量上报]
|
|
393
|
-
AB -- 否 --> AD{页面是否卸载?}
|
|
394
|
-
AD -- 是 --> AE[调用 flush() 方法上报所有日志]
|
|
395
|
-
|
|
396
|
-
subgraph 队列管理
|
|
397
|
-
AF[内存队列]
|
|
398
|
-
AG[持久化存储<br/>localStorage/Storage]
|
|
399
|
-
AF <--> AG
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
subgraph 传输适配器
|
|
403
|
-
AH[Beacon 适配器]
|
|
404
|
-
AI[Image 像素适配器]
|
|
405
|
-
AJ[微信小程序适配器]
|
|
406
|
-
AK[自动选择最佳适配器]
|
|
407
|
-
AH --> AK
|
|
408
|
-
AI --> AK
|
|
409
|
-
AJ --> AK
|
|
410
|
-
end
|
|
411
|
-
|
|
412
|
-
Z --> P
|
|
413
|
-
AA --> P
|
|
414
|
-
AC --> V
|
|
415
|
-
AE --> V
|
|
416
|
-
```
|
|
178
|
+
## 迁移指南(多实例 → 单例 + init)
|
|
417
179
|
|
|
418
|
-
|
|
180
|
+
- 统一在应用入口:`LoggerSDK.getInstance().init(opts)`
|
|
181
|
+
- 其他模块直接使用该单例进行 `track/trace/flush`
|
|
182
|
+
- 会话边界:登出/身份切换/子应用卸载时调用 `destroy()`,随后重新 `init()`
|
|
419
183
|
|
|
420
|
-
|
|
184
|
+
## 发布与类型构建
|
|
421
185
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
### 批量上报配置
|
|
445
|
-
|
|
446
|
-
```typescript
|
|
447
|
-
const sdk = new LoggerSDK({
|
|
448
|
-
endpoint: 'https://your-api.com/logs',
|
|
449
|
-
appId: 'my-app',
|
|
450
|
-
|
|
451
|
-
// 批量上报配置
|
|
452
|
-
enableBatch: true, // 启用批量上报
|
|
453
|
-
batchSize: 20, // 队列达到20条时批量上报
|
|
454
|
-
batchInterval: 10000, // 或每隔10秒上报一次
|
|
455
|
-
maxQueueSize: 100, // 队列最大100条日志
|
|
456
|
-
|
|
457
|
-
// 持久化存储配置
|
|
458
|
-
enableStorage: true, // 启用持久化存储
|
|
459
|
-
storagePrefix: 'my_app_logger',
|
|
460
|
-
});
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
### 重试机制配置
|
|
464
|
-
|
|
465
|
-
```typescript
|
|
466
|
-
const sdk = new LoggerSDK({
|
|
467
|
-
endpoint: 'https://your-api.com/logs',
|
|
468
|
-
appId: 'my-app',
|
|
469
|
-
|
|
470
|
-
// 重试配置
|
|
471
|
-
enableRetry: true, // 启用重试机制
|
|
472
|
-
maxRetries: 5, // 最多重试5次
|
|
473
|
-
retryDelay: 2000, // 基础延迟2秒
|
|
474
|
-
retryBackoff: true, // 启用指数退避
|
|
475
|
-
});
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
### 手动刷新队列
|
|
479
|
-
|
|
480
|
-
```typescript
|
|
481
|
-
// 立即上报所有待发送日志
|
|
482
|
-
await sdk.flush();
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
### 禁用批量上报(实时上报)
|
|
486
|
-
|
|
487
|
-
```typescript
|
|
488
|
-
const sdk = LoggerSDK.getInstance();
|
|
489
|
-
sdk.init({
|
|
490
|
-
endpoint: 'https://your-api.com/logs',
|
|
491
|
-
appId: 'my-app',
|
|
492
|
-
enableBatch: false, // 默认即为 false;每条日志立即发送
|
|
493
|
-
enableRetry: true,
|
|
494
|
-
});
|
|
495
|
-
```
|
|
186
|
+
- 多产物发布
|
|
187
|
+
- ESM:dist/esm(现代浏览器与打包器)
|
|
188
|
+
- CJS:dist/cjs(Node/工具链)
|
|
189
|
+
- UMD(压缩):dist/umd/logger-sdk.min.js(CDN/script 标签,全局 `LoggerSDK`)
|
|
190
|
+
- 包入口与导出
|
|
191
|
+
- main 指向 CJS,module 指向 ESM,browser 指向 ESM
|
|
192
|
+
- exports 同时声明 import/require/default,现代打包器自动选择
|
|
193
|
+
- unpkg/jsdelivr 指向 UMD 压缩产物
|
|
194
|
+
- tsconfig 策略
|
|
195
|
+
- tsconfig.base.json:通用编译选项(target、module、lib、skipLibCheck 等)
|
|
196
|
+
- tsconfig.json:仅类型检查(noEmit: true)
|
|
197
|
+
- tsconfig.types.json:仅声明构建(emitDeclarationOnly,declarationDir: dist/types)
|
|
198
|
+
- 脚本
|
|
199
|
+
- 类型检查:`yarn typecheck`
|
|
200
|
+
- 声明构建:`yarn build-types`
|
|
201
|
+
- 代码产物:`yarn build`
|
|
202
|
+
- 使用建议
|
|
203
|
+
- CDN:`https://unpkg.com/@pluve/logger-sdk/dist/umd/logger-sdk.min.js`,全局变量 `LoggerSDK`
|
|
204
|
+
- 打包器:优先使用 ESM(import { LoggerSDK } from '@pluve/logger-sdk')
|
|
496
205
|
|
|
497
|
-
##
|
|
206
|
+
## 其他
|
|
498
207
|
|
|
499
|
-
|
|
500
|
-
- 普通事件默认不合并环境标签,建议仅在必要时通过 `tags` 传入额外信息
|
|
501
|
-
- 推荐使用 `LoggerSDK.getInstance()` 获取单例,避免多实例重复初始化
|
|
208
|
+
生成 mermaid 图:`yarn generate-mermaid`
|