@be-link/cls-logger 1.0.1-beta.4 → 1.0.1-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ClsLogger.d.ts +9 -96
- package/dist/ClsLogger.d.ts.map +1 -1
- package/dist/ClsLoggerCore.d.ts +127 -0
- package/dist/ClsLoggerCore.d.ts.map +1 -0
- package/dist/ClsLoggerMini.d.ts +8 -0
- package/dist/ClsLoggerMini.d.ts.map +1 -0
- package/dist/ClsLoggerWeb.d.ts +8 -0
- package/dist/ClsLoggerWeb.d.ts.map +1 -0
- package/dist/clsSdkTypes.d.ts +18 -0
- package/dist/clsSdkTypes.d.ts.map +1 -0
- package/dist/index.esm.js +214 -31
- package/dist/index.js +214 -31
- package/dist/index.umd.js +218 -33
- package/dist/mini.d.ts +6 -0
- package/dist/mini.d.ts.map +1 -0
- package/dist/mini.esm.js +2553 -0
- package/dist/mini.js +2578 -0
- package/dist/sdkUtils.d.ts +3 -0
- package/dist/sdkUtils.d.ts.map +1 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/web.d.ts +6 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.esm.js +2523 -0
- package/dist/web.js +2548 -0
- package/package.json +27 -2
package/dist/index.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var tencentcloudClsSdkJsWeb = require('tencentcloud-cls-sdk-js-web');
|
|
6
|
-
|
|
7
5
|
function isPlainObject(value) {
|
|
8
6
|
return Object.prototype.toString.call(value) === '[object Object]';
|
|
9
7
|
}
|
|
@@ -1909,9 +1907,20 @@ function enterClsSendingGuard() {
|
|
|
1909
1907
|
g.__beLinkClsLoggerSendingCount__ = cur > 0 ? cur - 1 : 0;
|
|
1910
1908
|
};
|
|
1911
1909
|
}
|
|
1912
|
-
|
|
1910
|
+
/**
|
|
1911
|
+
* CLS Logger 核心基类
|
|
1912
|
+
* - 负责所有上报、队列、监控逻辑
|
|
1913
|
+
* - 不包含具体的 SDK 加载实现(由子类负责)
|
|
1914
|
+
* - 这样可以把 web/mini 的 SDK 依赖彻底解耦到子入口
|
|
1915
|
+
*/
|
|
1916
|
+
class ClsLoggerCore {
|
|
1913
1917
|
constructor() {
|
|
1918
|
+
this.sdk = null;
|
|
1919
|
+
this.sdkPromise = null;
|
|
1920
|
+
this.sdkOverride = null;
|
|
1921
|
+
this.sdkLoaderOverride = null;
|
|
1914
1922
|
this.client = null;
|
|
1923
|
+
this.clientPromise = null;
|
|
1915
1924
|
this.topicId = null;
|
|
1916
1925
|
this.endpoint = 'ap-shanghai.cls.tencentcs.com';
|
|
1917
1926
|
this.retryTimes = 10;
|
|
@@ -1942,6 +1951,15 @@ class ClsLogger {
|
|
|
1942
1951
|
this.behaviorMonitorStarted = false;
|
|
1943
1952
|
this.behaviorMonitorCleanup = null;
|
|
1944
1953
|
}
|
|
1954
|
+
/**
|
|
1955
|
+
* 子类可按需重写(默认检测 wx)
|
|
1956
|
+
*/
|
|
1957
|
+
detectEnvType() {
|
|
1958
|
+
const wxAny = globalThis.wx;
|
|
1959
|
+
if (wxAny && typeof wxAny.getSystemInfoSync === 'function')
|
|
1960
|
+
return 'miniprogram';
|
|
1961
|
+
return 'browser';
|
|
1962
|
+
}
|
|
1945
1963
|
init(options) {
|
|
1946
1964
|
this.initTs = Date.now();
|
|
1947
1965
|
const topicId = options?.tencentCloud?.topicID ?? options?.topic_id ?? options?.topicID ?? this.topicId ?? null;
|
|
@@ -1953,6 +1971,19 @@ class ClsLogger {
|
|
|
1953
1971
|
console.warn('ClsLogger.init 没有传 topicID/topic_id');
|
|
1954
1972
|
return;
|
|
1955
1973
|
}
|
|
1974
|
+
const nextEnvType = options.envType ?? this.detectEnvType();
|
|
1975
|
+
// envType/endpoint/retryTimes 变化时:重置 client(以及可能的 sdk)
|
|
1976
|
+
const envChanged = nextEnvType !== this.envType;
|
|
1977
|
+
const endpointChanged = endpoint !== this.endpoint;
|
|
1978
|
+
const retryChanged = retryTimes !== this.retryTimes;
|
|
1979
|
+
if (envChanged || endpointChanged || retryChanged) {
|
|
1980
|
+
this.client = null;
|
|
1981
|
+
this.clientPromise = null;
|
|
1982
|
+
}
|
|
1983
|
+
if (envChanged) {
|
|
1984
|
+
this.sdk = null;
|
|
1985
|
+
this.sdkPromise = null;
|
|
1986
|
+
}
|
|
1956
1987
|
this.topicId = topicId;
|
|
1957
1988
|
this.endpoint = endpoint;
|
|
1958
1989
|
this.retryTimes = retryTimes;
|
|
@@ -1963,7 +1994,10 @@ class ClsLogger {
|
|
|
1963
1994
|
this.projectName = options.projectName ?? this.projectName;
|
|
1964
1995
|
this.appId = options.appId ?? this.appId;
|
|
1965
1996
|
this.appVersion = options.appVersion ?? this.appVersion;
|
|
1966
|
-
this.envType =
|
|
1997
|
+
this.envType = nextEnvType;
|
|
1998
|
+
// 可选:外部注入 SDK(优先级:sdkLoader > sdk)
|
|
1999
|
+
this.sdkLoaderOverride = options.sdkLoader ?? this.sdkLoaderOverride;
|
|
2000
|
+
this.sdkOverride = options.sdk ?? this.sdkOverride;
|
|
1967
2001
|
this.userGenerateBaseFields = options.generateBaseFields ?? this.userGenerateBaseFields;
|
|
1968
2002
|
this.autoGenerateBaseFields = createAutoDeviceInfoBaseFields(this.envType, options.deviceInfo);
|
|
1969
2003
|
this.storageKey = options.storageKey ?? this.storageKey;
|
|
@@ -1973,8 +2007,10 @@ class ClsLogger {
|
|
|
1973
2007
|
this.startupDelayMs = options.batch?.startupDelayMs ?? this.startupDelayMs;
|
|
1974
2008
|
this.failedCacheKey = options.failedCacheKey ?? this.failedCacheKey;
|
|
1975
2009
|
this.failedCacheMax = options.failedCacheMax ?? this.failedCacheMax;
|
|
1976
|
-
//
|
|
1977
|
-
this.getInstance()
|
|
2010
|
+
// 预热(避免首条日志触发 import/初始化开销)
|
|
2011
|
+
void this.getInstance().catch(() => {
|
|
2012
|
+
// ignore
|
|
2013
|
+
});
|
|
1978
2014
|
// 启动时尝试发送失败缓存
|
|
1979
2015
|
this.flushFailed();
|
|
1980
2016
|
// 初始化后立即启动请求监听
|
|
@@ -2078,20 +2114,29 @@ class ClsLogger {
|
|
|
2078
2114
|
this.behaviorMonitorCleanup = null;
|
|
2079
2115
|
this.behaviorMonitorStarted = false;
|
|
2080
2116
|
}
|
|
2081
|
-
|
|
2117
|
+
/**
|
|
2118
|
+
* 获取 CLS client(按环境懒加载 SDK)
|
|
2119
|
+
*/
|
|
2120
|
+
async getInstance() {
|
|
2082
2121
|
if (this.client)
|
|
2083
2122
|
return this.client;
|
|
2084
|
-
this.
|
|
2085
|
-
|
|
2086
|
-
|
|
2123
|
+
if (this.clientPromise)
|
|
2124
|
+
return this.clientPromise;
|
|
2125
|
+
this.clientPromise = this.loadSdk()
|
|
2126
|
+
.then(({ AsyncClient }) => {
|
|
2127
|
+
const client = new AsyncClient({
|
|
2128
|
+
endpoint: this.endpoint,
|
|
2129
|
+
retry_times: this.retryTimes,
|
|
2130
|
+
});
|
|
2131
|
+
this.client = client;
|
|
2132
|
+
return client;
|
|
2133
|
+
})
|
|
2134
|
+
.catch((err) => {
|
|
2135
|
+
// 失败后允许下次重试
|
|
2136
|
+
this.clientPromise = null;
|
|
2137
|
+
throw err;
|
|
2087
2138
|
});
|
|
2088
|
-
return this.
|
|
2089
|
-
}
|
|
2090
|
-
detectEnvType() {
|
|
2091
|
-
const wxAny = globalThis.wx;
|
|
2092
|
-
if (wxAny && typeof wxAny.getSystemInfoSync === 'function')
|
|
2093
|
-
return 'miniprogram';
|
|
2094
|
-
return 'browser';
|
|
2139
|
+
return this.clientPromise;
|
|
2095
2140
|
}
|
|
2096
2141
|
/**
|
|
2097
2142
|
* 直接上报:埋点入参必须是一维(扁平)Object
|
|
@@ -2117,22 +2162,33 @@ class ClsLogger {
|
|
|
2117
2162
|
appVersion: this.appVersion || undefined,
|
|
2118
2163
|
...normalizedFields,
|
|
2119
2164
|
});
|
|
2120
|
-
|
|
2121
|
-
|
|
2165
|
+
// 同步 API:内部异步发送,避免把网络异常冒泡到业务(尤其小程序)
|
|
2166
|
+
void this.putAsync(finalFields).catch(() => {
|
|
2167
|
+
// ignore
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
async putAsync(finalFields) {
|
|
2171
|
+
if (!this.topicId)
|
|
2172
|
+
return;
|
|
2173
|
+
const sdk = await this.loadSdk();
|
|
2174
|
+
const client = await this.getInstance();
|
|
2175
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2122
2176
|
logGroup.setSource(this.source);
|
|
2123
|
-
const log = new
|
|
2177
|
+
const log = new sdk.Log(Date.now());
|
|
2124
2178
|
for (const key of Object.keys(finalFields)) {
|
|
2125
2179
|
log.addContent(key, stringifyLogValue(finalFields[key]));
|
|
2126
2180
|
}
|
|
2127
2181
|
logGroup.addLog(log);
|
|
2128
|
-
const request = new
|
|
2182
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2129
2183
|
const exit = enterClsSendingGuard();
|
|
2184
|
+
let p;
|
|
2130
2185
|
try {
|
|
2131
|
-
client.PutLogs(request);
|
|
2186
|
+
p = client.PutLogs(request);
|
|
2132
2187
|
}
|
|
2133
2188
|
finally {
|
|
2134
2189
|
exit();
|
|
2135
2190
|
}
|
|
2191
|
+
await p;
|
|
2136
2192
|
}
|
|
2137
2193
|
/**
|
|
2138
2194
|
* 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
|
|
@@ -2191,11 +2247,19 @@ class ClsLogger {
|
|
|
2191
2247
|
console.warn('ClsLogger.putBatch:未初始化 topic_id');
|
|
2192
2248
|
return;
|
|
2193
2249
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2250
|
+
void this.putBatchAsync(queue).catch(() => {
|
|
2251
|
+
// ignore
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
2254
|
+
async putBatchAsync(queue) {
|
|
2255
|
+
if (!this.topicId)
|
|
2256
|
+
return;
|
|
2257
|
+
const sdk = await this.loadSdk();
|
|
2258
|
+
const client = await this.getInstance();
|
|
2259
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2196
2260
|
logGroup.setSource(this.source);
|
|
2197
2261
|
for (const item of queue) {
|
|
2198
|
-
const log = new
|
|
2262
|
+
const log = new sdk.Log(item.time);
|
|
2199
2263
|
const data = item.data ?? {};
|
|
2200
2264
|
for (const key of Object.keys(data)) {
|
|
2201
2265
|
log.addContent(key, stringifyLogValue(data[key]));
|
|
@@ -2204,14 +2268,16 @@ class ClsLogger {
|
|
|
2204
2268
|
}
|
|
2205
2269
|
if (logGroup.getLogs().length === 0)
|
|
2206
2270
|
return;
|
|
2207
|
-
const request = new
|
|
2271
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2208
2272
|
const exit = enterClsSendingGuard();
|
|
2273
|
+
let p;
|
|
2209
2274
|
try {
|
|
2210
|
-
client.PutLogs(request);
|
|
2275
|
+
p = client.PutLogs(request);
|
|
2211
2276
|
}
|
|
2212
2277
|
finally {
|
|
2213
2278
|
exit();
|
|
2214
2279
|
}
|
|
2280
|
+
await p;
|
|
2215
2281
|
}
|
|
2216
2282
|
/**
|
|
2217
2283
|
* 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
|
|
@@ -2324,12 +2390,13 @@ class ClsLogger {
|
|
|
2324
2390
|
async sendReportLogs(logs) {
|
|
2325
2391
|
if (!this.topicId)
|
|
2326
2392
|
return;
|
|
2327
|
-
const
|
|
2328
|
-
const
|
|
2393
|
+
const sdk = await this.loadSdk();
|
|
2394
|
+
const client = await this.getInstance();
|
|
2395
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2329
2396
|
logGroup.setSource(this.source);
|
|
2330
2397
|
for (const item of logs) {
|
|
2331
2398
|
const fields = this.buildReportFields(item);
|
|
2332
|
-
const log = new
|
|
2399
|
+
const log = new sdk.Log(fields.timestamp);
|
|
2333
2400
|
for (const key of Object.keys(fields)) {
|
|
2334
2401
|
if (key === 'timestamp')
|
|
2335
2402
|
continue;
|
|
@@ -2337,7 +2404,7 @@ class ClsLogger {
|
|
|
2337
2404
|
}
|
|
2338
2405
|
logGroup.addLog(log);
|
|
2339
2406
|
}
|
|
2340
|
-
const request = new
|
|
2407
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2341
2408
|
// 只在“发起网络请求”的同步阶段打标记,避免 requestMonitor 监控 CLS 上报请求导致递归
|
|
2342
2409
|
const exit = enterClsSendingGuard();
|
|
2343
2410
|
let p;
|
|
@@ -2413,6 +2480,122 @@ class ClsLogger {
|
|
|
2413
2480
|
}
|
|
2414
2481
|
}
|
|
2415
2482
|
|
|
2483
|
+
function readGlobal(key) {
|
|
2484
|
+
try {
|
|
2485
|
+
const g = globalThis;
|
|
2486
|
+
return g[key] ?? null;
|
|
2487
|
+
}
|
|
2488
|
+
catch {
|
|
2489
|
+
return null;
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
function tryRequire(moduleName) {
|
|
2493
|
+
try {
|
|
2494
|
+
// 说明:
|
|
2495
|
+
// - ESM 构建(exports.import/module)里通常不存在模块作用域的 require
|
|
2496
|
+
// - 一些小程序运行时/构建链路会把 require 挂到 globalThis 上
|
|
2497
|
+
// 因此这里同时探测“模块作用域 require”与 “globalThis.require”
|
|
2498
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
2499
|
+
const localReq = (typeof require === 'function' ? require : null);
|
|
2500
|
+
const globalReq = readGlobal('require');
|
|
2501
|
+
const candidates = [localReq, globalReq].filter((fn) => typeof fn === 'function');
|
|
2502
|
+
for (const fn of candidates) {
|
|
2503
|
+
try {
|
|
2504
|
+
return fn(moduleName);
|
|
2505
|
+
}
|
|
2506
|
+
catch {
|
|
2507
|
+
// continue
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
return null;
|
|
2511
|
+
}
|
|
2512
|
+
catch {
|
|
2513
|
+
return null;
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
/**
|
|
2518
|
+
* 兼容版 ClsLogger(默认入口)
|
|
2519
|
+
* - 保留了自动识别环境 + 动态 import 的逻辑
|
|
2520
|
+
* - 如果业务想瘦身,建议改用 @be-link/cls-logger/web 或 /mini
|
|
2521
|
+
*/
|
|
2522
|
+
class ClsLogger extends ClsLoggerCore {
|
|
2523
|
+
async loadSdk() {
|
|
2524
|
+
if (this.sdk)
|
|
2525
|
+
return this.sdk;
|
|
2526
|
+
if (this.sdkPromise)
|
|
2527
|
+
return this.sdkPromise;
|
|
2528
|
+
const normalizeSdk = (m) => {
|
|
2529
|
+
const mod = (m?.default && m.default.AsyncClient ? m.default : m);
|
|
2530
|
+
if (mod?.AsyncClient && mod?.Log && mod?.LogGroup && mod?.PutLogsRequest) {
|
|
2531
|
+
return {
|
|
2532
|
+
AsyncClient: mod.AsyncClient,
|
|
2533
|
+
Log: mod.Log,
|
|
2534
|
+
LogGroup: mod.LogGroup,
|
|
2535
|
+
PutLogsRequest: mod.PutLogsRequest,
|
|
2536
|
+
};
|
|
2537
|
+
}
|
|
2538
|
+
return null;
|
|
2539
|
+
};
|
|
2540
|
+
// 1) 外部注入的 loader(最高优先级)
|
|
2541
|
+
if (this.sdkLoaderOverride) {
|
|
2542
|
+
try {
|
|
2543
|
+
const loaded = await this.sdkLoaderOverride();
|
|
2544
|
+
const sdk = normalizeSdk(loaded);
|
|
2545
|
+
if (sdk) {
|
|
2546
|
+
this.sdk = sdk;
|
|
2547
|
+
return sdk;
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
catch {
|
|
2551
|
+
// ignore and fallback
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
// 2) 外部直接注入的 sdk
|
|
2555
|
+
if (this.sdkOverride) {
|
|
2556
|
+
const sdk = normalizeSdk(this.sdkOverride);
|
|
2557
|
+
if (sdk) {
|
|
2558
|
+
this.sdk = sdk;
|
|
2559
|
+
return sdk;
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
const isMini = this.envType === 'miniprogram';
|
|
2563
|
+
// 静态字面量,方便打包器识别(但在此兼容入口里,仍然可能被一起分析)
|
|
2564
|
+
const WEB_SDK = 'tencentcloud-cls-sdk-js-web';
|
|
2565
|
+
const MINI_SDK = 'tencentcloud-cls-sdk-js-mini';
|
|
2566
|
+
// UMD(浏览器脚本)优先读全局变量
|
|
2567
|
+
if (!isMini) {
|
|
2568
|
+
const g = readGlobal('tencentcloudClsSdkJsWeb');
|
|
2569
|
+
const sdk = normalizeSdk(g);
|
|
2570
|
+
if (sdk) {
|
|
2571
|
+
this.sdk = sdk;
|
|
2572
|
+
return sdk;
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
// 尽量同步 require
|
|
2576
|
+
const reqMod = tryRequire(isMini ? MINI_SDK : WEB_SDK);
|
|
2577
|
+
const reqSdk = normalizeSdk(reqMod);
|
|
2578
|
+
if (reqSdk) {
|
|
2579
|
+
this.sdk = reqSdk;
|
|
2580
|
+
return reqSdk;
|
|
2581
|
+
}
|
|
2582
|
+
// 动态 import
|
|
2583
|
+
this.sdkPromise = (isMini ? import(MINI_SDK) : import(WEB_SDK))
|
|
2584
|
+
.then((m) => {
|
|
2585
|
+
const sdk = normalizeSdk(m);
|
|
2586
|
+
if (!sdk)
|
|
2587
|
+
throw new Error(`ClsLogger.loadSdk: invalid sdk module for ${isMini ? MINI_SDK : WEB_SDK}`);
|
|
2588
|
+
this.sdk = sdk;
|
|
2589
|
+
return sdk;
|
|
2590
|
+
})
|
|
2591
|
+
.catch((err) => {
|
|
2592
|
+
this.sdkPromise = null;
|
|
2593
|
+
throw err;
|
|
2594
|
+
});
|
|
2595
|
+
return this.sdkPromise;
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2416
2599
|
const clsLogger = new ClsLogger();
|
|
2417
2600
|
|
|
2418
2601
|
exports.ClsLogger = ClsLogger;
|