@pluve/logger-sdk 0.0.5 → 0.0.6
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.html +982 -0
- package/README.md +67 -16
- package/dist/loggerSDK.d.ts +13 -3
- package/dist/loggerSDK.js +132 -90
- package/dist/types.d.ts +2 -2
- package/dist/utils.js +51 -106
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,40 +10,46 @@
|
|
|
10
10
|
## 安装与引入
|
|
11
11
|
|
|
12
12
|
- 安装:`pnpm add @pluve/logger-sdk`
|
|
13
|
-
- ESM:`import
|
|
13
|
+
- ESM:`import LoggerSDK from '@pluve/logger-sdk'`
|
|
14
14
|
- UMD:构建后全局为 `LoggerSDK`
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## 快速开始(单例 + init)
|
|
17
17
|
|
|
18
18
|
```ts
|
|
19
|
-
import
|
|
19
|
+
import LoggerSDK from '@pluve/logger-sdk';
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
// 推荐使用单例
|
|
22
|
+
const sdk = LoggerSDK.getInstance();
|
|
23
|
+
sdk.init({
|
|
22
24
|
endpoint: '/api/log',
|
|
23
25
|
appId: 'web-shop',
|
|
24
26
|
env: 'prod', // prod/stage/dev
|
|
25
27
|
debug: true,
|
|
28
|
+
// 默认批量关闭,如需开启:
|
|
29
|
+
// enableBatch: true,
|
|
26
30
|
});
|
|
27
31
|
|
|
32
|
+
// init 会自动上报一次 'session_start',携带环境信息(UA/OS/屏幕等)
|
|
33
|
+
// 后续事件默认不再合并环境标签(节省流量)
|
|
34
|
+
|
|
28
35
|
// 记录错误日志
|
|
29
|
-
sdk.track('error', 'TypeError: Cannot read property', {
|
|
36
|
+
await sdk.track('error', 'TypeError: Cannot read property', undefined, {
|
|
30
37
|
level: 'error',
|
|
31
38
|
stack: 'Error stack trace...',
|
|
32
39
|
userId: '123',
|
|
33
40
|
tags: {
|
|
34
41
|
component: 'checkout',
|
|
35
|
-
browser: 'Chrome 120',
|
|
36
42
|
},
|
|
37
43
|
});
|
|
38
44
|
|
|
39
45
|
// 记录带 traceId 的错误(用于关联多个日志)
|
|
40
|
-
sdk.track('error', 'Request failed', 'trace-abc-123', {
|
|
46
|
+
await sdk.track('error', 'Request failed', 'trace-abc-123', {
|
|
41
47
|
level: 'error',
|
|
42
48
|
tags: { api: '/api/user' },
|
|
43
49
|
});
|
|
44
50
|
|
|
45
51
|
// 记录自定义事件
|
|
46
|
-
sdk.track('custom', 'User clicked button', {
|
|
52
|
+
await sdk.track('custom', 'User clicked button', undefined, {
|
|
47
53
|
level: 'info',
|
|
48
54
|
tags: { action: 'click', button: 'submit' },
|
|
49
55
|
});
|
|
@@ -57,7 +63,7 @@ sdk.track('custom', 'User clicked button', {
|
|
|
57
63
|
{
|
|
58
64
|
"logId": "550e8400-e29b-41d4-a716-446655440000", // 日志 ID(UUID v4)
|
|
59
65
|
"traceId": "trace-123456", // 可选:追踪 ID(用于关联多个日志)
|
|
60
|
-
"eventType": "error", // 固定:error/crash/pageview/custom
|
|
66
|
+
"eventType": "error", // 固定:error/crash/pageview/custom/session_start
|
|
61
67
|
"ts": 1690000000000, // 毫秒时间戳
|
|
62
68
|
"appId": "web-shop", // 应用标识
|
|
63
69
|
"env": "prod", // prod/stage/dev
|
|
@@ -76,23 +82,35 @@ sdk.track('custom', 'User clicked button', {
|
|
|
76
82
|
|
|
77
83
|
## API
|
|
78
84
|
|
|
79
|
-
###
|
|
85
|
+
### 单例与初始化
|
|
86
|
+
|
|
87
|
+
#### `LoggerSDK.getInstance(): LoggerSDK`
|
|
80
88
|
|
|
81
|
-
|
|
89
|
+
获取全局唯一实例。
|
|
90
|
+
|
|
91
|
+
#### `init(options: SDKOptions)`
|
|
92
|
+
|
|
93
|
+
初始化 SDK、生成并锁定 sessionId、收集环境信息并上报一次 `session_start`。
|
|
94
|
+
注意:锁定的 sessionId 将在销毁前用于所有日志上报。
|
|
95
|
+
|
|
96
|
+
#### `new LoggerSDK(options?: SDKOptions)`
|
|
97
|
+
|
|
98
|
+
创建 SDK 实例;如果传入 `options`,会在构造时自动调用 `init(options)`。
|
|
82
99
|
|
|
83
100
|
**配置项:**
|
|
84
101
|
|
|
85
102
|
```typescript
|
|
86
103
|
interface SDKOptions {
|
|
87
104
|
endpoint: string; // 上报端点 URL(必选)
|
|
88
|
-
appId
|
|
105
|
+
appId: string; // 应用 ID(必选)
|
|
89
106
|
env?: Env; // 环境标识:prod/stage/dev,默认 'dev'
|
|
90
107
|
debug?: boolean; // 是否开启调试模式
|
|
91
108
|
pixelParam?: string; // 像素上报参数名,默认 'data'
|
|
92
109
|
maxPixelUrlLen?: number; // 像素上报 URL 最大长度,默认 1900
|
|
110
|
+
enableGzip?: boolean; // 是否启用 gzip(传输适配器内部处理)
|
|
93
111
|
|
|
94
112
|
// 批量上报配置
|
|
95
|
-
enableBatch?: boolean; // 是否启用批量上报,默认
|
|
113
|
+
enableBatch?: boolean; // 是否启用批量上报,默认 false(需显式开启)
|
|
96
114
|
batchSize?: number; // 批量上报最大数量,默认 10
|
|
97
115
|
batchInterval?: number; // 批量上报时间间隔(毫秒),默认 5000
|
|
98
116
|
maxQueueSize?: number; // 队列最大长度,默认 100
|
|
@@ -175,10 +193,30 @@ sdk.track('error', 'Request failed', traceId, {
|
|
|
175
193
|
|
|
176
194
|
设置用户 ID(用于后续日志关联)。
|
|
177
195
|
|
|
196
|
+
### `trace(error: Error | string, options?)`
|
|
197
|
+
|
|
198
|
+
错误专用方法,自动设置 `eventType: 'error'` 与 `level: 'error'`,不合并环境标签。
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
try {
|
|
202
|
+
throw new Error('Network Error');
|
|
203
|
+
} catch (e) {
|
|
204
|
+
await sdk.trace(e as Error, { userId: 'u123', traceId: 'req-1' });
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
178
208
|
### `destroy()`
|
|
179
209
|
|
|
180
210
|
销毁 SDK 实例,停止所有监听。
|
|
181
211
|
|
|
212
|
+
销毁后单例会被清理;如需新会话,重新调用 `init()` 即可生成新的 sessionId。
|
|
213
|
+
|
|
214
|
+
### 会话管理
|
|
215
|
+
|
|
216
|
+
- 在 `init()` 时生成并锁定 `sessionId`
|
|
217
|
+
- 在调用 `destroy()` 前,所有日志都会使用该 `sessionId`
|
|
218
|
+
- 重新 `init()` 将开始新的会话(新的 `sessionId`)
|
|
219
|
+
|
|
182
220
|
## 自动采集
|
|
183
221
|
|
|
184
222
|
SDK 会自动监听以下页面事件并上报:
|
|
@@ -206,6 +244,12 @@ SDK 使用两种上报方式,按优先级自动选择:
|
|
|
206
244
|
|
|
207
245
|
如果 Beacon 失败,会自动降级到 Image 方式。
|
|
208
246
|
|
|
247
|
+
### 微信小程序适配器
|
|
248
|
+
|
|
249
|
+
- 环境:微信小程序
|
|
250
|
+
- 支持:请求成功/失败/非 2xx 状态码与超时控制
|
|
251
|
+
- Header Content-Type 会根据是否启用 gzip 自动调整
|
|
252
|
+
|
|
209
253
|
## 使用场景
|
|
210
254
|
|
|
211
255
|
### 错误监控
|
|
@@ -441,10 +485,17 @@ await sdk.flush();
|
|
|
441
485
|
### 禁用批量上报(实时上报)
|
|
442
486
|
|
|
443
487
|
```typescript
|
|
444
|
-
const sdk =
|
|
488
|
+
const sdk = LoggerSDK.getInstance();
|
|
489
|
+
sdk.init({
|
|
445
490
|
endpoint: 'https://your-api.com/logs',
|
|
446
491
|
appId: 'my-app',
|
|
447
|
-
enableBatch: false,
|
|
448
|
-
enableRetry: true,
|
|
492
|
+
enableBatch: false, // 默认即为 false;每条日志立即发送
|
|
493
|
+
enableRetry: true,
|
|
449
494
|
});
|
|
450
495
|
```
|
|
496
|
+
|
|
497
|
+
## 重要说明
|
|
498
|
+
|
|
499
|
+
- `init()` 会自动上报 `session_start`,携带环境信息标签(仅此一次)
|
|
500
|
+
- 普通事件默认不合并环境标签,建议仅在必要时通过 `tags` 传入额外信息
|
|
501
|
+
- 推荐使用 `LoggerSDK.getInstance()` 获取单例,避免多实例重复初始化
|
package/dist/loggerSDK.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { SDKOptions, LogEventType, LogEventLevel } from './types';
|
|
2
2
|
export declare class LoggerSDK {
|
|
3
|
-
private
|
|
3
|
+
private static instance;
|
|
4
|
+
private opts?;
|
|
4
5
|
private seq;
|
|
5
6
|
private closed;
|
|
6
|
-
/** 预收集的环境信息 tags */
|
|
7
|
+
/** 预收集的环境信息 tags(仅用于初始化上报) */
|
|
7
8
|
private envTags;
|
|
9
|
+
/** 是否已初始化 */
|
|
10
|
+
private initialized;
|
|
11
|
+
/** 初始化时生成并锁定的会话标识 */
|
|
12
|
+
private sessionId;
|
|
8
13
|
/** 队列管理器 */
|
|
9
14
|
private queueManager?;
|
|
10
15
|
/** 重试管理器 */
|
|
@@ -13,7 +18,12 @@ export declare class LoggerSDK {
|
|
|
13
18
|
private batchTimer?;
|
|
14
19
|
/** 是否正在上报 */
|
|
15
20
|
private isSending;
|
|
16
|
-
constructor(options
|
|
21
|
+
constructor(options?: SDKOptions);
|
|
22
|
+
static getInstance(): LoggerSDK;
|
|
23
|
+
/**
|
|
24
|
+
* 初始化:配置参数、收集环境信息与 UA,并生成 sessionId,完成初始上报
|
|
25
|
+
*/
|
|
26
|
+
init(options: SDKOptions): void;
|
|
17
27
|
private logDebug;
|
|
18
28
|
/**
|
|
19
29
|
* 收集环境信息并生成 tags(仅在初始化时执行一次)
|
package/dist/loggerSDK.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
2
|
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
3
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
3
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
6
4
|
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
7
5
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
@@ -20,8 +18,12 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
20
18
|
_defineProperty(this, "opts", void 0);
|
|
21
19
|
_defineProperty(this, "seq", 0);
|
|
22
20
|
_defineProperty(this, "closed", false);
|
|
23
|
-
/** 预收集的环境信息 tags */
|
|
24
|
-
_defineProperty(this, "envTags",
|
|
21
|
+
/** 预收集的环境信息 tags(仅用于初始化上报) */
|
|
22
|
+
_defineProperty(this, "envTags", {});
|
|
23
|
+
/** 是否已初始化 */
|
|
24
|
+
_defineProperty(this, "initialized", false);
|
|
25
|
+
/** 初始化时生成并锁定的会话标识 */
|
|
26
|
+
_defineProperty(this, "sessionId", void 0);
|
|
25
27
|
/** 队列管理器 */
|
|
26
28
|
_defineProperty(this, "queueManager", void 0);
|
|
27
29
|
/** 重试管理器 */
|
|
@@ -30,71 +32,92 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
30
32
|
_defineProperty(this, "batchTimer", void 0);
|
|
31
33
|
/** 是否正在上报 */
|
|
32
34
|
_defineProperty(this, "isSending", false);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
35
|
+
if (options) {
|
|
36
|
+
this.init(options);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
_createClass(LoggerSDK, [{
|
|
40
|
+
key: "init",
|
|
41
|
+
value:
|
|
42
|
+
/**
|
|
43
|
+
* 初始化:配置参数、收集环境信息与 UA,并生成 sessionId,完成初始上报
|
|
44
|
+
*/
|
|
45
|
+
function init(options) {
|
|
46
|
+
var _this = this;
|
|
47
|
+
this.opts = {
|
|
48
|
+
endpoint: options.endpoint,
|
|
49
|
+
appId: options.appId || 'unknown',
|
|
50
|
+
env: options.env || 'dev',
|
|
51
|
+
debug: !!options.debug,
|
|
52
|
+
pixelParam: options.pixelParam || 'data',
|
|
53
|
+
maxPixelUrlLen: options.maxPixelUrlLen || 1900,
|
|
54
|
+
enableGzip: !!options.enableGzip,
|
|
55
|
+
// 批量上报配置(默认关闭,需显式开启)
|
|
56
|
+
enableBatch: options.enableBatch === true,
|
|
57
|
+
batchSize: options.batchSize || 10,
|
|
58
|
+
batchInterval: options.batchInterval || 5000,
|
|
59
|
+
maxQueueSize: options.maxQueueSize || 100,
|
|
60
|
+
// 持久化存储配置
|
|
61
|
+
enableStorage: options.enableStorage !== false,
|
|
62
|
+
// 默认启用
|
|
63
|
+
storagePrefix: options.storagePrefix || 'logger_sdk',
|
|
64
|
+
// 重试配置
|
|
65
|
+
enableRetry: options.enableRetry !== false,
|
|
66
|
+
// 默认启用
|
|
67
|
+
maxRetries: options.maxRetries || 3,
|
|
68
|
+
retryDelay: options.retryDelay || 1000,
|
|
69
|
+
retryBackoff: options.retryBackoff !== false // 默认启用
|
|
70
|
+
};
|
|
58
71
|
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
// 初始化队列管理器
|
|
73
|
+
if (this.opts.enableBatch) {
|
|
74
|
+
this.queueManager = new QueueManager({
|
|
75
|
+
maxSize: this.opts.maxQueueSize,
|
|
76
|
+
enableStorage: this.opts.enableStorage,
|
|
77
|
+
storagePrefix: this.opts.storagePrefix,
|
|
78
|
+
debug: this.opts.debug
|
|
79
|
+
});
|
|
80
|
+
}
|
|
61
81
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
// 初始化重试管理器
|
|
83
|
+
if (this.opts.enableRetry) {
|
|
84
|
+
this.retryManager = new RetryManager({
|
|
85
|
+
maxRetries: this.opts.maxRetries,
|
|
86
|
+
baseDelay: this.opts.retryDelay,
|
|
87
|
+
useBackoff: this.opts.retryBackoff,
|
|
88
|
+
debug: this.opts.debug
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 监听页面卸载事件
|
|
93
|
+
this.attachUnloadHandlers();
|
|
94
|
+
|
|
95
|
+
// 生成并缓存 sessionId(便于 UV 统计),并锁定到实例生命周期
|
|
96
|
+
this.sessionId = getSessionId();
|
|
71
97
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
98
|
+
// 收集 UA / 环境信息并完成初始上报(便于后端统计 UA 和 UV)
|
|
99
|
+
this.envTags = this.collectEnvironmentTags();
|
|
100
|
+
this.track('session_start', 'Session started', undefined, {
|
|
101
|
+
level: 'info',
|
|
102
|
+
tags: this.envTags
|
|
103
|
+
}).catch(function (err) {
|
|
104
|
+
_this.logDebug('Failed to report session_start', err);
|
|
79
105
|
});
|
|
80
|
-
}
|
|
81
106
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
107
|
+
// 启动批量上报定时器
|
|
108
|
+
if (this.opts.enableBatch) {
|
|
109
|
+
this.startBatchTimer();
|
|
110
|
+
}
|
|
111
|
+
this.initialized = true;
|
|
85
112
|
}
|
|
86
|
-
|
|
87
|
-
// 监听页面卸载事件
|
|
88
|
-
this.attachUnloadHandlers();
|
|
89
|
-
}
|
|
90
|
-
_createClass(LoggerSDK, [{
|
|
113
|
+
}, {
|
|
91
114
|
key: "logDebug",
|
|
92
115
|
value: function logDebug() {
|
|
93
|
-
var _console;
|
|
116
|
+
var _this$opts, _console;
|
|
94
117
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
95
118
|
args[_key] = arguments[_key];
|
|
96
119
|
}
|
|
97
|
-
if (this.opts.debug) (_console = console).debug.apply(_console, ['[LoggerSDK]'].concat(args));
|
|
120
|
+
if ((_this$opts = this.opts) !== null && _this$opts !== void 0 && _this$opts.debug) (_console = console).debug.apply(_console, ['[LoggerSDK]'].concat(args));
|
|
98
121
|
}
|
|
99
122
|
|
|
100
123
|
/**
|
|
@@ -151,6 +174,13 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
151
174
|
}
|
|
152
175
|
return _context.abrupt("return");
|
|
153
176
|
case 2:
|
|
177
|
+
if (this.initialized) {
|
|
178
|
+
_context.next = 5;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
this.logDebug('SDK not initialized, skip track');
|
|
182
|
+
return _context.abrupt("return");
|
|
183
|
+
case 5:
|
|
154
184
|
this.seq += 1;
|
|
155
185
|
|
|
156
186
|
// 构建标准化日志格式
|
|
@@ -167,46 +197,46 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
167
197
|
stack: options === null || options === void 0 ? void 0 : options.stack,
|
|
168
198
|
url: getCurrentUrl(),
|
|
169
199
|
userId: options === null || options === void 0 ? void 0 : options.userId,
|
|
170
|
-
sessionId:
|
|
171
|
-
//
|
|
172
|
-
tags:
|
|
200
|
+
sessionId: this.sessionId,
|
|
201
|
+
// 单次事件只携带自定义 tags,不再包含环境数据,节省流量
|
|
202
|
+
tags: (options === null || options === void 0 ? void 0 : options.tags) || {}
|
|
173
203
|
};
|
|
174
204
|
this.logDebug('track', logEvent);
|
|
175
205
|
|
|
176
206
|
// 如果启用批量上报,添加到队列
|
|
177
207
|
if (!(this.opts.enableBatch && this.queueManager)) {
|
|
178
|
-
_context.next =
|
|
208
|
+
_context.next = 16;
|
|
179
209
|
break;
|
|
180
210
|
}
|
|
181
211
|
this.queueManager.enqueue(logEvent);
|
|
182
212
|
// 如果队列已满,立即上报
|
|
183
213
|
if (!(this.queueManager.size() >= this.opts.batchSize)) {
|
|
184
|
-
_context.next =
|
|
214
|
+
_context.next = 14;
|
|
185
215
|
break;
|
|
186
216
|
}
|
|
187
217
|
this.logDebug('Queue size reached batch size, flushing immediately');
|
|
188
|
-
_context.next =
|
|
218
|
+
_context.next = 14;
|
|
189
219
|
return this.flush();
|
|
190
|
-
case
|
|
191
|
-
_context.next =
|
|
220
|
+
case 14:
|
|
221
|
+
_context.next = 24;
|
|
192
222
|
break;
|
|
193
|
-
case 13:
|
|
194
|
-
_context.prev = 13;
|
|
195
|
-
_context.next = 16;
|
|
196
|
-
return this.sendEvent(logEvent);
|
|
197
223
|
case 16:
|
|
198
|
-
_context.
|
|
224
|
+
_context.prev = 16;
|
|
225
|
+
_context.next = 19;
|
|
226
|
+
return this.sendEvent(logEvent);
|
|
227
|
+
case 19:
|
|
228
|
+
_context.next = 24;
|
|
199
229
|
break;
|
|
200
|
-
case
|
|
201
|
-
_context.prev =
|
|
202
|
-
_context.t0 = _context["catch"](
|
|
230
|
+
case 21:
|
|
231
|
+
_context.prev = 21;
|
|
232
|
+
_context.t0 = _context["catch"](16);
|
|
203
233
|
this.logDebug('track failed', _context.t0);
|
|
204
234
|
// 静默失败,不影响主流程
|
|
205
|
-
case
|
|
235
|
+
case 24:
|
|
206
236
|
case "end":
|
|
207
237
|
return _context.stop();
|
|
208
238
|
}
|
|
209
|
-
}, _callee, this, [[
|
|
239
|
+
}, _callee, this, [[16, 21]]);
|
|
210
240
|
}));
|
|
211
241
|
function track(_x, _x2, _x3, _x4) {
|
|
212
242
|
return _track.apply(this, arguments);
|
|
@@ -317,7 +347,10 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
317
347
|
if (this.retryManager) {
|
|
318
348
|
this.retryManager.clear();
|
|
319
349
|
}
|
|
320
|
-
|
|
350
|
+
this.initialized = false;
|
|
351
|
+
this.sessionId = undefined;
|
|
352
|
+
LoggerSDK.instance = undefined;
|
|
353
|
+
case 9:
|
|
321
354
|
case "end":
|
|
322
355
|
return _context3.stop();
|
|
323
356
|
}
|
|
@@ -336,7 +369,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
336
369
|
key: "sendEvent",
|
|
337
370
|
value: function () {
|
|
338
371
|
var _sendEvent = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(event) {
|
|
339
|
-
var
|
|
372
|
+
var _this2 = this;
|
|
340
373
|
var sendFn;
|
|
341
374
|
return _regeneratorRuntime().wrap(function _callee5$(_context5) {
|
|
342
375
|
while (1) switch (_context5.prev = _context5.next) {
|
|
@@ -347,7 +380,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
347
380
|
while (1) switch (_context4.prev = _context4.next) {
|
|
348
381
|
case 0:
|
|
349
382
|
_context4.next = 2;
|
|
350
|
-
return defaultTransport(event,
|
|
383
|
+
return defaultTransport(event, _this2.opts);
|
|
351
384
|
case 2:
|
|
352
385
|
case "end":
|
|
353
386
|
return _context4.stop();
|
|
@@ -388,7 +421,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
388
421
|
key: "sendBatch",
|
|
389
422
|
value: (function () {
|
|
390
423
|
var _sendBatch = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(events) {
|
|
391
|
-
var
|
|
424
|
+
var _this3 = this;
|
|
392
425
|
var batchId, sendFn;
|
|
393
426
|
return _regeneratorRuntime().wrap(function _callee7$(_context7) {
|
|
394
427
|
while (1) switch (_context7.prev = _context7.next) {
|
|
@@ -407,7 +440,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
407
440
|
while (1) switch (_context6.prev = _context6.next) {
|
|
408
441
|
case 0:
|
|
409
442
|
_context6.next = 2;
|
|
410
|
-
return defaultTransport(events,
|
|
443
|
+
return defaultTransport(events, _this3.opts);
|
|
411
444
|
case 2:
|
|
412
445
|
case "end":
|
|
413
446
|
return _context6.stop();
|
|
@@ -448,13 +481,13 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
448
481
|
}, {
|
|
449
482
|
key: "startBatchTimer",
|
|
450
483
|
value: function startBatchTimer() {
|
|
451
|
-
var
|
|
484
|
+
var _this4 = this;
|
|
452
485
|
if (this.batchTimer) return;
|
|
453
486
|
this.batchTimer = setInterval(function () {
|
|
454
|
-
if (!
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
487
|
+
if (!_this4.closed && _this4.queueManager && _this4.queueManager.size() > 0) {
|
|
488
|
+
_this4.logDebug('Batch timer triggered, flushing queue');
|
|
489
|
+
_this4.flush().catch(function (error) {
|
|
490
|
+
_this4.logDebug('Batch timer flush failed', error);
|
|
458
491
|
});
|
|
459
492
|
}
|
|
460
493
|
}, this.opts.batchInterval);
|
|
@@ -469,7 +502,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
469
502
|
}, {
|
|
470
503
|
key: "attachUnloadHandlers",
|
|
471
504
|
value: function attachUnloadHandlers() {
|
|
472
|
-
var
|
|
505
|
+
var _this5 = this;
|
|
473
506
|
// 微信小程序环境
|
|
474
507
|
if (isWeChatMiniProgram()) {
|
|
475
508
|
// 微信小程序使用 App 生命周期
|
|
@@ -487,7 +520,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
487
520
|
try {
|
|
488
521
|
if (document.visibilityState === 'hidden') {
|
|
489
522
|
// 页面隐藏时刷新队列
|
|
490
|
-
|
|
523
|
+
_this5.flush().catch(function () {
|
|
491
524
|
// 忽略错误
|
|
492
525
|
});
|
|
493
526
|
console.log('Page hidden, flushed queue');
|
|
@@ -501,7 +534,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
501
534
|
win.addEventListener && win.addEventListener('pagehide', function () {
|
|
502
535
|
try {
|
|
503
536
|
// 页面隐藏时刷新队列(同步)
|
|
504
|
-
|
|
537
|
+
_this5.flush().catch(function () {
|
|
505
538
|
// 忽略错误
|
|
506
539
|
});
|
|
507
540
|
console.log('Page hide, flushed queue');
|
|
@@ -514,7 +547,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
514
547
|
win.addEventListener && win.addEventListener('beforeunload', function () {
|
|
515
548
|
try {
|
|
516
549
|
// 页面卸载前刷新队列(同步)
|
|
517
|
-
|
|
550
|
+
_this5.flush().catch(function () {
|
|
518
551
|
// 忽略错误
|
|
519
552
|
});
|
|
520
553
|
console.log('Page unload, flushed queue');
|
|
@@ -523,9 +556,18 @@ export var LoggerSDK = /*#__PURE__*/function () {
|
|
|
523
556
|
}
|
|
524
557
|
});
|
|
525
558
|
}
|
|
559
|
+
}], [{
|
|
560
|
+
key: "getInstance",
|
|
561
|
+
value: function getInstance() {
|
|
562
|
+
if (!LoggerSDK.instance) {
|
|
563
|
+
LoggerSDK.instance = new LoggerSDK();
|
|
564
|
+
}
|
|
565
|
+
return LoggerSDK.instance;
|
|
566
|
+
}
|
|
526
567
|
}]);
|
|
527
568
|
return LoggerSDK;
|
|
528
569
|
}();
|
|
529
570
|
|
|
530
571
|
// 兼容导出(UMD/ESM)
|
|
572
|
+
_defineProperty(LoggerSDK, "instance", void 0);
|
|
531
573
|
export default LoggerSDK;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** 环境类型 */
|
|
2
2
|
export type Env = 'prod' | 'stage' | 'dev';
|
|
3
3
|
/** 事件类型 */
|
|
4
|
-
export type LogEventType = 'error' | 'crash' | 'pageview' | 'custom';
|
|
4
|
+
export type LogEventType = 'error' | 'crash' | 'pageview' | 'custom' | 'session_start';
|
|
5
5
|
/** 日志级别 */
|
|
6
6
|
export type LogEventLevel = 'info' | 'warn' | 'error' | 'fatal';
|
|
7
7
|
/** SDK 配置选项 */
|
|
@@ -45,7 +45,7 @@ export interface SDKOptions {
|
|
|
45
45
|
export interface LogEvent {
|
|
46
46
|
logId: string;
|
|
47
47
|
traceId?: string;
|
|
48
|
-
/** 事件类型:error/crash/pageview/custom */
|
|
48
|
+
/** 事件类型:error/crash/pageview/custom/session_start */
|
|
49
49
|
eventType: LogEventType;
|
|
50
50
|
/** 毫秒时间戳 */
|
|
51
51
|
ts: number;
|