@pluve/logger-sdk 0.0.4 → 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/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"); } }
@@ -12,38 +10,114 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
12
10
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
13
11
  import { defaultTransport } from "./transportAdapter";
14
12
  import { isBrowser, isWeChatMiniProgram, now, getSessionId, getCurrentUrl, getEnvironmentInfo, parseBrowserInfo, generateUUID } from "./utils";
13
+ import { QueueManager } from "./queueManager";
14
+ import { RetryManager } from "./retryManager";
15
15
  export var LoggerSDK = /*#__PURE__*/function () {
16
16
  function LoggerSDK(options) {
17
17
  _classCallCheck(this, LoggerSDK);
18
18
  _defineProperty(this, "opts", void 0);
19
19
  _defineProperty(this, "seq", 0);
20
20
  _defineProperty(this, "closed", false);
21
- /** 预收集的环境信息 tags */
22
- _defineProperty(this, "envTags", void 0);
23
- this.opts = {
24
- endpoint: options.endpoint,
25
- appId: options.appId || 'unknown',
26
- env: options.env || 'dev',
27
- debug: !!options.debug,
28
- pixelParam: options.pixelParam || 'data',
29
- maxPixelUrlLen: options.maxPixelUrlLen || 1900,
30
- enableGzip: !!options.enableGzip
31
- };
32
-
33
- // 初始化时收集环境信息
34
- this.envTags = this.collectEnvironmentTags();
35
-
36
- // 监听页面卸载事件
37
- this.attachUnloadHandlers();
21
+ /** 预收集的环境信息 tags(仅用于初始化上报) */
22
+ _defineProperty(this, "envTags", {});
23
+ /** 是否已初始化 */
24
+ _defineProperty(this, "initialized", false);
25
+ /** 初始化时生成并锁定的会话标识 */
26
+ _defineProperty(this, "sessionId", void 0);
27
+ /** 队列管理器 */
28
+ _defineProperty(this, "queueManager", void 0);
29
+ /** 重试管理器 */
30
+ _defineProperty(this, "retryManager", void 0);
31
+ /** 批量上报定时器 */
32
+ _defineProperty(this, "batchTimer", void 0);
33
+ /** 是否正在上报 */
34
+ _defineProperty(this, "isSending", false);
35
+ if (options) {
36
+ this.init(options);
37
+ }
38
38
  }
39
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
+ };
71
+
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
+ }
81
+
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();
97
+
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);
105
+ });
106
+
107
+ // 启动批量上报定时器
108
+ if (this.opts.enableBatch) {
109
+ this.startBatchTimer();
110
+ }
111
+ this.initialized = true;
112
+ }
113
+ }, {
40
114
  key: "logDebug",
41
115
  value: function logDebug() {
42
- var _console;
116
+ var _this$opts, _console;
43
117
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
44
118
  args[_key] = arguments[_key];
45
119
  }
46
- 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));
47
121
  }
48
122
 
49
123
  /**
@@ -100,6 +174,13 @@ export var LoggerSDK = /*#__PURE__*/function () {
100
174
  }
101
175
  return _context.abrupt("return");
102
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:
103
184
  this.seq += 1;
104
185
 
105
186
  // 构建标准化日志格式
@@ -116,27 +197,46 @@ export var LoggerSDK = /*#__PURE__*/function () {
116
197
  stack: options === null || options === void 0 ? void 0 : options.stack,
117
198
  url: getCurrentUrl(),
118
199
  userId: options === null || options === void 0 ? void 0 : options.userId,
119
- sessionId: getSessionId(),
120
- // 合并预收集的环境 tags 和用户自定义 tags
121
- tags: _objectSpread(_objectSpread({}, this.envTags), (options === null || options === void 0 ? void 0 : options.tags) || {})
200
+ sessionId: this.sessionId,
201
+ // 单次事件只携带自定义 tags,不再包含环境数据,节省流量
202
+ tags: (options === null || options === void 0 ? void 0 : options.tags) || {}
122
203
  };
123
204
  this.logDebug('track', logEvent);
124
- _context.prev = 5;
125
- _context.next = 8;
126
- return defaultTransport(logEvent, this.opts);
127
- case 8:
128
- _context.next = 13;
205
+
206
+ // 如果启用批量上报,添加到队列
207
+ if (!(this.opts.enableBatch && this.queueManager)) {
208
+ _context.next = 16;
209
+ break;
210
+ }
211
+ this.queueManager.enqueue(logEvent);
212
+ // 如果队列已满,立即上报
213
+ if (!(this.queueManager.size() >= this.opts.batchSize)) {
214
+ _context.next = 14;
215
+ break;
216
+ }
217
+ this.logDebug('Queue size reached batch size, flushing immediately');
218
+ _context.next = 14;
219
+ return this.flush();
220
+ case 14:
221
+ _context.next = 24;
222
+ break;
223
+ case 16:
224
+ _context.prev = 16;
225
+ _context.next = 19;
226
+ return this.sendEvent(logEvent);
227
+ case 19:
228
+ _context.next = 24;
129
229
  break;
130
- case 10:
131
- _context.prev = 10;
132
- _context.t0 = _context["catch"](5);
230
+ case 21:
231
+ _context.prev = 21;
232
+ _context.t0 = _context["catch"](16);
133
233
  this.logDebug('track failed', _context.t0);
134
234
  // 静默失败,不影响主流程
135
- case 13:
235
+ case 24:
136
236
  case "end":
137
237
  return _context.stop();
138
238
  }
139
- }, _callee, this, [[5, 10]]);
239
+ }, _callee, this, [[16, 21]]);
140
240
  }));
141
241
  function track(_x, _x2, _x3, _x4) {
142
242
  return _track.apply(this, arguments);
@@ -154,13 +254,244 @@ export var LoggerSDK = /*#__PURE__*/function () {
154
254
  // userId 将在 track 时传入
155
255
  }
156
256
 
257
+ /**
258
+ * 手动刷新队列,立即上报所有待发送日志
259
+ */
260
+ }, {
261
+ key: "flush",
262
+ value: (function () {
263
+ var _flush = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
264
+ var events;
265
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
266
+ while (1) switch (_context2.prev = _context2.next) {
267
+ case 0:
268
+ if (!(!this.queueManager || this.queueManager.size() === 0)) {
269
+ _context2.next = 2;
270
+ break;
271
+ }
272
+ return _context2.abrupt("return");
273
+ case 2:
274
+ if (!this.isSending) {
275
+ _context2.next = 5;
276
+ break;
277
+ }
278
+ this.logDebug('Already sending, skip flush');
279
+ return _context2.abrupt("return");
280
+ case 5:
281
+ this.isSending = true;
282
+ this.logDebug("Flushing ".concat(this.queueManager.size(), " events"));
283
+ _context2.prev = 7;
284
+ // 获取所有待发送的日志(不移除)
285
+ events = this.queueManager.peek(this.queueManager.size());
286
+ if (!(events.length === 0)) {
287
+ _context2.next = 11;
288
+ break;
289
+ }
290
+ return _context2.abrupt("return");
291
+ case 11:
292
+ _context2.next = 13;
293
+ return this.sendBatch(events);
294
+ case 13:
295
+ // 发送成功后,从队列中移除
296
+ this.queueManager.dequeue(events.length);
297
+ this.logDebug("Flushed ".concat(events.length, " events successfully"));
298
+ _context2.next = 20;
299
+ break;
300
+ case 17:
301
+ _context2.prev = 17;
302
+ _context2.t0 = _context2["catch"](7);
303
+ this.logDebug('Flush failed', _context2.t0);
304
+ // 失败不移除队列,下次继续重试
305
+ case 20:
306
+ _context2.prev = 20;
307
+ this.isSending = false;
308
+ return _context2.finish(20);
309
+ case 23:
310
+ case "end":
311
+ return _context2.stop();
312
+ }
313
+ }, _callee2, this, [[7, 17, 20, 23]]);
314
+ }));
315
+ function flush() {
316
+ return _flush.apply(this, arguments);
317
+ }
318
+ return flush;
319
+ }()
157
320
  /**
158
321
  * 销毁实例
159
322
  */
323
+ )
160
324
  }, {
161
325
  key: "destroy",
162
- value: function destroy() {
163
- this.closed = true;
326
+ value: (function () {
327
+ var _destroy = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
328
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
329
+ while (1) switch (_context3.prev = _context3.next) {
330
+ case 0:
331
+ this.closed = true;
332
+
333
+ // 停止批量上报定时器
334
+ if (this.batchTimer) {
335
+ clearInterval(this.batchTimer);
336
+ this.batchTimer = null;
337
+ }
338
+
339
+ // 刷新队列
340
+ _context3.next = 4;
341
+ return this.flush();
342
+ case 4:
343
+ // 清理资源
344
+ if (this.queueManager) {
345
+ this.queueManager.clear();
346
+ }
347
+ if (this.retryManager) {
348
+ this.retryManager.clear();
349
+ }
350
+ this.initialized = false;
351
+ this.sessionId = undefined;
352
+ LoggerSDK.instance = undefined;
353
+ case 9:
354
+ case "end":
355
+ return _context3.stop();
356
+ }
357
+ }, _callee3, this);
358
+ }));
359
+ function destroy() {
360
+ return _destroy.apply(this, arguments);
361
+ }
362
+ return destroy;
363
+ }() // ========== 内部方法 ===========
364
+ /**
365
+ * 发送单个事件(带重试)
366
+ */
367
+ )
368
+ }, {
369
+ key: "sendEvent",
370
+ value: function () {
371
+ var _sendEvent = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(event) {
372
+ var _this2 = this;
373
+ var sendFn;
374
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
375
+ while (1) switch (_context5.prev = _context5.next) {
376
+ case 0:
377
+ sendFn = /*#__PURE__*/function () {
378
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
379
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
380
+ while (1) switch (_context4.prev = _context4.next) {
381
+ case 0:
382
+ _context4.next = 2;
383
+ return defaultTransport(event, _this2.opts);
384
+ case 2:
385
+ case "end":
386
+ return _context4.stop();
387
+ }
388
+ }, _callee4);
389
+ }));
390
+ return function sendFn() {
391
+ return _ref.apply(this, arguments);
392
+ };
393
+ }(); // 如果启用重试
394
+ if (!(this.opts.enableRetry && this.retryManager)) {
395
+ _context5.next = 6;
396
+ break;
397
+ }
398
+ _context5.next = 4;
399
+ return this.retryManager.executeWithRetry(event.logId, sendFn);
400
+ case 4:
401
+ _context5.next = 8;
402
+ break;
403
+ case 6:
404
+ _context5.next = 8;
405
+ return sendFn();
406
+ case 8:
407
+ case "end":
408
+ return _context5.stop();
409
+ }
410
+ }, _callee5, this);
411
+ }));
412
+ function sendEvent(_x5) {
413
+ return _sendEvent.apply(this, arguments);
414
+ }
415
+ return sendEvent;
416
+ }()
417
+ /**
418
+ * 批量发送事件(带重试)
419
+ */
420
+ }, {
421
+ key: "sendBatch",
422
+ value: (function () {
423
+ var _sendBatch = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(events) {
424
+ var _this3 = this;
425
+ var batchId, sendFn;
426
+ return _regeneratorRuntime().wrap(function _callee7$(_context7) {
427
+ while (1) switch (_context7.prev = _context7.next) {
428
+ case 0:
429
+ if (!(events.length === 0)) {
430
+ _context7.next = 2;
431
+ break;
432
+ }
433
+ return _context7.abrupt("return");
434
+ case 2:
435
+ // 生成批次 ID
436
+ batchId = "batch_".concat(now(), "_").concat(Math.random().toString(36).substring(2, 9));
437
+ sendFn = /*#__PURE__*/function () {
438
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
439
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
440
+ while (1) switch (_context6.prev = _context6.next) {
441
+ case 0:
442
+ _context6.next = 2;
443
+ return defaultTransport(events, _this3.opts);
444
+ case 2:
445
+ case "end":
446
+ return _context6.stop();
447
+ }
448
+ }, _callee6);
449
+ }));
450
+ return function sendFn() {
451
+ return _ref2.apply(this, arguments);
452
+ };
453
+ }(); // 如果启用重试
454
+ if (!(this.opts.enableRetry && this.retryManager)) {
455
+ _context7.next = 9;
456
+ break;
457
+ }
458
+ _context7.next = 7;
459
+ return this.retryManager.executeWithRetry(batchId, sendFn);
460
+ case 7:
461
+ _context7.next = 11;
462
+ break;
463
+ case 9:
464
+ _context7.next = 11;
465
+ return sendFn();
466
+ case 11:
467
+ case "end":
468
+ return _context7.stop();
469
+ }
470
+ }, _callee7, this);
471
+ }));
472
+ function sendBatch(_x6) {
473
+ return _sendBatch.apply(this, arguments);
474
+ }
475
+ return sendBatch;
476
+ }()
477
+ /**
478
+ * 启动批量上报定时器
479
+ */
480
+ )
481
+ }, {
482
+ key: "startBatchTimer",
483
+ value: function startBatchTimer() {
484
+ var _this4 = this;
485
+ if (this.batchTimer) return;
486
+ this.batchTimer = setInterval(function () {
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);
491
+ });
492
+ }
493
+ }, this.opts.batchInterval);
494
+ this.logDebug("Batch timer started with interval ".concat(this.opts.batchInterval, "ms"));
164
495
  }
165
496
 
166
497
  // ========== 自动采集 ===========
@@ -171,6 +502,7 @@ export var LoggerSDK = /*#__PURE__*/function () {
171
502
  }, {
172
503
  key: "attachUnloadHandlers",
173
504
  value: function attachUnloadHandlers() {
505
+ var _this5 = this;
174
506
  // 微信小程序环境
175
507
  if (isWeChatMiniProgram()) {
176
508
  // 微信小程序使用 App 生命周期
@@ -187,11 +519,11 @@ export var LoggerSDK = /*#__PURE__*/function () {
187
519
  document.addEventListener && document.addEventListener('visibilitychange', function () {
188
520
  try {
189
521
  if (document.visibilityState === 'hidden') {
190
- // this.track('pageview', 'Page hidden', {
191
- // level: 'info',
192
- // tags: { action: 'page_hidden' },
193
- // });
194
- console.log('Page hidden');
522
+ // 页面隐藏时刷新队列
523
+ _this5.flush().catch(function () {
524
+ // 忽略错误
525
+ });
526
+ console.log('Page hidden, flushed queue');
195
527
  }
196
528
  } catch (_unused) {
197
529
  //
@@ -201,11 +533,11 @@ export var LoggerSDK = /*#__PURE__*/function () {
201
533
  // 页面隐藏
202
534
  win.addEventListener && win.addEventListener('pagehide', function () {
203
535
  try {
204
- // this.track('pageview', 'Page hide', {
205
- // level: 'info',
206
- // tags: { action: 'page_hide' },
207
- // });
208
- console.log('Page hide');
536
+ // 页面隐藏时刷新队列(同步)
537
+ _this5.flush().catch(function () {
538
+ // 忽略错误
539
+ });
540
+ console.log('Page hide, flushed queue');
209
541
  } catch (_unused2) {
210
542
  //
211
543
  }
@@ -214,19 +546,28 @@ export var LoggerSDK = /*#__PURE__*/function () {
214
546
  // 页面卸载前
215
547
  win.addEventListener && win.addEventListener('beforeunload', function () {
216
548
  try {
217
- // this.track('pageview', 'Page unload', {
218
- // level: 'info',
219
- // tags: { action: 'page_unload' },
220
- // });
221
- console.log('Page unload');
549
+ // 页面卸载前刷新队列(同步)
550
+ _this5.flush().catch(function () {
551
+ // 忽略错误
552
+ });
553
+ console.log('Page unload, flushed queue');
222
554
  } catch (_unused3) {
223
555
  //
224
556
  }
225
557
  });
226
558
  }
559
+ }], [{
560
+ key: "getInstance",
561
+ value: function getInstance() {
562
+ if (!LoggerSDK.instance) {
563
+ LoggerSDK.instance = new LoggerSDK();
564
+ }
565
+ return LoggerSDK.instance;
566
+ }
227
567
  }]);
228
568
  return LoggerSDK;
229
569
  }();
230
570
 
231
571
  // 兼容导出(UMD/ESM)
572
+ _defineProperty(LoggerSDK, "instance", void 0);
232
573
  export default LoggerSDK;
@@ -0,0 +1,59 @@
1
+ import { LogEvent } from './types';
2
+ /** 队列配置选项 */
3
+ export interface QueueOptions {
4
+ /** 队列最大长度 */
5
+ maxSize: number;
6
+ /** 是否启用持久化存储 */
7
+ enableStorage: boolean;
8
+ /** 存储 key 前缀 */
9
+ storagePrefix: string;
10
+ /** 调试模式 */
11
+ debug?: boolean;
12
+ }
13
+ /**
14
+ * 队列管理器
15
+ * - 内存队列:快速访问
16
+ * - 持久化存储:防止页面刷新/关闭时数据丢失
17
+ */
18
+ export declare class QueueManager {
19
+ private queue;
20
+ private opts;
21
+ private storageKey;
22
+ constructor(options: QueueOptions);
23
+ /**
24
+ * 添加日志到队列
25
+ */
26
+ enqueue(event: LogEvent): boolean;
27
+ /**
28
+ * 批量获取日志(不移除)
29
+ */
30
+ peek(count: number): LogEvent[];
31
+ /**
32
+ * 批量移除日志
33
+ */
34
+ dequeue(count: number): LogEvent[];
35
+ /**
36
+ * 获取队列长度
37
+ */
38
+ size(): number;
39
+ /**
40
+ * 清空队列
41
+ */
42
+ clear(): void;
43
+ /**
44
+ * 从持久化存储加载队列
45
+ */
46
+ private loadFromStorage;
47
+ /**
48
+ * 保存队列到持久化存储
49
+ */
50
+ private saveToStorage;
51
+ /**
52
+ * 从持久化存储移除队列
53
+ */
54
+ private removeFromStorage;
55
+ /**
56
+ * 调试日志
57
+ */
58
+ private logDebug;
59
+ }