@pluve/logger-sdk 0.0.1

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.
@@ -0,0 +1,761 @@
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
+ 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; }
3
+ 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; }
4
+ 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; }
5
+ 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
+ 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
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
9
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
10
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
12
+ 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
+ import IDBQueue from "./dbQueue";
14
+ import { defaultTransport } from "./transportAdapter";
15
+ import { isBrowser, isIndexedDBAvailable, isWeChatMiniProgram, now, safeStringify } from "./utils";
16
+ import { browserStorage, wechatStorage } from "./storeAdapter";
17
+ export var LoggerSDK = /*#__PURE__*/function () {
18
+ function LoggerSDK(options) {
19
+ var _this = this;
20
+ _classCallCheck(this, LoggerSDK);
21
+ _defineProperty(this, "opts", void 0);
22
+ _defineProperty(this, "env", void 0);
23
+ _defineProperty(this, "inMemoryQueue", []);
24
+ _defineProperty(this, "seq", 0);
25
+ _defineProperty(this, "timerId", null);
26
+ _defineProperty(this, "storage", null);
27
+ _defineProperty(this, "closed", false);
28
+ _defineProperty(this, "idbQueue", null);
29
+ _defineProperty(this, "flushing", false);
30
+ var defaults = {
31
+ endpoints: options.endpoints || {},
32
+ appId: options.appId || '',
33
+ env: options.env || function () {
34
+ if (isWeChatMiniProgram()) return 'wechat';
35
+ if (isBrowser()) return 'h5';
36
+ return 'unknown';
37
+ }(),
38
+ batchSize: options.batchSize || 10,
39
+ flushInterval: options.flushInterval || 5000,
40
+ retryCount: options.retryCount || 3,
41
+ retryBase: options.retryBase || 300,
42
+ storageKey: options.storageKey || 'logger_sdk_cache_v2',
43
+ maxCacheSize: options.maxCacheSize || 2000,
44
+ timeout: options.timeout || 10000,
45
+ debug: !!options.debug,
46
+ transport: options.transport || defaultTransport,
47
+ globalHeaders: options.globalHeaders || {},
48
+ enableAutoPV: options.enableAutoPV !== false,
49
+ enablePerf: options.enablePerf !== false,
50
+ usePixel: options.usePixel || false,
51
+ pixelParam: options.pixelParam || 'data',
52
+ maxPixelUrlLen: options.maxPixelUrlLen || 1900
53
+ };
54
+ this.opts = Object.assign(defaults, options);
55
+ this.env = this.opts.env;
56
+
57
+ // choose storage
58
+ if (this.env === 'wechat') this.storage = wechatStorage(this.opts.storageKey);else if (this.env === 'h5') this.storage = browserStorage(this.opts.storageKey);else this.storage = null;
59
+
60
+ // idb queue
61
+ if (isBrowser() && isIndexedDBAvailable()) {
62
+ this.idbQueue = new IDBQueue('logger_sdk_db', 'queue');
63
+ this.idbQueue.open().catch(function () {
64
+ _this.idbQueue = null;
65
+ });
66
+ }
67
+
68
+ // load existing persisted items (localStorage)
69
+ this.loadFromStorage().then(function () {
70
+ if (_this.opts.flushInterval > 0) _this.startTimer();
71
+ });
72
+
73
+ // attach error handlers
74
+ this.attachGlobalHandlers();
75
+
76
+ // auto PV
77
+ if (this.opts.enableAutoPV && this.env === 'h5') this.installAutoPV();
78
+
79
+ // collect perf once on load
80
+ if (this.opts.enablePerf && this.env === 'h5') {
81
+ if (document.readyState === 'complete') this.collectPerf();else window.addEventListener('load', function () {
82
+ return _this.collectPerf();
83
+ });
84
+ }
85
+ }
86
+ _createClass(LoggerSDK, [{
87
+ key: "logDebug",
88
+ value: function logDebug() {
89
+ var _console;
90
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
91
+ args[_key] = arguments[_key];
92
+ }
93
+ if (this.opts.debug) (_console = console).debug.apply(_console, ['[LoggerSDK]'].concat(args));
94
+ }
95
+ }, {
96
+ key: "loadFromStorage",
97
+ value: function () {
98
+ var _loadFromStorage = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
99
+ var raw, arr;
100
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
101
+ while (1) switch (_context.prev = _context.next) {
102
+ case 0:
103
+ if (this.storage) {
104
+ _context.next = 2;
105
+ break;
106
+ }
107
+ return _context.abrupt("return");
108
+ case 2:
109
+ _context.prev = 2;
110
+ _context.next = 5;
111
+ return this.storage.get();
112
+ case 5:
113
+ raw = _context.sent;
114
+ if (raw) {
115
+ arr = JSON.parse(raw);
116
+ this.inMemoryQueue = arr.concat(this.inMemoryQueue).slice(-this.opts.maxCacheSize);
117
+ this.logDebug('loaded persisted queue', this.inMemoryQueue.length);
118
+ }
119
+ _context.next = 12;
120
+ break;
121
+ case 9:
122
+ _context.prev = 9;
123
+ _context.t0 = _context["catch"](2);
124
+ this.logDebug('load persisted fail', _context.t0);
125
+ case 12:
126
+ case "end":
127
+ return _context.stop();
128
+ }
129
+ }, _callee, this, [[2, 9]]);
130
+ }));
131
+ function loadFromStorage() {
132
+ return _loadFromStorage.apply(this, arguments);
133
+ }
134
+ return loadFromStorage;
135
+ }()
136
+ }, {
137
+ key: "persistToStorage",
138
+ value: function () {
139
+ var _persistToStorage = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
140
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
141
+ while (1) switch (_context2.prev = _context2.next) {
142
+ case 0:
143
+ if (this.storage) {
144
+ _context2.next = 2;
145
+ break;
146
+ }
147
+ return _context2.abrupt("return");
148
+ case 2:
149
+ _context2.prev = 2;
150
+ _context2.next = 5;
151
+ return this.storage.set(safeStringify(this.inMemoryQueue));
152
+ case 5:
153
+ this.logDebug('persisted queue', this.inMemoryQueue.length);
154
+ _context2.next = 11;
155
+ break;
156
+ case 8:
157
+ _context2.prev = 8;
158
+ _context2.t0 = _context2["catch"](2);
159
+ this.logDebug('persist fail', _context2.t0);
160
+ case 11:
161
+ case "end":
162
+ return _context2.stop();
163
+ }
164
+ }, _callee2, this, [[2, 8]]);
165
+ }));
166
+ function persistToStorage() {
167
+ return _persistToStorage.apply(this, arguments);
168
+ }
169
+ return persistToStorage;
170
+ }()
171
+ }, {
172
+ key: "startTimer",
173
+ value: function startTimer() {
174
+ var _this2 = this;
175
+ if (this.timerId) return;
176
+ this.timerId = setInterval(function () {
177
+ return _this2.flush().catch(function () {});
178
+ }, this.opts.flushInterval);
179
+ }
180
+ }, {
181
+ key: "stopTimer",
182
+ value: function stopTimer() {
183
+ if (!this.timerId) return;
184
+ clearInterval(this.timerId);
185
+ this.timerId = null;
186
+ }
187
+
188
+ // 将事件入队(先到内存,再持久化)
189
+ }, {
190
+ key: "track",
191
+ value: function () {
192
+ var _track = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(event, headers) {
193
+ var e;
194
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
195
+ while (1) switch (_context3.prev = _context3.next) {
196
+ case 0:
197
+ if (!this.closed) {
198
+ _context3.next = 2;
199
+ break;
200
+ }
201
+ return _context3.abrupt("return");
202
+ case 2:
203
+ this.seq += 1;
204
+ e = {
205
+ type: event.type || 'custom',
206
+ time: event.time || now(),
207
+ user: event.user || undefined,
208
+ ctx: event.ctx || {},
209
+ level: event.level || 'info',
210
+ seq: this.seq
211
+ };
212
+ this.inMemoryQueue.push(e);
213
+ this.logDebug('enqueue', e);
214
+
215
+ // persist to local storage
216
+ _context3.next = 8;
217
+ return this.persistToStorage();
218
+ case 8:
219
+ if (!this.idbQueue) {
220
+ _context3.next = 17;
221
+ break;
222
+ }
223
+ _context3.prev = 9;
224
+ _context3.next = 12;
225
+ return this.idbQueue.add(e);
226
+ case 12:
227
+ _context3.next = 17;
228
+ break;
229
+ case 14:
230
+ _context3.prev = 14;
231
+ _context3.t0 = _context3["catch"](9);
232
+ this.logDebug('idb add fail', _context3.t0);
233
+ case 17:
234
+ if (!(this.inMemoryQueue.length >= this.opts.batchSize)) {
235
+ _context3.next = 20;
236
+ break;
237
+ }
238
+ _context3.next = 20;
239
+ return this.flush(headers).catch(function () {});
240
+ case 20:
241
+ case "end":
242
+ return _context3.stop();
243
+ }
244
+ }, _callee3, this, [[9, 14]]);
245
+ }));
246
+ function track(_x, _x2) {
247
+ return _track.apply(this, arguments);
248
+ }
249
+ return track;
250
+ }() // flush:从队列中取一批发送(按 level 分 endpoint,支持部分成功剔除)
251
+ }, {
252
+ key: "flush",
253
+ value: function () {
254
+ var _flush = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(extraHeaders) {
255
+ var _this3 = this;
256
+ var batch, groups, delay, sendGroup, results, successLevels, allOk, removeSeq;
257
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
258
+ while (1) switch (_context5.prev = _context5.next) {
259
+ case 0:
260
+ if (!this.closed) {
261
+ _context5.next = 2;
262
+ break;
263
+ }
264
+ return _context5.abrupt("return");
265
+ case 2:
266
+ if (!(this.inMemoryQueue.length === 0)) {
267
+ _context5.next = 4;
268
+ break;
269
+ }
270
+ return _context5.abrupt("return");
271
+ case 4:
272
+ if (!this.flushing) {
273
+ _context5.next = 6;
274
+ break;
275
+ }
276
+ return _context5.abrupt("return");
277
+ case 6:
278
+ this.flushing = true;
279
+ _context5.prev = 7;
280
+ // 按 batchSize 划分
281
+ batch = this.inMemoryQueue.slice(0, this.opts.batchSize); // 我们支持将同一批事件按照 level 分开上报到不同 endpoint
282
+ groups = {};
283
+ batch.forEach(function (ev) {
284
+ var level = ev.level || 'info';
285
+ (groups[level] = groups[level] || []).push(ev);
286
+ });
287
+ delay = function delay(ms) {
288
+ return new Promise(function (r) {
289
+ return setTimeout(r, ms);
290
+ });
291
+ };
292
+ sendGroup = function sendGroup(level, events) {
293
+ var endpoint = _this3.opts.endpoints[level] || _this3.opts.endpoints.default;
294
+ var payload = {
295
+ appId: _this3.opts.appId,
296
+ env: _this3.env,
297
+ ts: now(),
298
+ level: level,
299
+ events: events
300
+ };
301
+ var maxTry = _this3.opts.retryCount;
302
+ var attemptOnce = function attemptOnce(attempt) {
303
+ var transportOpts = _objectSpread(_objectSpread({}, _this3.opts), {}, {
304
+ endpoint: endpoint,
305
+ headers: _objectSpread(_objectSpread({}, _this3.opts.globalHeaders || {}), extraHeaders || {})
306
+ });
307
+ return _this3.opts.transport(payload, transportOpts).then(function () {
308
+ return true;
309
+ }).catch( /*#__PURE__*/function () {
310
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(err) {
311
+ var next, wait;
312
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
313
+ while (1) switch (_context4.prev = _context4.next) {
314
+ case 0:
315
+ next = attempt + 1;
316
+ _this3.logDebug('send fail', level, next, err);
317
+ if (!(next > maxTry)) {
318
+ _context4.next = 4;
319
+ break;
320
+ }
321
+ return _context4.abrupt("return", false);
322
+ case 4:
323
+ wait = (_this3.opts.retryBase || 300) * Math.pow(2, next - 1);
324
+ _context4.next = 7;
325
+ return delay(wait);
326
+ case 7:
327
+ return _context4.abrupt("return", attemptOnce(next));
328
+ case 8:
329
+ case "end":
330
+ return _context4.stop();
331
+ }
332
+ }, _callee4);
333
+ }));
334
+ return function (_x4) {
335
+ return _ref.apply(this, arguments);
336
+ };
337
+ }());
338
+ };
339
+ return attemptOnce(0).then(function (ok) {
340
+ return {
341
+ ok: ok,
342
+ level: level,
343
+ events: events
344
+ };
345
+ });
346
+ };
347
+ _context5.next = 15;
348
+ return Promise.all(Object.keys(groups).map(function (level) {
349
+ return sendGroup(level, groups[level]);
350
+ }));
351
+ case 15:
352
+ results = _context5.sent;
353
+ successLevels = new Set(results.filter(function (r) {
354
+ return r.ok;
355
+ }).map(function (r) {
356
+ return r.level;
357
+ }));
358
+ allOk = results.length > 0 && results.every(function (r) {
359
+ return r.ok;
360
+ });
361
+ if (!(!allOk && successLevels.size === 0)) {
362
+ _context5.next = 21;
363
+ break;
364
+ }
365
+ // 全部失败:保留队列,等待下次重试
366
+ this.logDebug('batch send failed, keep batch in queue');
367
+ return _context5.abrupt("return");
368
+ case 21:
369
+ // 部分成功:仅移除已成功 level 的事件
370
+ removeSeq = new Set(batch.filter(function (e) {
371
+ return successLevels.has(e.level || 'info');
372
+ }).map(function (e) {
373
+ return e.seq;
374
+ }));
375
+ this.inMemoryQueue = this.inMemoryQueue.filter(function (x) {
376
+ return !removeSeq.has(x.seq);
377
+ });
378
+ _context5.next = 25;
379
+ return this.persistToStorage();
380
+ case 25:
381
+ if (!(allOk && this.idbQueue)) {
382
+ _context5.next = 34;
383
+ break;
384
+ }
385
+ _context5.prev = 26;
386
+ _context5.next = 29;
387
+ return this.idbQueue.clear();
388
+ case 29:
389
+ _context5.next = 34;
390
+ break;
391
+ case 31:
392
+ _context5.prev = 31;
393
+ _context5.t0 = _context5["catch"](26);
394
+ this.logDebug('idb clear fail', _context5.t0);
395
+ case 34:
396
+ _context5.prev = 34;
397
+ this.flushing = false;
398
+ return _context5.finish(34);
399
+ case 37:
400
+ case "end":
401
+ return _context5.stop();
402
+ }
403
+ }, _callee5, this, [[7,, 34, 37], [26, 31]]);
404
+ }));
405
+ function flush(_x3) {
406
+ return _flush.apply(this, arguments);
407
+ }
408
+ return flush;
409
+ }() // 将队列尽力全部发送(分批轮询 + 安全阈值)
410
+ }, {
411
+ key: "flushAll",
412
+ value: function () {
413
+ var _flushAll = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7() {
414
+ var _this4 = this;
415
+ var safety;
416
+ return _regeneratorRuntime().wrap(function _callee7$(_context7) {
417
+ while (1) switch (_context7.prev = _context7.next) {
418
+ case 0:
419
+ safety = 0;
420
+ return _context7.abrupt("return", new Promise(function (resolve) {
421
+ var tick = /*#__PURE__*/function () {
422
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
423
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
424
+ while (1) switch (_context6.prev = _context6.next) {
425
+ case 0:
426
+ // 安全阈值,避免异常情况下无限循环
427
+ safety += 1;
428
+ if (!(_this4.inMemoryQueue.length === 0 || safety >= 200)) {
429
+ _context6.next = 3;
430
+ break;
431
+ }
432
+ return _context6.abrupt("return", resolve());
433
+ case 3:
434
+ if (_this4.flushing) {
435
+ _context6.next = 11;
436
+ break;
437
+ }
438
+ _context6.prev = 4;
439
+ _context6.next = 7;
440
+ return _this4.flush();
441
+ case 7:
442
+ _context6.next = 11;
443
+ break;
444
+ case 9:
445
+ _context6.prev = 9;
446
+ _context6.t0 = _context6["catch"](4);
447
+ case 11:
448
+ setTimeout(tick, 50);
449
+ case 12:
450
+ case "end":
451
+ return _context6.stop();
452
+ }
453
+ }, _callee6, null, [[4, 9]]);
454
+ }));
455
+ return function tick() {
456
+ return _ref2.apply(this, arguments);
457
+ };
458
+ }();
459
+ tick();
460
+ }));
461
+ case 2:
462
+ case "end":
463
+ return _context7.stop();
464
+ }
465
+ }, _callee7);
466
+ }));
467
+ function flushAll() {
468
+ return _flushAll.apply(this, arguments);
469
+ }
470
+ return flushAll;
471
+ }()
472
+ }, {
473
+ key: "identify",
474
+ value: function () {
475
+ var _identify = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(user) {
476
+ return _regeneratorRuntime().wrap(function _callee8$(_context8) {
477
+ while (1) switch (_context8.prev = _context8.next) {
478
+ case 0:
479
+ this.opts.appId = user && user.appId || this.opts.appId;
480
+ this.logDebug('identify', user);
481
+ case 2:
482
+ case "end":
483
+ return _context8.stop();
484
+ }
485
+ }, _callee8, this);
486
+ }));
487
+ function identify(_x5) {
488
+ return _identify.apply(this, arguments);
489
+ }
490
+ return identify;
491
+ }()
492
+ }, {
493
+ key: "setCommon",
494
+ value: function () {
495
+ var _setCommon = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(params) {
496
+ return _regeneratorRuntime().wrap(function _callee9$(_context9) {
497
+ while (1) switch (_context9.prev = _context9.next) {
498
+ case 0:
499
+ Object.assign(this.opts, params);
500
+ this.logDebug('setCommon', params);
501
+ case 2:
502
+ case "end":
503
+ return _context9.stop();
504
+ }
505
+ }, _callee9, this);
506
+ }));
507
+ function setCommon(_x6) {
508
+ return _setCommon.apply(this, arguments);
509
+ }
510
+ return setCommon;
511
+ }()
512
+ }, {
513
+ key: "destroy",
514
+ value: function destroy() {
515
+ this.stopTimer();
516
+ this.closed = true;
517
+ }
518
+
519
+ // ========== 自动采集与错误处理 ===========
520
+ }, {
521
+ key: "attachGlobalHandlers",
522
+ value: function attachGlobalHandlers() {
523
+ var _this5 = this;
524
+ if (this.env === 'h5' && typeof window !== 'undefined') {
525
+ var win = window;
526
+ // JS 错误
527
+ win.addEventListener && win.addEventListener('error', function (ev) {
528
+ try {
529
+ _this5.track({
530
+ type: 'error',
531
+ level: 'error',
532
+ ctx: {
533
+ message: ev.message,
534
+ filename: ev.filename,
535
+ lineno: ev.lineno,
536
+ colno: ev.colno,
537
+ stack: ev.error && ev.error.stack
538
+ }
539
+ });
540
+ } catch (_unused2) {
541
+ //
542
+ }
543
+ });
544
+ // Promise 未捕获
545
+ win.addEventListener && win.addEventListener('unhandledrejection', function (ev) {
546
+ try {
547
+ _this5.track({
548
+ type: 'error',
549
+ level: 'error',
550
+ ctx: {
551
+ reason: ev.reason && (ev.reason.stack || ev.reason)
552
+ }
553
+ });
554
+ } catch (_unused3) {
555
+ //
556
+ }
557
+ });
558
+ // Resource 加载错误(img/script/link)
559
+ win.addEventListener && win.addEventListener('error', function (ev) {
560
+ if (ev.target && (ev.target.src || ev.target.href)) {
561
+ try {
562
+ _this5.track({
563
+ type: 'error',
564
+ level: 'warn',
565
+ ctx: {
566
+ resource: ev.target.src || ev.target.href,
567
+ tag: ev.target.tagName
568
+ }
569
+ });
570
+ } catch (_unused4) {
571
+ //
572
+ }
573
+ }
574
+ }, true);
575
+ document.addEventListener && document.addEventListener('visibilitychange', function () {
576
+ try {
577
+ if (document.visibilityState === 'hidden') _this5.flushBeacon();
578
+ } catch (_unused5) {
579
+ //
580
+ }
581
+ });
582
+ win.addEventListener && win.addEventListener('pagehide', function () {
583
+ try {
584
+ _this5.flushBeacon();
585
+ } catch (_unused6) {
586
+ //
587
+ }
588
+ });
589
+ win.addEventListener && win.addEventListener('beforeunload', function () {
590
+ try {
591
+ _this5.flushBeacon();
592
+ } catch (_unused7) {
593
+ //
594
+ }
595
+ });
596
+ }
597
+ }
598
+
599
+ // 自动 PV(single-page 支持简单的 history 池监听)
600
+ }, {
601
+ key: "installAutoPV",
602
+ value: function installAutoPV() {
603
+ var _this6 = this;
604
+ // 仅在浏览器环境安装 PV 监听,避免 SSR/Node 触发 window 访问错误
605
+ if (!isBrowser()) return;
606
+ var _window = window,
607
+ history = _window.history,
608
+ location = _window.location;
609
+ var _ref3 = history,
610
+ pushState = _ref3.pushState;
611
+ var _ref4 = history,
612
+ replaceState = _ref4.replaceState;
613
+ var onUrlChange = function onUrlChange() {
614
+ try {
615
+ _this6.track({
616
+ type: 'pageview',
617
+ level: 'info',
618
+ ctx: {
619
+ path: location.pathname + location.search,
620
+ title: document.title
621
+ }
622
+ });
623
+ } catch (_unused8) {
624
+ //
625
+ }
626
+ };
627
+ // 包装原生 history 方法,正确转发所有参数并派发自定义事件
628
+ history.pushState = function () {
629
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
630
+ args[_key2] = arguments[_key2];
631
+ }
632
+ // @ts-ignore
633
+ pushState.apply(this, args);
634
+ window.dispatchEvent(new Event('locationchange'));
635
+ };
636
+ history.replaceState = function () {
637
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
638
+ args[_key3] = arguments[_key3];
639
+ }
640
+ // @ts-ignore
641
+ replaceState.apply(this, args);
642
+ window.dispatchEvent(new Event('locationchange'));
643
+ };
644
+ window.addEventListener('popstate', function () {
645
+ return window.dispatchEvent(new Event('locationchange'));
646
+ });
647
+ window.addEventListener('locationchange', onUrlChange);
648
+ // 首次 PV
649
+ onUrlChange();
650
+ }
651
+
652
+ // 性能采集(Navigation timing + Paint)
653
+ }, {
654
+ key: "collectPerf",
655
+ value: function collectPerf() {
656
+ if (!isBrowser() || !('performance' in window)) return;
657
+ try {
658
+ var perf = window.performance;
659
+ var nav = perf.getEntriesByType && perf.getEntriesByType('navigation') && perf.getEntriesByType('navigation')[0];
660
+ var paints = perf.getEntriesByType ? perf.getEntriesByType('paint') : [];
661
+ var data = {};
662
+ if (nav) {
663
+ data.ttfb = nav.responseStart - nav.requestStart;
664
+ data.domContentLoaded = nav.domContentLoadedEventEnd - nav.startTime;
665
+ data.load = nav.loadEventEnd - nav.startTime;
666
+ } else if (perf.timing) {
667
+ var t = perf.timing;
668
+ data.ttfb = t.responseStart - t.requestStart;
669
+ data.domContentLoaded = t.domContentLoadedEventEnd - t.navigationStart;
670
+ data.load = t.loadEventEnd - t.navigationStart;
671
+ }
672
+ if (paints && paints.length) {
673
+ paints.forEach(function (p) {
674
+ data[p.name] = p.startTime;
675
+ });
676
+ }
677
+ this.track({
678
+ type: 'perf',
679
+ level: 'info',
680
+ ctx: data
681
+ });
682
+ } catch (e) {
683
+ this.logDebug('collect perf fail', e);
684
+ }
685
+ }
686
+ }, {
687
+ key: "flushBeacon",
688
+ value: function flushBeacon() {
689
+ var _this7 = this;
690
+ if (!isBrowser()) return;
691
+ if (this.inMemoryQueue.length === 0) return;
692
+ var groups = {};
693
+ this.inMemoryQueue.forEach(function (ev) {
694
+ var level = ev.level || 'info';
695
+ (groups[level] = groups[level] || []).push(ev);
696
+ });
697
+ Object.keys(groups).forEach(function (level) {
698
+ var events = groups[level];
699
+ var endpoint = _this7.opts.endpoints[level] || _this7.opts.endpoints.default;
700
+ var payload = {
701
+ appId: _this7.opts.appId,
702
+ env: _this7.env,
703
+ ts: now(),
704
+ level: level,
705
+ events: events
706
+ };
707
+ var transportOpts = _objectSpread(_objectSpread({}, _this7.opts), {}, {
708
+ endpoint: endpoint,
709
+ headers: _objectSpread({}, _this7.opts.globalHeaders || {}),
710
+ useBeacon: true,
711
+ usePixel: _this7.opts.usePixel,
712
+ pixelParam: _this7.opts.pixelParam,
713
+ maxPixelUrlLen: _this7.opts.maxPixelUrlLen
714
+ });
715
+ try {
716
+ _this7.opts.transport(payload, transportOpts);
717
+ } catch (_unused9) {
718
+ //
719
+ }
720
+ });
721
+ }
722
+
723
+ // 生成简单 Demo 页面(HTML 字符串),方便生成 demo 文档站点
724
+ // public generateDemoHtml(opts?: { scriptUrl?: string }) {
725
+ // const scriptUrl = (opts && opts.scriptUrl) || 'dist/index.umd.js';
726
+ // const html = ```
727
+ // <!doctype html>
728
+ // <html>
729
+ // <head>
730
+ // <meta charset="utf-8" />
731
+ // <title>LoggerSDK Demo</title>
732
+ // </head>
733
+ // <body>
734
+ // <h1>LoggerSDK Demo</h1>
735
+ // <script src="${scriptUrl}"></script>
736
+ // <script>
737
+ // // 通过 UMD 全局 MyLogger 使用
738
+ // const sdk = new MyLogger.LoggerSDK({
739
+ // endpoints: { default: '/api/collect', info: '/api/collect/info', error: '/api/collect/error' },
740
+ // appId: 'demo-app',
741
+ // debug: true,
742
+ // enableAutoPV: true,
743
+ // enablePerf: true
744
+ // });
745
+
746
+ // // 手动埋点
747
+ // sdk.track({ type: 'custom', level: 'info', ctx: { action: 'click_demo' } });
748
+
749
+ // // 模拟错误
750
+ // setTimeout(() => { throw new Error('demo error'); }, 2000);
751
+ // </script>
752
+ // </body>
753
+ // </html>```;
754
+ // return html;
755
+ // }
756
+ }]);
757
+ return LoggerSDK;
758
+ }();
759
+
760
+ // 兼容导出(UMD/ESM)
761
+ export default LoggerSDK;