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