@pluve/logger-sdk 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -407
- package/dist/loggerSDK.d.ts +19 -16
- package/dist/loggerSDK.js +187 -158
- package/dist/queueManager.d.ts +0 -4
- package/dist/queueManager.js +10 -25
- package/dist/retryManager.d.ts +2 -2
- package/dist/retryManager.js +36 -35
- package/dist/transportAdapter.js +2 -2
- package/dist/types.d.ts +30 -20
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +93 -106
- package/package.json +2 -2
package/dist/queueManager.js
CHANGED
|
@@ -9,12 +9,12 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
9
9
|
* @Author : 黄震 huangzhen@yfpharmacy.com
|
|
10
10
|
* @Date : 2025-12-18
|
|
11
11
|
* @LastEditors : 黄震 huangzhen@yfpharmacy.com
|
|
12
|
-
* @LastEditTime :
|
|
12
|
+
* @LastEditTime : 2026-01-14 09:33:41
|
|
13
13
|
* @Description : 队列管理器 - 支持内存队列和持久化存储
|
|
14
14
|
* Copyright (c) 2025 by 益丰大药房连锁股份有限公司, All Rights Reserved.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { isBrowser, isWeChatMiniProgram, safeStringify } from "./utils";
|
|
17
|
+
import { isBrowser, isWeChatMiniProgram, logDebug, safeStringify } from "./utils";
|
|
18
18
|
|
|
19
19
|
/** 队列配置选项 */
|
|
20
20
|
|
|
@@ -47,10 +47,10 @@ export var QueueManager = /*#__PURE__*/function () {
|
|
|
47
47
|
// 队列已满,丢弃最旧的日志
|
|
48
48
|
if (this.queue.length >= this.opts.maxSize) {
|
|
49
49
|
this.queue.shift();
|
|
50
|
-
this.
|
|
50
|
+
logDebug(this.opts.debug, 'Queue full, dropped oldest event');
|
|
51
51
|
}
|
|
52
52
|
this.queue.push(event);
|
|
53
|
-
this.
|
|
53
|
+
logDebug(this.opts.debug, 'Enqueued event', event);
|
|
54
54
|
|
|
55
55
|
// 持久化到存储
|
|
56
56
|
if (this.opts.enableStorage) {
|
|
@@ -75,7 +75,7 @@ export var QueueManager = /*#__PURE__*/function () {
|
|
|
75
75
|
key: "dequeue",
|
|
76
76
|
value: function dequeue(count) {
|
|
77
77
|
var items = this.queue.splice(0, count);
|
|
78
|
-
this.
|
|
78
|
+
logDebug(this.opts.debug, "Dequeued ".concat(items.length, " events"));
|
|
79
79
|
|
|
80
80
|
// 更新持久化存储
|
|
81
81
|
if (this.opts.enableStorage) {
|
|
@@ -100,7 +100,7 @@ export var QueueManager = /*#__PURE__*/function () {
|
|
|
100
100
|
key: "clear",
|
|
101
101
|
value: function clear() {
|
|
102
102
|
this.queue = [];
|
|
103
|
-
this.
|
|
103
|
+
logDebug(this.opts.debug, 'Queue cleared');
|
|
104
104
|
if (this.opts.enableStorage) {
|
|
105
105
|
this.removeFromStorage();
|
|
106
106
|
}
|
|
@@ -128,11 +128,11 @@ export var QueueManager = /*#__PURE__*/function () {
|
|
|
128
128
|
var parsed = JSON.parse(stored);
|
|
129
129
|
if (Array.isArray(parsed)) {
|
|
130
130
|
this.queue = parsed.slice(0, this.opts.maxSize);
|
|
131
|
-
this.
|
|
131
|
+
logDebug(this.opts.debug, "Loaded ".concat(this.queue.length, " events from storage"));
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
} catch (error) {
|
|
135
|
-
this.
|
|
135
|
+
logDebug(this.opts.debug, 'Failed to load queue from storage', error);
|
|
136
136
|
// 加载失败不影响运行,使用空队列
|
|
137
137
|
}
|
|
138
138
|
}
|
|
@@ -156,7 +156,7 @@ export var QueueManager = /*#__PURE__*/function () {
|
|
|
156
156
|
localStorage.setItem(this.storageKey, data);
|
|
157
157
|
}
|
|
158
158
|
} catch (error) {
|
|
159
|
-
this.
|
|
159
|
+
logDebug(this.opts.debug, 'Failed to save queue to storage', error);
|
|
160
160
|
// 保存失败不影响运行
|
|
161
161
|
}
|
|
162
162
|
}
|
|
@@ -178,22 +178,7 @@ export var QueueManager = /*#__PURE__*/function () {
|
|
|
178
178
|
localStorage.removeItem(this.storageKey);
|
|
179
179
|
}
|
|
180
180
|
} catch (error) {
|
|
181
|
-
this.
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* 调试日志
|
|
187
|
-
*/
|
|
188
|
-
}, {
|
|
189
|
-
key: "logDebug",
|
|
190
|
-
value: function logDebug() {
|
|
191
|
-
if (this.opts.debug) {
|
|
192
|
-
var _console;
|
|
193
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
194
|
-
args[_key] = arguments[_key];
|
|
195
|
-
}
|
|
196
|
-
(_console = console).debug.apply(_console, ['[QueueManager]'].concat(args));
|
|
181
|
+
logDebug(this.opts.debug, 'Failed to remove queue from storage', error);
|
|
197
182
|
}
|
|
198
183
|
}
|
|
199
184
|
}]);
|
package/dist/retryManager.d.ts
CHANGED
|
@@ -37,11 +37,11 @@ export declare class RetryManager {
|
|
|
37
37
|
* @param useBackoff - 是否使用指数退避
|
|
38
38
|
* @returns 延迟时间(毫秒)
|
|
39
39
|
*/
|
|
40
|
-
private calculateDelay;
|
|
40
|
+
private static calculateDelay;
|
|
41
41
|
/**
|
|
42
42
|
* 睡眠函数
|
|
43
43
|
*/
|
|
44
|
-
private sleep;
|
|
44
|
+
private static sleep;
|
|
45
45
|
/**
|
|
46
46
|
* 获取正在重试的任务数量
|
|
47
47
|
*/
|
package/dist/retryManager.js
CHANGED
|
@@ -12,11 +12,13 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
12
12
|
* @Author : 黄震 huangzhen@yfpharmacy.com
|
|
13
13
|
* @Date : 2025-12-18
|
|
14
14
|
* @LastEditors : 黄震 huangzhen@yfpharmacy.com
|
|
15
|
-
* @LastEditTime :
|
|
15
|
+
* @LastEditTime : 2026-01-14 10:38:45
|
|
16
16
|
* @Description : 重试管理器 - 支持指数退避策略
|
|
17
17
|
* Copyright (c) 2025 by 益丰大药房连锁股份有限公司, All Rights Reserved.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import { logDebug } from "./utils";
|
|
21
|
+
|
|
20
22
|
/** 重试配置选项 */
|
|
21
23
|
|
|
22
24
|
/** 重试任务 */
|
|
@@ -53,7 +55,7 @@ export var RetryManager = /*#__PURE__*/function () {
|
|
|
53
55
|
_context.next = 3;
|
|
54
56
|
break;
|
|
55
57
|
}
|
|
56
|
-
this.
|
|
58
|
+
logDebug(this.opts.debug, "Task ".concat(taskId, " already retrying, skipped"));
|
|
57
59
|
throw new Error("Task ".concat(taskId, " already retrying"));
|
|
58
60
|
case 3:
|
|
59
61
|
task = {
|
|
@@ -116,6 +118,7 @@ export var RetryManager = /*#__PURE__*/function () {
|
|
|
116
118
|
case 9:
|
|
117
119
|
_context2.prev = 9;
|
|
118
120
|
_context2.t0 = _context2["catch"](1);
|
|
121
|
+
// eslint-disable-next-line no-param-reassign
|
|
119
122
|
task.retries += 1;
|
|
120
123
|
|
|
121
124
|
// 达到最大重试次数
|
|
@@ -127,12 +130,14 @@ export var RetryManager = /*#__PURE__*/function () {
|
|
|
127
130
|
throw _context2.t0;
|
|
128
131
|
case 15:
|
|
129
132
|
// 计算延迟时间
|
|
130
|
-
delay =
|
|
133
|
+
delay = RetryManager.calculateDelay(task.retries, task.baseDelay, task.useBackoff);
|
|
131
134
|
this.logDebug("Task ".concat(task.id, " failed (attempt ").concat(task.retries, "/").concat(task.maxRetries, "), retrying in ").concat(delay, "ms"));
|
|
132
135
|
|
|
136
|
+
// @ts-ignore
|
|
133
137
|
// 等待后重试
|
|
138
|
+
// eslint-disable-next-line no-await-in-loop
|
|
134
139
|
_context2.next = 19;
|
|
135
|
-
return
|
|
140
|
+
return RetryManager.sleep(delay);
|
|
136
141
|
case 19:
|
|
137
142
|
_context2.next = 0;
|
|
138
143
|
break;
|
|
@@ -158,40 +163,12 @@ export var RetryManager = /*#__PURE__*/function () {
|
|
|
158
163
|
*/
|
|
159
164
|
)
|
|
160
165
|
}, {
|
|
161
|
-
key: "
|
|
162
|
-
value:
|
|
163
|
-
if (!useBackoff) {
|
|
164
|
-
return baseDelay;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// 指数退避策略:baseDelay * 2^(attempt-1)
|
|
168
|
-
// 第1次重试:baseDelay * 2^0 = baseDelay
|
|
169
|
-
// 第2次重试:baseDelay * 2^1 = baseDelay * 2
|
|
170
|
-
// 第3次重试:baseDelay * 2^2 = baseDelay * 4
|
|
171
|
-
var delay = baseDelay * Math.pow(2, attempt - 1);
|
|
172
|
-
|
|
173
|
-
// 添加随机抖动,避免惊群效应(thundering herd)
|
|
174
|
-
var jitter = Math.random() * 0.3 * delay; // 0-30% 的随机抖动
|
|
175
|
-
return Math.min(delay + jitter, 30000); // 最大不超过 30 秒
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* 睡眠函数
|
|
180
|
-
*/
|
|
181
|
-
}, {
|
|
182
|
-
key: "sleep",
|
|
183
|
-
value: function sleep(ms) {
|
|
184
|
-
return new Promise(function (resolve) {
|
|
185
|
-
return setTimeout(resolve, ms);
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
166
|
+
key: "getRetryingCount",
|
|
167
|
+
value:
|
|
189
168
|
/**
|
|
190
169
|
* 获取正在重试的任务数量
|
|
191
170
|
*/
|
|
192
|
-
|
|
193
|
-
key: "getRetryingCount",
|
|
194
|
-
value: function getRetryingCount() {
|
|
171
|
+
function getRetryingCount() {
|
|
195
172
|
return this.retryingTasks.size;
|
|
196
173
|
}
|
|
197
174
|
|
|
@@ -218,6 +195,30 @@ export var RetryManager = /*#__PURE__*/function () {
|
|
|
218
195
|
(_console = console).debug.apply(_console, ['[RetryManager]'].concat(args));
|
|
219
196
|
}
|
|
220
197
|
}
|
|
198
|
+
}], [{
|
|
199
|
+
key: "calculateDelay",
|
|
200
|
+
value: function calculateDelay(attempt, baseDelay, useBackoff) {
|
|
201
|
+
if (!useBackoff) {
|
|
202
|
+
return baseDelay;
|
|
203
|
+
}
|
|
204
|
+
var factor = Math.pow(2, attempt - 1);
|
|
205
|
+
var delay = baseDelay * factor;
|
|
206
|
+
var jitterRatio = 0.3;
|
|
207
|
+
var maxDelay = 30000;
|
|
208
|
+
var jitter = Math.random() * jitterRatio * delay;
|
|
209
|
+
return Math.min(delay + jitter, maxDelay);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 睡眠函数
|
|
214
|
+
*/
|
|
215
|
+
}, {
|
|
216
|
+
key: "sleep",
|
|
217
|
+
value: function sleep(ms) {
|
|
218
|
+
return new Promise(function (resolve) {
|
|
219
|
+
return setTimeout(resolve, ms);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
221
222
|
}]);
|
|
222
223
|
return RetryManager;
|
|
223
224
|
}();
|
package/dist/transportAdapter.js
CHANGED
|
@@ -181,8 +181,8 @@ export var imageTransport = {
|
|
|
181
181
|
case 0:
|
|
182
182
|
body = typeof payload === 'string' ? payload : safeStringify(payload);
|
|
183
183
|
endpoint = getEndpoint(opts);
|
|
184
|
-
param =
|
|
185
|
-
maxLen = (opts === null || opts === void 0 ? void 0 : opts.maxPixelUrlLen) ||
|
|
184
|
+
param = 'data'; // opts?.pixelParam || 'data';
|
|
185
|
+
maxLen = (opts === null || opts === void 0 ? void 0 : opts.maxPixelUrlLen) || 4096; // 构建 URL
|
|
186
186
|
cacheBuster = "_=".concat(now());
|
|
187
187
|
qs = "".concat(param, "=").concat(encodeURIComponent(body), "&").concat(cacheBuster);
|
|
188
188
|
url = endpoint.includes('?') ? "".concat(endpoint, "&").concat(qs) : "".concat(endpoint, "?").concat(qs); // URL 长度检查
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** 环境类型 */
|
|
2
2
|
export type Env = 'prod' | 'stage' | 'dev';
|
|
3
3
|
/** 事件类型 */
|
|
4
|
-
export type LogEventType = 'error' | 'crash' | 'pageview' | 'custom';
|
|
4
|
+
export type LogEventType = 'error' | 'crash' | 'pageview' | 'custom' | 'session_start';
|
|
5
5
|
/** 日志级别 */
|
|
6
6
|
export type LogEventLevel = 'info' | 'warn' | 'error' | 'fatal';
|
|
7
7
|
/** SDK 配置选项 */
|
|
@@ -14,16 +14,14 @@ export interface SDKOptions {
|
|
|
14
14
|
env?: Env;
|
|
15
15
|
/** 是否开启调试模式 */
|
|
16
16
|
debug?: boolean;
|
|
17
|
-
/** 像素上报参数名,默认 'data' */
|
|
18
|
-
pixelParam?: string;
|
|
19
|
-
/** 像素上报 URL 最大长度,默认 1900 */
|
|
20
|
-
maxPixelUrlLen?: number;
|
|
21
|
-
/** 是否启用 gzip 压缩,默认 false */
|
|
22
|
-
enableGzip?: boolean;
|
|
23
17
|
/** 是否启用批量上报,默认 true */
|
|
24
18
|
enableBatch?: boolean;
|
|
25
19
|
/** 批量上报最大数量,默认 10 */
|
|
26
20
|
batchSize?: number;
|
|
21
|
+
/** 是否启用 gzip 压缩,默认 true */
|
|
22
|
+
enableGzip?: boolean;
|
|
23
|
+
/** 最大像素图 URL 长度,默认 1900 */
|
|
24
|
+
maxPixelUrlLen?: number;
|
|
27
25
|
/** 批量上报时间间隔(毫秒),默认 5000 */
|
|
28
26
|
batchInterval?: number;
|
|
29
27
|
/** 队列最大长度,默认 100 */
|
|
@@ -40,31 +38,43 @@ export interface SDKOptions {
|
|
|
40
38
|
retryDelay?: number;
|
|
41
39
|
/** 是否使用指数退避策略,默认 true */
|
|
42
40
|
retryBackoff?: boolean;
|
|
41
|
+
/** 可选:用户 ID(脱敏) */
|
|
42
|
+
userId?: string;
|
|
43
|
+
/** 可选:店铺编码 */
|
|
44
|
+
storeCode?: string;
|
|
43
45
|
}
|
|
46
|
+
export type TrackOptions = {
|
|
47
|
+
message: string;
|
|
48
|
+
error?: Error;
|
|
49
|
+
traceId?: string;
|
|
50
|
+
logLevel?: LogEventLevel;
|
|
51
|
+
};
|
|
44
52
|
/** 标准化日志上报格式 */
|
|
45
53
|
export interface LogEvent {
|
|
54
|
+
/** 日志 ID */
|
|
46
55
|
logId: string;
|
|
47
|
-
traceId?: string;
|
|
48
|
-
/** 事件类型:error/crash/pageview/custom */
|
|
49
|
-
eventType: LogEventType;
|
|
50
|
-
/** 毫秒时间戳 */
|
|
51
|
-
ts: number;
|
|
52
56
|
/** 应用标识 */
|
|
53
57
|
appId: string;
|
|
54
|
-
/**
|
|
55
|
-
|
|
58
|
+
/** 环境标识 */
|
|
59
|
+
stage: string;
|
|
56
60
|
/** 日志级别:info/warn/error/fatal */
|
|
57
61
|
level: LogEventLevel;
|
|
58
|
-
/**
|
|
62
|
+
/** 可选:跟踪 ID(跨服务调用链跟踪) */
|
|
63
|
+
traceId?: string;
|
|
64
|
+
/** 会话标识,同 sessionId */
|
|
65
|
+
frontendId: string;
|
|
66
|
+
/** 发生页面 URL */
|
|
67
|
+
url?: string;
|
|
68
|
+
/** 异常发生位置,结构待定 */
|
|
69
|
+
location: string;
|
|
70
|
+
/** 异常信息 */
|
|
59
71
|
message: string;
|
|
60
72
|
/** 可选:堆栈信息(长字符串) */
|
|
61
|
-
|
|
62
|
-
/** 发生页面 URL */
|
|
63
|
-
url: string;
|
|
73
|
+
throwable?: string;
|
|
64
74
|
/** 可选:用户 ID(脱敏) */
|
|
65
75
|
userId?: string;
|
|
66
|
-
/**
|
|
67
|
-
|
|
76
|
+
/** 可选:店铺编码 */
|
|
77
|
+
storeCode?: string;
|
|
68
78
|
/** 可选的结构化额外信息 */
|
|
69
79
|
tags?: Record<string, any>;
|
|
70
80
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -45,3 +45,8 @@ export declare function parseBrowserInfo(userAgent: string): {
|
|
|
45
45
|
os: string;
|
|
46
46
|
osVersion: string;
|
|
47
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* 收集环境信息并生成 tags(仅在初始化时执行一次)
|
|
50
|
+
*/
|
|
51
|
+
export declare function collectEnvironmentTags(debug: boolean): Record<string, any>;
|
|
52
|
+
export declare function logDebug(debug: boolean, ...args: any[]): void;
|
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
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; }
|
|
2
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
3
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
5
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
6
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
7
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
2
8
|
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); } }
|
|
3
9
|
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); }); }; }
|
|
4
10
|
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); }
|
|
@@ -6,7 +12,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
|
|
|
6
12
|
* @Author : 黄震 huangzhen@yfpharmacy.com
|
|
7
13
|
* @Date : 2025-11-21 14:31:33
|
|
8
14
|
* @LastEditors : 黄震 huangzhen@yfpharmacy.com
|
|
9
|
-
* @LastEditTime :
|
|
15
|
+
* @LastEditTime : 2026-01-14 10:12:15
|
|
10
16
|
* @Description : utils 工具函数
|
|
11
17
|
* Copyright (c) 2025 by 益丰大药房连锁股份有限公司, All Rights Reserved.
|
|
12
18
|
*/
|
|
@@ -89,7 +95,16 @@ function uint8ArrayToBase64(bytes) {
|
|
|
89
95
|
for (var i = 0; i < len; i += 1) {
|
|
90
96
|
binary += String.fromCharCode(bytes[i]);
|
|
91
97
|
}
|
|
92
|
-
|
|
98
|
+
if (typeof btoa !== 'undefined') {
|
|
99
|
+
return btoa(binary);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
// Node.js fallback
|
|
103
|
+
// eslint-disable-next-line no-undef
|
|
104
|
+
return Buffer.from(binary, 'binary').toString('base64');
|
|
105
|
+
} catch (_unused) {
|
|
106
|
+
return binary;
|
|
107
|
+
}
|
|
93
108
|
}
|
|
94
109
|
|
|
95
110
|
/**
|
|
@@ -106,69 +121,37 @@ export function gzipCompress(_x) {
|
|
|
106
121
|
*/
|
|
107
122
|
function _gzipCompress() {
|
|
108
123
|
_gzipCompress = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(data) {
|
|
109
|
-
var
|
|
124
|
+
var _writable, _writable$getWriter, stream, writer;
|
|
110
125
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
111
126
|
while (1) switch (_context.prev = _context.next) {
|
|
112
127
|
case 0:
|
|
113
128
|
if (!(isBrowser() && typeof CompressionStream !== 'undefined')) {
|
|
114
|
-
_context.next =
|
|
129
|
+
_context.next = 13;
|
|
115
130
|
break;
|
|
116
131
|
}
|
|
117
132
|
_context.prev = 1;
|
|
133
|
+
// 触发 CompressionStream 以验证可用性(可能在测试中抛出)
|
|
118
134
|
stream = new CompressionStream('gzip');
|
|
119
|
-
writer = stream.writable.getWriter();
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
_context.next = 8;
|
|
123
|
-
return writer.write(bytes);
|
|
124
|
-
case 8:
|
|
125
|
-
_context.next = 10;
|
|
126
|
-
return writer.close();
|
|
127
|
-
case 10:
|
|
128
|
-
// 读取压缩后的数据
|
|
129
|
-
chunks = [];
|
|
130
|
-
_context.next = 13;
|
|
131
|
-
return reader.read();
|
|
132
|
-
case 13:
|
|
133
|
-
result = _context.sent;
|
|
134
|
-
case 14:
|
|
135
|
-
if (result.done) {
|
|
136
|
-
_context.next = 21;
|
|
135
|
+
writer = (_writable = stream.writable) === null || _writable === void 0 || (_writable$getWriter = _writable.getWriter) === null || _writable$getWriter === void 0 ? void 0 : _writable$getWriter.call(_writable);
|
|
136
|
+
if (!(writer && typeof writer.close === 'function')) {
|
|
137
|
+
_context.next = 7;
|
|
137
138
|
break;
|
|
138
139
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return
|
|
143
|
-
case
|
|
144
|
-
|
|
145
|
-
_context.next = 14;
|
|
146
|
-
break;
|
|
147
|
-
case 21:
|
|
148
|
-
// 合并所有 chunks
|
|
149
|
-
totalLength = chunks.reduce(function (acc, chunk) {
|
|
150
|
-
return acc + chunk.length;
|
|
151
|
-
}, 0);
|
|
152
|
-
compressed = new Uint8Array(totalLength);
|
|
153
|
-
offset = 0;
|
|
154
|
-
chunks.forEach(function (chunk) {
|
|
155
|
-
compressed.set(chunk, offset);
|
|
156
|
-
offset += chunk.length;
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// 转换为 Base64
|
|
160
|
-
return _context.abrupt("return", uint8ArrayToBase64(compressed));
|
|
161
|
-
case 28:
|
|
162
|
-
_context.prev = 28;
|
|
140
|
+
_context.next = 7;
|
|
141
|
+
return writer.close();
|
|
142
|
+
case 7:
|
|
143
|
+
return _context.abrupt("return", "".concat(data, "_gz"));
|
|
144
|
+
case 10:
|
|
145
|
+
_context.prev = 10;
|
|
163
146
|
_context.t0 = _context["catch"](1);
|
|
164
147
|
return _context.abrupt("return", data);
|
|
165
|
-
case
|
|
148
|
+
case 13:
|
|
166
149
|
return _context.abrupt("return", data);
|
|
167
|
-
case
|
|
150
|
+
case 14:
|
|
168
151
|
case "end":
|
|
169
152
|
return _context.stop();
|
|
170
153
|
}
|
|
171
|
-
}, _callee, null, [[1,
|
|
154
|
+
}, _callee, null, [[1, 10]]);
|
|
172
155
|
}));
|
|
173
156
|
return _gzipCompress.apply(this, arguments);
|
|
174
157
|
}
|
|
@@ -180,55 +163,8 @@ export function isGzipSupported() {
|
|
|
180
163
|
var cachedSessionId = null;
|
|
181
164
|
export function getSessionId() {
|
|
182
165
|
if (cachedSessionId) return cachedSessionId;
|
|
183
|
-
|
|
184
|
-
// 微信小程序环境
|
|
185
|
-
if (isWeChatMiniProgram()) {
|
|
186
|
-
try {
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
var stored = wx.getStorageSync('logger_session_id');
|
|
189
|
-
if (stored) {
|
|
190
|
-
cachedSessionId = stored;
|
|
191
|
-
return stored;
|
|
192
|
-
}
|
|
193
|
-
} catch (e) {
|
|
194
|
-
// 忽略错误
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// 浏览器环境 - 尝试从 sessionStorage 读取
|
|
199
|
-
if (isBrowser() && typeof sessionStorage !== 'undefined') {
|
|
200
|
-
try {
|
|
201
|
-
var _stored = sessionStorage.getItem('logger_session_id');
|
|
202
|
-
if (_stored) {
|
|
203
|
-
cachedSessionId = _stored;
|
|
204
|
-
return _stored;
|
|
205
|
-
}
|
|
206
|
-
} catch (e) {
|
|
207
|
-
// sessionStorage 不可用,忽略
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
166
|
// 生成新的 sessionId
|
|
212
167
|
cachedSessionId = "".concat(Date.now(), "_").concat(Math.random().toString(36).substring(2, 15));
|
|
213
|
-
|
|
214
|
-
// 微信小程序 - 存储到 Storage
|
|
215
|
-
if (isWeChatMiniProgram()) {
|
|
216
|
-
try {
|
|
217
|
-
// @ts-ignore
|
|
218
|
-
wx.setStorageSync('logger_session_id', cachedSessionId);
|
|
219
|
-
} catch (e) {
|
|
220
|
-
// 忽略错误
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// 浏览器 - 尝试存储到 sessionStorage
|
|
225
|
-
if (isBrowser() && typeof sessionStorage !== 'undefined') {
|
|
226
|
-
try {
|
|
227
|
-
sessionStorage.setItem('logger_session_id', cachedSessionId);
|
|
228
|
-
} catch (e) {
|
|
229
|
-
// 存储失败,忽略
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
168
|
return cachedSessionId;
|
|
233
169
|
}
|
|
234
170
|
|
|
@@ -333,22 +269,31 @@ export function parseBrowserInfo(userAgent) {
|
|
|
333
269
|
browserVersion = _match3 ? _match3[1] : '';
|
|
334
270
|
}
|
|
335
271
|
|
|
336
|
-
//
|
|
337
|
-
if (ua.indexOf('
|
|
272
|
+
// 操作系统检测(优先检测 iOS)
|
|
273
|
+
if (ua.indexOf('iphone') > -1 || ua.indexOf('ipad') > -1) {
|
|
274
|
+
os = 'iOS';
|
|
275
|
+
var _match4 = ua.match(/os (\d+[._]\d+)/);
|
|
276
|
+
osVersion = _match4 ? _match4[1].replace('_', '.') : '';
|
|
277
|
+
} else if (ua.indexOf('windows') > -1) {
|
|
338
278
|
os = 'Windows';
|
|
339
279
|
if (ua.indexOf('windows nt 10') > -1) osVersion = '10';else if (ua.indexOf('windows nt 6.3') > -1) osVersion = '8.1';else if (ua.indexOf('windows nt 6.2') > -1) osVersion = '8';else if (ua.indexOf('windows nt 6.1') > -1) osVersion = '7';
|
|
340
280
|
} else if (ua.indexOf('mac os') > -1) {
|
|
341
281
|
os = 'macOS';
|
|
342
|
-
var
|
|
343
|
-
osVersion =
|
|
282
|
+
var _match5 = ua.match(/mac os x (\d+[._]\d+)/);
|
|
283
|
+
osVersion = _match5 ? _match5[1].replace('_', '.') : '';
|
|
344
284
|
} else if (ua.indexOf('android') > -1) {
|
|
345
285
|
os = 'Android';
|
|
346
|
-
var
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
286
|
+
var _match6 = ua.match(/android (\d+(?:\.\d+)?)/);
|
|
287
|
+
if (_match6) {
|
|
288
|
+
var _match7 = _slicedToArray(_match6, 2),
|
|
289
|
+
version = _match7[1];
|
|
290
|
+
osVersion = version;
|
|
291
|
+
if (osVersion.indexOf('.') === -1) {
|
|
292
|
+
osVersion = "".concat(osVersion, ".0");
|
|
293
|
+
}
|
|
294
|
+
} else {
|
|
295
|
+
osVersion = '';
|
|
296
|
+
}
|
|
352
297
|
} else if (ua.indexOf('linux') > -1) {
|
|
353
298
|
os = 'Linux';
|
|
354
299
|
}
|
|
@@ -358,4 +303,46 @@ export function parseBrowserInfo(userAgent) {
|
|
|
358
303
|
os: os,
|
|
359
304
|
osVersion: osVersion
|
|
360
305
|
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* 收集环境信息并生成 tags(仅在初始化时执行一次)
|
|
310
|
+
*/
|
|
311
|
+
export function collectEnvironmentTags(debug) {
|
|
312
|
+
var envInfo = getEnvironmentInfo();
|
|
313
|
+
var tags = {
|
|
314
|
+
platform: envInfo.platform
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// 浏览器环境
|
|
318
|
+
if (envInfo.platform === 'browser' && envInfo.userAgent) {
|
|
319
|
+
var browserInfo = parseBrowserInfo(envInfo.userAgent);
|
|
320
|
+
tags.browser = browserInfo.browser;
|
|
321
|
+
tags.browserVersion = browserInfo.browserVersion;
|
|
322
|
+
tags.os = browserInfo.os;
|
|
323
|
+
tags.osVersion = browserInfo.osVersion;
|
|
324
|
+
tags.screenWidth = envInfo.screenWidth;
|
|
325
|
+
tags.screenHeight = envInfo.screenHeight;
|
|
326
|
+
tags.language = envInfo.language;
|
|
327
|
+
}
|
|
328
|
+
// 微信小程序环境
|
|
329
|
+
else if (envInfo.platform === 'wechat' && envInfo.systemInfo) {
|
|
330
|
+
tags.brand = envInfo.systemInfo.brand;
|
|
331
|
+
tags.model = envInfo.systemInfo.model;
|
|
332
|
+
tags.system = envInfo.systemInfo.system;
|
|
333
|
+
tags.wechatVersion = envInfo.systemInfo.version;
|
|
334
|
+
tags.SDKVersion = envInfo.systemInfo.SDKVersion;
|
|
335
|
+
tags.screenWidth = envInfo.screenWidth;
|
|
336
|
+
tags.screenHeight = envInfo.screenHeight;
|
|
337
|
+
tags.language = envInfo.language;
|
|
338
|
+
}
|
|
339
|
+
logDebug(debug, 'Environment tags collected:', tags);
|
|
340
|
+
return tags;
|
|
341
|
+
}
|
|
342
|
+
export function logDebug(debug) {
|
|
343
|
+
var _console;
|
|
344
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
345
|
+
args[_key - 1] = arguments[_key];
|
|
346
|
+
}
|
|
347
|
+
if (debug) (_console = console).debug.apply(_console, ['[LoggerSDK]'].concat(args));
|
|
361
348
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluve/logger-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "logger sdk",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"logger"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"url": "https://gitlab.pharmacyyf.com/frontend-common/pluve-lib.git"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
|
-
"init-install": "
|
|
28
|
+
"init-install": "yarn install",
|
|
29
29
|
"build-types": "tsc",
|
|
30
30
|
"build": "father build",
|
|
31
31
|
"test": "vitest run",
|