@pluve/logger-sdk 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +139 -432
  2. package/dist/cjs/capture/jsError.js +48 -0
  3. package/dist/cjs/capture/promiseError.js +49 -0
  4. package/dist/cjs/capture/resourceError.js +48 -0
  5. package/dist/cjs/capture/wechatError.js +95 -0
  6. package/dist/cjs/compress/compression.js +84 -0
  7. package/dist/cjs/config/index.js +55 -0
  8. package/dist/cjs/core/fingerprint.js +36 -0
  9. package/dist/cjs/core/httpClient.js +96 -0
  10. package/dist/cjs/core/loggerSDK.js +641 -0
  11. package/dist/cjs/core/queueManager.js +249 -0
  12. package/dist/cjs/core/retryManager.js +127 -0
  13. package/dist/cjs/index.js +29 -0
  14. package/dist/cjs/logger-sdk.mermaid +84 -0
  15. package/dist/cjs/logger-sdk.svg +1 -0
  16. package/dist/cjs/stack/stacktrace.js +48 -0
  17. package/dist/cjs/transport/beaconTransport.js +64 -0
  18. package/dist/cjs/transport/pixelImageTransport.js +100 -0
  19. package/dist/cjs/transport/transport.js +17 -0
  20. package/dist/cjs/transport/transportAdapter.js +56 -0
  21. package/dist/cjs/transport/wechatTransport.js +103 -0
  22. package/dist/cjs/types/api.js +17 -0
  23. package/dist/cjs/types/env.js +17 -0
  24. package/dist/cjs/types/external.d.ts +21 -0
  25. package/dist/cjs/types/logEvent.js +17 -0
  26. package/dist/cjs/types/logEventLevel.js +17 -0
  27. package/dist/cjs/types/sdkOptions.js +17 -0
  28. package/dist/cjs/types/trackOptions.js +17 -0
  29. package/dist/cjs/utils/environment.js +183 -0
  30. package/dist/cjs/utils/session.js +31 -0
  31. package/dist/cjs/utils/tools.js +82 -0
  32. package/dist/cjs/utils/uuid.js +35 -0
  33. package/dist/esm/capture/jsError.js +45 -0
  34. package/dist/esm/capture/promiseError.js +46 -0
  35. package/dist/esm/capture/resourceError.js +24 -0
  36. package/dist/esm/capture/wechatError.js +92 -0
  37. package/dist/esm/compress/compression.js +82 -0
  38. package/dist/esm/config/index.js +28 -0
  39. package/dist/esm/core/fingerprint.js +12 -0
  40. package/dist/esm/core/httpClient.js +95 -0
  41. package/dist/esm/core/loggerSDK.js +650 -0
  42. package/dist/esm/core/queueManager.js +269 -0
  43. package/dist/esm/core/retryManager.js +129 -0
  44. package/dist/esm/index.js +5 -0
  45. package/dist/esm/logger-sdk.mermaid +84 -0
  46. package/dist/esm/logger-sdk.svg +1 -0
  47. package/dist/esm/stack/stacktrace.js +37 -0
  48. package/dist/esm/transport/beaconTransport.js +81 -0
  49. package/dist/esm/transport/pixelImageTransport.js +99 -0
  50. package/dist/esm/transport/transport.js +0 -0
  51. package/dist/esm/transport/transportAdapter.js +32 -0
  52. package/dist/esm/transport/wechatTransport.js +120 -0
  53. package/dist/esm/types/api.js +0 -0
  54. package/dist/esm/types/env.js +0 -0
  55. package/dist/esm/types/external.d.ts +21 -0
  56. package/dist/esm/types/logEvent.js +0 -0
  57. package/dist/esm/types/logEventLevel.js +0 -0
  58. package/dist/esm/types/sdkOptions.js +0 -0
  59. package/dist/esm/types/trackOptions.js +0 -0
  60. package/dist/esm/utils/environment.js +154 -0
  61. package/dist/esm/utils/session.js +7 -0
  62. package/dist/esm/utils/tools.js +76 -0
  63. package/dist/esm/utils/uuid.js +11 -0
  64. package/dist/types/capture/jsError.d.ts +2 -0
  65. package/dist/types/capture/promiseError.d.ts +2 -0
  66. package/dist/types/capture/resourceError.d.ts +2 -0
  67. package/dist/types/capture/wechatError.d.ts +3 -0
  68. package/dist/types/compress/compression.d.ts +10 -0
  69. package/dist/types/config/index.d.ts +9 -0
  70. package/dist/types/core/fingerprint.d.ts +8 -0
  71. package/dist/types/core/httpClient.d.ts +11 -0
  72. package/dist/{loggerSDK.d.ts → types/core/loggerSDK.d.ts} +32 -14
  73. package/dist/{queueManager.d.ts → types/core/queueManager.d.ts} +9 -5
  74. package/dist/{retryManager.d.ts → types/core/retryManager.d.ts} +2 -6
  75. package/dist/types/index.d.ts +1 -0
  76. package/dist/types/stack/stacktrace.d.ts +2 -0
  77. package/dist/types/transport/beaconTransport.d.ts +11 -0
  78. package/dist/types/transport/pixelImageTransport.d.ts +11 -0
  79. package/dist/types/transport/transport.d.ts +14 -0
  80. package/dist/types/transport/transportAdapter.d.ts +10 -0
  81. package/dist/types/transport/wechatTransport.d.ts +11 -0
  82. package/dist/types/types/api.d.ts +12 -0
  83. package/dist/types/types/env.d.ts +14 -0
  84. package/dist/types/types/logEvent.d.ts +57 -0
  85. package/dist/types/types/logEventLevel.d.ts +2 -0
  86. package/dist/types/types/sdkOptions.d.ts +61 -0
  87. package/dist/types/types/trackOptions.d.ts +7 -0
  88. package/dist/types/utils/environment.d.ts +21 -0
  89. package/dist/types/utils/session.d.ts +1 -0
  90. package/dist/types/utils/tools.d.ts +12 -0
  91. package/dist/types/utils/uuid.d.ts +7 -0
  92. package/dist/umd/logger-sdk.min.js +1 -0
  93. package/package.json +30 -6
  94. package/README.html +0 -982
  95. package/dist/index.d.ts +0 -10
  96. package/dist/index.js +0 -13
  97. package/dist/loggerSDK.js +0 -573
  98. package/dist/queueManager.js +0 -201
  99. package/dist/retryManager.js +0 -223
  100. package/dist/transportAdapter.d.ts +0 -51
  101. package/dist/transportAdapter.js +0 -315
  102. package/dist/types.d.ts +0 -70
  103. package/dist/types.js +0 -1
  104. package/dist/utils.d.ts +0 -47
  105. package/dist/utils.js +0 -306
@@ -0,0 +1,650 @@
1
+ var __async = (__this, __arguments, generator) => {
2
+ return new Promise((resolve, reject) => {
3
+ var fulfilled = (value) => {
4
+ try {
5
+ step(generator.next(value));
6
+ } catch (e) {
7
+ reject(e);
8
+ }
9
+ };
10
+ var rejected = (value) => {
11
+ try {
12
+ step(generator.throw(value));
13
+ } catch (e) {
14
+ reject(e);
15
+ }
16
+ };
17
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
18
+ step((generator = generator.apply(__this, __arguments)).next());
19
+ });
20
+ };
21
+
22
+ // src/core/loggerSDK.ts
23
+ import { registerJsErrorCapture } from "../capture/jsError";
24
+ import { registerPromiseErrorCapture } from "../capture/promiseError";
25
+ import { registerResourceErrorCapture } from "../capture/resourceError";
26
+ import { getRegisterApi } from "../config";
27
+ import { TransportAdapter } from "../transport/transportAdapter";
28
+ import { collectEnvironmentTags, getCurrentUrl, isBrowser } from "../utils/environment";
29
+ import { registerWechatErrorCapture, registerWechatUnhandledCapture } from "../capture/wechatError";
30
+ import { getSessionId } from "../utils/session";
31
+ import { flattenStack, hashToProb, logDebug, now, normalizeMessage } from "../utils/tools";
32
+ import { uuid } from "../utils/uuid";
33
+ import { HttpClient } from "./httpClient";
34
+ import { QueueManager } from "./queueManager";
35
+ import { RetryManager } from "./retryManager";
36
+ var LoggerSDK = class {
37
+ constructor() {
38
+ /** 事件序列编号,用于事件去重 */
39
+ this.seq = 0;
40
+ /** 是否已关闭 */
41
+ this.closed = false;
42
+ /** 预收集的环境信息 tags(仅用于初始化上报) */
43
+ this.envTags = {};
44
+ /** 是否已初始化 */
45
+ this.initialized = false;
46
+ /** 是否正在上报 */
47
+ this.isSending = false;
48
+ this.collectSwitch = 0;
49
+ // 采集开关,0:关闭,1:开启
50
+ this.collectLogLevel = [];
51
+ // 采集日志等级
52
+ this.recentAutoEvents = /* @__PURE__ */ new Map();
53
+ this.sessionId = getSessionId();
54
+ }
55
+ static getInstance() {
56
+ if (!LoggerSDK.instance) {
57
+ LoggerSDK.instance = new LoggerSDK();
58
+ }
59
+ return LoggerSDK.instance;
60
+ }
61
+ /**
62
+ * 初始化:配置参数、收集环境信息与 UA,并生成 sessionId,完成初始上报
63
+ */
64
+ init(options) {
65
+ this.opts = {
66
+ // endpoint: options.endpoint,
67
+ appId: `${options.appId}-frontend` || "unknown",
68
+ env: options.env || "develop",
69
+ /** 日志环境 */
70
+ logStage: options.logStage,
71
+ debug: !!options.debug,
72
+ /** 是否启用 gzip 压缩,默认 true */
73
+ enableGzip: options.enableGzip !== false,
74
+ // 默认启用
75
+ gzipOnlyInBatchMode: options.gzipOnlyInBatchMode !== false,
76
+ // 默认启用
77
+ /** 最大像素图 URL 长度,默认 1900 */
78
+ maxPixelUrlLen: options.maxPixelUrlLen || 8192,
79
+ // 批量上报配置(默认关闭,需显式开启)
80
+ enableBatch: options.enableBatch === true,
81
+ batchSize: options.batchSize || 20,
82
+ batchInterval: options.batchInterval || 15e3,
83
+ // 默认 15 秒批量上报一次,在开启批量上报的情况下
84
+ maxQueueSize: options.maxQueueSize || 100,
85
+ // 持久化存储配置
86
+ enableStorage: options.enableBatch === true || options.enableStorage !== false,
87
+ // 默认启用
88
+ storagePrefix: options.storagePrefix || "logger_sdk",
89
+ // 重试配置
90
+ enableRetry: options.enableRetry !== false,
91
+ // 默认启用
92
+ maxRetries: options.maxRetries || 3,
93
+ retryDelay: options.retryDelay || 1e3,
94
+ retryBackoff: options.retryBackoff !== false,
95
+ // 默认启用
96
+ userId: options.userId,
97
+ storeCode: options.storeCode,
98
+ token: options.token,
99
+ sampleRate: typeof options.sampleRate === "number" ? options.sampleRate : 1,
100
+ levelSampleRate: options.levelSampleRate || {
101
+ ERROR: 0.8,
102
+ WARN: 0.5,
103
+ INFO: 0.1,
104
+ FATAL: 1
105
+ },
106
+ sourceSampleRate: options.sourceSampleRate || {
107
+ js: 0.8,
108
+ promise: 0.5,
109
+ resource: 0.2,
110
+ custom: 1
111
+ },
112
+ pathSampleRate: options.pathSampleRate || {
113
+ "/": 1
114
+ },
115
+ enableAutoCapture: options.enableAutoCapture !== false,
116
+ // 默认启用
117
+ autoCapture: options.autoCapture || {
118
+ js: true,
119
+ promise: true,
120
+ resource: true,
121
+ wechat: true
122
+ }
123
+ };
124
+ if (this.opts.enableBatch) {
125
+ this.queueManager = new QueueManager({
126
+ maxSize: this.opts.maxQueueSize,
127
+ enableStorage: this.opts.enableStorage,
128
+ storagePrefix: this.opts.storagePrefix,
129
+ debug: this.opts.debug
130
+ });
131
+ }
132
+ if (this.opts.enableRetry) {
133
+ this.retryManager = new RetryManager({
134
+ maxRetries: this.opts.maxRetries,
135
+ baseDelay: this.opts.retryDelay,
136
+ useBackoff: this.opts.retryBackoff,
137
+ debug: this.opts.debug
138
+ });
139
+ }
140
+ this.transporter = TransportAdapter.getInstance(this.opts).getTransporter();
141
+ this.sessionId = getSessionId();
142
+ this.envTags = collectEnvironmentTags();
143
+ this.initSDK(this.opts, (data) => {
144
+ var _a, _b, _c, _d, _e, _f, _g, _h;
145
+ this.collectSwitch = data.collectSwitch;
146
+ this.collectLogLevel = data.collectLogLevel;
147
+ this.opts.sampleRate = data.samplingRate;
148
+ if ((_a = this.opts) == null ? void 0 : _a.enableBatch) {
149
+ this.startBatchTimer();
150
+ }
151
+ this.initialized = true;
152
+ this.attachUnloadHandlers();
153
+ const enableAuto = ((_b = this.opts) == null ? void 0 : _b.enableAutoCapture) !== false;
154
+ const ac = ((_c = this.opts) == null ? void 0 : _c.autoCapture) || {};
155
+ if (enableAuto && ac.js !== false) {
156
+ this.offJs = registerJsErrorCapture(!!((_d = this.opts) == null ? void 0 : _d.debug), this.trackInner.bind(this));
157
+ }
158
+ if (enableAuto && ac.promise !== false) {
159
+ this.offPromise = registerPromiseErrorCapture(!!((_e = this.opts) == null ? void 0 : _e.debug), this.trackInner.bind(this));
160
+ }
161
+ if (enableAuto && ac.resource !== false) {
162
+ this.offResource = registerResourceErrorCapture(!!((_f = this.opts) == null ? void 0 : _f.debug), this.trackInner.bind(this));
163
+ }
164
+ if (enableAuto && ac.wechat !== false) {
165
+ this.offWxError = registerWechatErrorCapture(!!((_g = this.opts) == null ? void 0 : _g.debug), this.trackInner.bind(this));
166
+ this.offWxUnhandled = registerWechatUnhandledCapture(!!((_h = this.opts) == null ? void 0 : _h.debug), this.trackInner.bind(this));
167
+ }
168
+ });
169
+ }
170
+ /**
171
+ * 设置用户信息
172
+ */
173
+ identify(userId) {
174
+ var _a;
175
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "identify", userId);
176
+ if (this.opts) {
177
+ this.opts.userId = userId;
178
+ }
179
+ }
180
+ /** 设置店铺编码 */
181
+ setStoreCode(storeCode) {
182
+ var _a;
183
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "setStoreCode", storeCode);
184
+ if (this.opts) {
185
+ this.opts.storeCode = storeCode;
186
+ }
187
+ }
188
+ /** 设置日志 stage(env) */
189
+ setStage(stage) {
190
+ var _a;
191
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "setStage", stage);
192
+ if (this.opts) {
193
+ this.opts.env = stage;
194
+ }
195
+ }
196
+ flattenEnvTags() {
197
+ return Object.entries(this.envTags || {}).map(([k, v]) => `${k}=${v}`).join(",");
198
+ }
199
+ track(_0) {
200
+ return __async(this, arguments, function* ({ message, error, traceId, logLevel = "INFO" }) {
201
+ var _a, _b, _c;
202
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "track", { message, error, traceId, logLevel });
203
+ if (this.closed)
204
+ return;
205
+ if (!this.initialized) {
206
+ logDebug(!!((_b = this.opts) == null ? void 0 : _b.debug), "SDK not initialized, skip track");
207
+ return;
208
+ }
209
+ if (!this.shouldSend(logLevel, "custom", getCurrentUrl(), traceId, message)) {
210
+ logDebug(!!((_c = this.opts) == null ? void 0 : _c.debug), "Event sampled out", { logLevel, traceId, message });
211
+ return;
212
+ }
213
+ this.seq += 1;
214
+ let errorLocation = "";
215
+ let throwableStack = "";
216
+ if (error instanceof Error) {
217
+ try {
218
+ const { location, throwable } = yield flattenStack(error);
219
+ errorLocation = location || "";
220
+ throwableStack = throwable || error.stack || "";
221
+ } catch (e) {
222
+ errorLocation = "";
223
+ throwableStack = error.stack || "";
224
+ }
225
+ }
226
+ const logEvent = {
227
+ /** 日志 ID */
228
+ logId: `${this.opts.appId}${uuid()}${now()}`,
229
+ // UUID
230
+ seq: this.seq,
231
+ /** 应用标识 */
232
+ appId: this.opts.appId || "unknown",
233
+ /** 环境标识 */
234
+ stage: this.opts.logStage,
235
+ /** 日志级别:info/warn/error/fatal */
236
+ level: logLevel,
237
+ /** 可选:跟踪 ID(跨服务调用链跟踪) */
238
+ traceId,
239
+ /** 会话标识,同 sessionId */
240
+ frontendId: this.sessionId,
241
+ // 同 sessionId
242
+ /** 发生页面 URL */
243
+ url: getCurrentUrl(),
244
+ location: errorLocation,
245
+ /** 异常信息 */
246
+ message: `[message]: ${message}; [envTags]: ${this.flattenEnvTags()}; [t]: ${now()}`,
247
+ /** 可选:堆栈信息(长字符串) */
248
+ throwable: throwableStack,
249
+ /** 可选:用户 ID(脱敏) */
250
+ userId: this.opts.userId,
251
+ /** 可选:店铺编码 */
252
+ storeCode: this.opts.storeCode
253
+ /** 可选的结构化额外信息 */
254
+ // tags: this.envTags,
255
+ };
256
+ this.doTrack(logEvent);
257
+ });
258
+ }
259
+ trackInner(error) {
260
+ var _a, _b, _c, _d, _e, _f, _g, _h;
261
+ if (this.closed)
262
+ return;
263
+ if (!this.initialized) {
264
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "SDK not initialized, skip track");
265
+ return;
266
+ }
267
+ logDebug(!!((_b = this.opts) == null ? void 0 : _b.debug), "trackInner", error);
268
+ const sig = `${error.type}|${normalizeMessage(error.message)}|${String(this.sessionId || "")}`;
269
+ const ts = now();
270
+ const last = this.recentAutoEvents.get(sig) || 0;
271
+ if (ts - last < 3e3) {
272
+ return;
273
+ }
274
+ this.recentAutoEvents.set(sig, ts);
275
+ if (!this.shouldSend("ERROR", error.type, getCurrentUrl(), void 0, error.message)) {
276
+ logDebug(!!((_c = this.opts) == null ? void 0 : _c.debug), "Auto-captured event sampled out", error.message);
277
+ return;
278
+ }
279
+ this.seq += 1;
280
+ let errorLocation = "";
281
+ const throwableStack = ((_d = error.stack) == null ? void 0 : _d.map((frame) => `${frame.file}:${frame.line}:${frame.column}`).join("\n ")) || "";
282
+ if (error.stack && error.stack.length > 0) {
283
+ errorLocation = `${(_e = error.stack) == null ? void 0 : _e[0].file}:${(_f = error.stack) == null ? void 0 : _f[0].line}:${(_g = error.stack) == null ? void 0 : _g[0].column}:${(_h = error.stack) == null ? void 0 : _h[0].function}`;
284
+ }
285
+ const logEvent = {
286
+ /** 日志 ID */
287
+ logId: `${this.opts.appId}${uuid()}${now()}`,
288
+ // UUID
289
+ seq: this.seq,
290
+ /** 应用标识 */
291
+ appId: this.opts.appId || "unknown",
292
+ /** 环境标识 */
293
+ stage: this.opts.env || "develop",
294
+ /** 日志级别:info/warn/error/fatal */
295
+ level: "ERROR",
296
+ /** 会话标识,同 sessionId */
297
+ frontendId: this.sessionId,
298
+ // 同 sessionId
299
+ /** 发生页面 URL */
300
+ url: getCurrentUrl(),
301
+ location: errorLocation,
302
+ /** 异常信息 */
303
+ message: `[message]: ${error.message}; [envTags]: ${this.flattenEnvTags()}; [t]: ${now()}`,
304
+ /** 可选:堆栈信息(长字符串) */
305
+ throwable: throwableStack,
306
+ /** 可选:用户 ID(脱敏) */
307
+ userId: this.opts.userId,
308
+ /** 可选:店铺编码 */
309
+ storeCode: this.opts.storeCode
310
+ /** 可选的结构化额外信息 */
311
+ // tags: this.envTags,
312
+ };
313
+ this.doTrack(logEvent);
314
+ }
315
+ /**
316
+ * 判断是否应该发送事件
317
+ */
318
+ shouldSend(level, source, url, traceId, message) {
319
+ var _a, _b, _c, _d, _e, _f, _g;
320
+ if (level === "FATAL")
321
+ return true;
322
+ if (this.collectSwitch === 0) {
323
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "Collect switch is off, skip track");
324
+ return false;
325
+ }
326
+ if (!this.collectLogLevel.some((l) => l === level)) {
327
+ logDebug(!!((_b = this.opts) == null ? void 0 : _b.debug), `Log level(${level}) not in collect log level, skip track`);
328
+ return false;
329
+ }
330
+ const levelRate = (_d = (_c = this.opts) == null ? void 0 : _c.levelSampleRate) == null ? void 0 : _d[level];
331
+ const sourceRate = (_f = (_e = this.opts) == null ? void 0 : _e.sourceSampleRate) == null ? void 0 : _f[source];
332
+ let pathRate;
333
+ const pathMap = ((_g = this.opts) == null ? void 0 : _g.pathSampleRate) || {};
334
+ const prefixes = Object.keys(pathMap);
335
+ if (prefixes.length) {
336
+ let best = "";
337
+ for (let i = 0; i < prefixes.length; i += 1) {
338
+ const p2 = prefixes[i];
339
+ if (url.startsWith(p2) && p2.length >= best.length)
340
+ best = p2;
341
+ }
342
+ if (best)
343
+ pathRate = pathMap[best];
344
+ }
345
+ const baseRate = (() => {
346
+ var _a2;
347
+ if (typeof levelRate === "number")
348
+ return levelRate;
349
+ if (typeof sourceRate === "number")
350
+ return sourceRate;
351
+ if (typeof pathRate === "number")
352
+ return pathRate;
353
+ const sr = (_a2 = this.opts) == null ? void 0 : _a2.sampleRate;
354
+ return typeof sr === "number" ? sr : 1;
355
+ })();
356
+ const rate = Math.max(0, Math.min(1, baseRate));
357
+ if (rate >= 1)
358
+ return true;
359
+ const seed = `${String(traceId || "")}|${String(message || "")}|${String(this.sessionId || "")}|${String(level)}|${String(source)}|${String(url)}`;
360
+ const p = hashToProb(seed);
361
+ return p < rate;
362
+ }
363
+ /**
364
+ * 记录事件
365
+ */
366
+ doTrack(logEvent) {
367
+ return __async(this, null, function* () {
368
+ var _a, _b, _c;
369
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "track", logEvent);
370
+ if (this.opts.enableBatch && this.queueManager) {
371
+ this.queueManager.enqueue(logEvent);
372
+ if (this.queueManager.size() >= this.opts.batchSize) {
373
+ logDebug(!!((_b = this.opts) == null ? void 0 : _b.debug), "Queue size reached batch size, flushing immediately");
374
+ yield this.flush();
375
+ }
376
+ } else {
377
+ try {
378
+ yield this.sendEvent(logEvent);
379
+ } catch (e) {
380
+ logDebug(!!((_c = this.opts) == null ? void 0 : _c.debug), "track failed", e);
381
+ }
382
+ }
383
+ });
384
+ }
385
+ /**
386
+ * 手动刷新队列,立即上报所有待发送日志
387
+ */
388
+ flush() {
389
+ return __async(this, null, function* () {
390
+ var _a, _b, _c, _d;
391
+ if (!this.queueManager || this.queueManager.size() === 0) {
392
+ return;
393
+ }
394
+ if (this.isSending) {
395
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), "Already sending, skip flush");
396
+ return;
397
+ }
398
+ this.isSending = true;
399
+ logDebug(!!((_b = this.opts) == null ? void 0 : _b.debug), `Flushing ${this.queueManager.size()} events`);
400
+ try {
401
+ const events = this.queueManager.peek(this.queueManager.size());
402
+ if (events.length === 0) {
403
+ return;
404
+ }
405
+ yield this.sendBatch(events);
406
+ this.queueManager.dequeue(events.length);
407
+ logDebug(!!((_c = this.opts) == null ? void 0 : _c.debug), `Flushed ${events.length} events successfully`);
408
+ } catch (error) {
409
+ logDebug(!!((_d = this.opts) == null ? void 0 : _d.debug), "Flush failed", error);
410
+ } finally {
411
+ this.isSending = false;
412
+ }
413
+ });
414
+ }
415
+ /**
416
+ * 销毁实例
417
+ */
418
+ destroy() {
419
+ return __async(this, null, function* () {
420
+ this.closed = true;
421
+ if (this.batchTimer) {
422
+ clearInterval(this.batchTimer);
423
+ this.batchTimer = null;
424
+ }
425
+ yield this.flush();
426
+ if (this.queueManager) {
427
+ this.queueManager.clear();
428
+ }
429
+ if (this.retryManager) {
430
+ this.retryManager.clear();
431
+ }
432
+ if (this.offJs) {
433
+ this.offJs();
434
+ this.offJs = void 0;
435
+ }
436
+ if (this.offPromise) {
437
+ this.offPromise();
438
+ this.offPromise = void 0;
439
+ }
440
+ if (this.offResource) {
441
+ this.offResource();
442
+ this.offResource = void 0;
443
+ }
444
+ if (this.offWxError) {
445
+ this.offWxError();
446
+ this.offWxError = void 0;
447
+ }
448
+ if (this.offWxUnhandled) {
449
+ this.offWxUnhandled();
450
+ this.offWxUnhandled = void 0;
451
+ }
452
+ this.initialized = false;
453
+ this.sessionId = void 0;
454
+ LoggerSDK.instance = void 0;
455
+ });
456
+ }
457
+ // ========== 内部方法 ===========
458
+ /**
459
+ * 发送单个事件(带重试)
460
+ */
461
+ sendEvent(event) {
462
+ return __async(this, null, function* () {
463
+ const sendFn = () => __async(this, null, function* () {
464
+ var _a;
465
+ yield (_a = this.transporter) == null ? void 0 : _a.send({
466
+ appId: event.appId,
467
+ appStage: event.stage,
468
+ items: [
469
+ {
470
+ level: event.level === "FATAL" ? "ERROR" : event.level,
471
+ traceId: event.traceId,
472
+ frontendId: event.frontendId,
473
+ location: event.location,
474
+ message: event.message,
475
+ throwable: event.throwable
476
+ }
477
+ ]
478
+ });
479
+ });
480
+ if (this.opts.enableRetry && this.retryManager) {
481
+ yield this.retryManager.executeWithRetry(event.logId, sendFn);
482
+ } else {
483
+ yield sendFn();
484
+ }
485
+ });
486
+ }
487
+ /**
488
+ * 批量发送事件(带重试)
489
+ */
490
+ sendBatch(events) {
491
+ return __async(this, null, function* () {
492
+ var _a;
493
+ if (events.length === 0)
494
+ return;
495
+ const groups = /* @__PURE__ */ new Map();
496
+ for (let i = 0; i < events.length; i += 1) {
497
+ const e = events[i];
498
+ const key = `${e.appId}|${e.stage}`;
499
+ const arr = groups.get(key);
500
+ if (arr)
501
+ arr.push(e);
502
+ else
503
+ groups.set(key, [e]);
504
+ }
505
+ const batchSize = Math.min(200, ((_a = this.opts) == null ? void 0 : _a.batchSize) || 50);
506
+ const entries = Array.from(groups.entries());
507
+ const tasks = [];
508
+ for (let gi = 0; gi < entries.length; gi += 1) {
509
+ const [key, group] = entries[gi];
510
+ group.sort((a, b) => a.seq - b.seq);
511
+ for (let i = 0; i < group.length; i += batchSize) {
512
+ const chunk = group.slice(i, i + batchSize);
513
+ if (chunk.length > 0) {
514
+ const batchId = `batch_${now()}_${Math.random().toString(36).substring(2, 9)}_${key}_${i}`;
515
+ const sendFn = () => __async(this, null, function* () {
516
+ var _a2;
517
+ yield (_a2 = this.transporter) == null ? void 0 : _a2.send({
518
+ appId: chunk[0].appId,
519
+ appStage: chunk[0].stage,
520
+ items: chunk.map((event) => ({
521
+ level: event.level === "FATAL" ? "ERROR" : event.level,
522
+ traceId: event.traceId,
523
+ frontendId: event.frontendId,
524
+ location: event.location,
525
+ message: event.message,
526
+ throwable: event.throwable
527
+ }))
528
+ });
529
+ });
530
+ const task = this.opts.enableRetry && this.retryManager ? this.retryManager.executeWithRetry(batchId, sendFn) : sendFn();
531
+ tasks.push(task);
532
+ }
533
+ }
534
+ }
535
+ yield Promise.all(tasks);
536
+ });
537
+ }
538
+ /**
539
+ * 启动批量上报定时器
540
+ */
541
+ startBatchTimer() {
542
+ var _a;
543
+ if (this.batchTimer)
544
+ return;
545
+ this.batchTimer = setInterval(() => {
546
+ var _a2;
547
+ if (!this.closed && this.queueManager && this.queueManager.size() > 0) {
548
+ logDebug(!!((_a2 = this.opts) == null ? void 0 : _a2.debug), "Batch timer triggered, flushing queue");
549
+ this.flush().catch((error) => {
550
+ var _a3;
551
+ logDebug(!!((_a3 = this.opts) == null ? void 0 : _a3.debug), "Batch timer flush failed", error);
552
+ });
553
+ }
554
+ }, this.opts.batchInterval);
555
+ logDebug(!!((_a = this.opts) == null ? void 0 : _a.debug), `Batch timer started with interval ${this.opts.batchInterval}ms`);
556
+ }
557
+ /**
558
+ * 监听页面卸载事件
559
+ */
560
+ attachUnloadHandlers() {
561
+ var _a;
562
+ if (((_a = this.opts) == null ? void 0 : _a.enableAutoCapture) === false)
563
+ return;
564
+ if (!isBrowser())
565
+ return;
566
+ const win = window;
567
+ document.addEventListener && document.addEventListener("visibilitychange", () => {
568
+ var _a2;
569
+ try {
570
+ if (document.visibilityState === "hidden") {
571
+ this.flush().catch(() => {
572
+ });
573
+ logDebug(!!((_a2 = this.opts) == null ? void 0 : _a2.debug), "Page hidden, flushed queue");
574
+ }
575
+ } catch (e) {
576
+ }
577
+ });
578
+ win.addEventListener && win.addEventListener("pagehide", () => {
579
+ var _a2, _b;
580
+ try {
581
+ logDebug(!!((_a2 = this.opts) == null ? void 0 : _a2.debug), "Page hide, flushed queue");
582
+ this.flush().catch(() => {
583
+ });
584
+ logDebug(!!((_b = this.opts) == null ? void 0 : _b.debug), "Page hide, flushed queue");
585
+ } catch (e) {
586
+ }
587
+ });
588
+ win.addEventListener && win.addEventListener("beforeunload", () => {
589
+ var _a2, _b;
590
+ try {
591
+ logDebug(!!((_a2 = this.opts) == null ? void 0 : _a2.debug), "Page unload, flushed queue");
592
+ this.flush().catch(() => {
593
+ });
594
+ logDebug(!!((_b = this.opts) == null ? void 0 : _b.debug), "Page unload, flushed queue");
595
+ } catch (e) {
596
+ }
597
+ });
598
+ }
599
+ /**
600
+ * 初始化 SDK(注册/初始化)
601
+ */
602
+ initSDK(opts, onSuccess) {
603
+ var _a;
604
+ HttpClient.post(
605
+ getRegisterApi(((_a = this.opts) == null ? void 0 : _a.env) || "develop"),
606
+ {
607
+ appId: opts.appId,
608
+ message: "init",
609
+ appStage: opts.logStage,
610
+ location: "",
611
+ userId: opts.userId,
612
+ storeCode: opts.storeCode
613
+ },
614
+ opts.token
615
+ ).then((response) => __async(this, null, function* () {
616
+ var _a2, _b, _c;
617
+ logDebug(!!((_a2 = this.opts) == null ? void 0 : _a2.debug), "Register success", response);
618
+ if (!response) {
619
+ return;
620
+ }
621
+ const { type, response: res, error } = response;
622
+ let isSuccess = false;
623
+ let data;
624
+ if (type === "wechat" && (res == null ? void 0 : res.statusCode) === 200) {
625
+ isSuccess = true;
626
+ data = res.data.data;
627
+ } else if (type === "fetch") {
628
+ const responseData = yield (_b = res == null ? void 0 : res.json) == null ? void 0 : _b.call(res);
629
+ logDebug(!!((_c = this.opts) == null ? void 0 : _c.debug), "Register fetch response", responseData);
630
+ if ((responseData == null ? void 0 : responseData.code) === 0) {
631
+ isSuccess = true;
632
+ data = responseData.data;
633
+ }
634
+ } else if (type === "xhr") {
635
+ isSuccess = true;
636
+ }
637
+ if (isSuccess && data) {
638
+ onSuccess(data);
639
+ }
640
+ })).catch((err) => {
641
+ var _a2;
642
+ logDebug(!!((_a2 = this.opts) == null ? void 0 : _a2.debug), "Failed to initialize SDK", err);
643
+ });
644
+ }
645
+ };
646
+ var loggerSDK_default = LoggerSDK;
647
+ export {
648
+ LoggerSDK,
649
+ loggerSDK_default as default
650
+ };