@be-link/cls-logger 1.0.1-beta.4 → 1.0.1-beta.5
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 +14 -2
- package/dist/ClsLogger.d.ts.map +1 -1
- package/dist/index.esm.js +139 -24
- package/dist/index.js +139 -24
- package/dist/index.umd.js +143 -26
- package/package.json +3 -2
package/dist/ClsLogger.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { AsyncClient } from 'tencentcloud-cls-sdk-js-web';
|
|
2
1
|
import type { ClsLoggerInitOptions, FlatFields, PutOptions, QueueItem, ReportLog } from './types';
|
|
3
2
|
export declare class ClsLogger {
|
|
3
|
+
private sdk;
|
|
4
|
+
private sdkPromise;
|
|
4
5
|
private client;
|
|
6
|
+
private clientPromise;
|
|
5
7
|
private topicId;
|
|
6
8
|
private endpoint;
|
|
7
9
|
private retryTimes;
|
|
@@ -42,7 +44,15 @@ export declare class ClsLogger {
|
|
|
42
44
|
* - 如需重启:可再次调用 init(或自行调用 init 后的默认启动逻辑)
|
|
43
45
|
*/
|
|
44
46
|
stopBehaviorMonitor(): void;
|
|
45
|
-
|
|
47
|
+
/**
|
|
48
|
+
* 获取 CLS client(按环境懒加载 SDK)
|
|
49
|
+
* - browser: 优先走 UMD 全局变量 `tencentcloudClsSdkJsWeb`
|
|
50
|
+
* - miniprogram: 优先走 require(webpack/taro 可解析),否则 fallback import()
|
|
51
|
+
*/
|
|
52
|
+
getInstance(): Promise<{
|
|
53
|
+
PutLogs: (request: unknown) => Promise<unknown> | unknown;
|
|
54
|
+
}>;
|
|
55
|
+
private loadSdk;
|
|
46
56
|
private detectEnvType;
|
|
47
57
|
/**
|
|
48
58
|
* 直接上报:埋点入参必须是一维(扁平)Object
|
|
@@ -50,6 +60,7 @@ export declare class ClsLogger {
|
|
|
50
60
|
* - 最终会把 fields 展开成 CLS 的 content(key/value 都会转成 string)
|
|
51
61
|
*/
|
|
52
62
|
put(fields: FlatFields, options?: PutOptions): void;
|
|
63
|
+
private putAsync;
|
|
53
64
|
/**
|
|
54
65
|
* 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
|
|
55
66
|
*/
|
|
@@ -67,6 +78,7 @@ export declare class ClsLogger {
|
|
|
67
78
|
* 批量上报(每条 item.data 展开为 log content)
|
|
68
79
|
*/
|
|
69
80
|
putBatch(queue: QueueItem[]): void;
|
|
81
|
+
private putBatchAsync;
|
|
70
82
|
/**
|
|
71
83
|
* 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
|
|
72
84
|
*/
|
package/dist/ClsLogger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClsLogger.d.ts","sourceRoot":"","sources":["../src/ClsLogger.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ClsLogger.d.ts","sourceRoot":"","sources":["../src/ClsLogger.ts"],"names":[],"mappings":"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"}
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { AsyncClient, LogGroup, Log, PutLogsRequest } from 'tencentcloud-cls-sdk-js-web';
|
|
2
|
-
|
|
3
1
|
function isPlainObject(value) {
|
|
4
2
|
return Object.prototype.toString.call(value) === '[object Object]';
|
|
5
3
|
}
|
|
@@ -1896,6 +1894,27 @@ function createAutoDeviceInfoBaseFields(envType, opts) {
|
|
|
1896
1894
|
};
|
|
1897
1895
|
}
|
|
1898
1896
|
|
|
1897
|
+
function readGlobal(key) {
|
|
1898
|
+
try {
|
|
1899
|
+
const g = globalThis;
|
|
1900
|
+
return g[key] ?? null;
|
|
1901
|
+
}
|
|
1902
|
+
catch {
|
|
1903
|
+
return null;
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
function tryRequire(moduleName) {
|
|
1907
|
+
try {
|
|
1908
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
1909
|
+
const req = (typeof require === 'function' ? require : null);
|
|
1910
|
+
if (!req)
|
|
1911
|
+
return null;
|
|
1912
|
+
return req(moduleName);
|
|
1913
|
+
}
|
|
1914
|
+
catch {
|
|
1915
|
+
return null;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1899
1918
|
function enterClsSendingGuard() {
|
|
1900
1919
|
const g = globalThis;
|
|
1901
1920
|
const next = (g.__beLinkClsLoggerSendingCount__ ?? 0) + 1;
|
|
@@ -1907,7 +1926,10 @@ function enterClsSendingGuard() {
|
|
|
1907
1926
|
}
|
|
1908
1927
|
class ClsLogger {
|
|
1909
1928
|
constructor() {
|
|
1929
|
+
this.sdk = null;
|
|
1930
|
+
this.sdkPromise = null;
|
|
1910
1931
|
this.client = null;
|
|
1932
|
+
this.clientPromise = null;
|
|
1911
1933
|
this.topicId = null;
|
|
1912
1934
|
this.endpoint = 'ap-shanghai.cls.tencentcs.com';
|
|
1913
1935
|
this.retryTimes = 10;
|
|
@@ -1949,6 +1971,19 @@ class ClsLogger {
|
|
|
1949
1971
|
console.warn('ClsLogger.init 没有传 topicID/topic_id');
|
|
1950
1972
|
return;
|
|
1951
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
|
+
}
|
|
1952
1987
|
this.topicId = topicId;
|
|
1953
1988
|
this.endpoint = endpoint;
|
|
1954
1989
|
this.retryTimes = retryTimes;
|
|
@@ -1959,7 +1994,7 @@ class ClsLogger {
|
|
|
1959
1994
|
this.projectName = options.projectName ?? this.projectName;
|
|
1960
1995
|
this.appId = options.appId ?? this.appId;
|
|
1961
1996
|
this.appVersion = options.appVersion ?? this.appVersion;
|
|
1962
|
-
this.envType =
|
|
1997
|
+
this.envType = nextEnvType;
|
|
1963
1998
|
this.userGenerateBaseFields = options.generateBaseFields ?? this.userGenerateBaseFields;
|
|
1964
1999
|
this.autoGenerateBaseFields = createAutoDeviceInfoBaseFields(this.envType, options.deviceInfo);
|
|
1965
2000
|
this.storageKey = options.storageKey ?? this.storageKey;
|
|
@@ -1969,8 +2004,10 @@ class ClsLogger {
|
|
|
1969
2004
|
this.startupDelayMs = options.batch?.startupDelayMs ?? this.startupDelayMs;
|
|
1970
2005
|
this.failedCacheKey = options.failedCacheKey ?? this.failedCacheKey;
|
|
1971
2006
|
this.failedCacheMax = options.failedCacheMax ?? this.failedCacheMax;
|
|
1972
|
-
//
|
|
1973
|
-
this.getInstance()
|
|
2007
|
+
// 预热(避免首条日志触发 import/初始化开销)
|
|
2008
|
+
void this.getInstance().catch(() => {
|
|
2009
|
+
// ignore
|
|
2010
|
+
});
|
|
1974
2011
|
// 启动时尝试发送失败缓存
|
|
1975
2012
|
this.flushFailed();
|
|
1976
2013
|
// 初始化后立即启动请求监听
|
|
@@ -2074,14 +2111,70 @@ class ClsLogger {
|
|
|
2074
2111
|
this.behaviorMonitorCleanup = null;
|
|
2075
2112
|
this.behaviorMonitorStarted = false;
|
|
2076
2113
|
}
|
|
2077
|
-
|
|
2114
|
+
/**
|
|
2115
|
+
* 获取 CLS client(按环境懒加载 SDK)
|
|
2116
|
+
* - browser: 优先走 UMD 全局变量 `tencentcloudClsSdkJsWeb`
|
|
2117
|
+
* - miniprogram: 优先走 require(webpack/taro 可解析),否则 fallback import()
|
|
2118
|
+
*/
|
|
2119
|
+
async getInstance() {
|
|
2078
2120
|
if (this.client)
|
|
2079
2121
|
return this.client;
|
|
2080
|
-
this.
|
|
2081
|
-
|
|
2082
|
-
|
|
2122
|
+
if (this.clientPromise)
|
|
2123
|
+
return this.clientPromise;
|
|
2124
|
+
this.clientPromise = this.loadSdk()
|
|
2125
|
+
.then(({ AsyncClient }) => {
|
|
2126
|
+
const client = new AsyncClient({
|
|
2127
|
+
endpoint: this.endpoint,
|
|
2128
|
+
retry_times: this.retryTimes,
|
|
2129
|
+
});
|
|
2130
|
+
this.client = client;
|
|
2131
|
+
return client;
|
|
2132
|
+
})
|
|
2133
|
+
.catch((err) => {
|
|
2134
|
+
// 失败后允许下次重试
|
|
2135
|
+
this.clientPromise = null;
|
|
2136
|
+
throw err;
|
|
2137
|
+
});
|
|
2138
|
+
return this.clientPromise;
|
|
2139
|
+
}
|
|
2140
|
+
async loadSdk() {
|
|
2141
|
+
if (this.sdk)
|
|
2142
|
+
return this.sdk;
|
|
2143
|
+
if (this.sdkPromise)
|
|
2144
|
+
return this.sdkPromise;
|
|
2145
|
+
const isMini = this.envType === 'miniprogram';
|
|
2146
|
+
const moduleName = isMini ? 'tencentcloud-cls-sdk-js-mini' : 'tencentcloud-cls-sdk-js-web';
|
|
2147
|
+
// UMD(浏览器脚本)优先读全局变量
|
|
2148
|
+
if (!isMini) {
|
|
2149
|
+
const g = readGlobal('tencentcloudClsSdkJsWeb');
|
|
2150
|
+
if (g?.AsyncClient && g?.Log && g?.LogGroup && g?.PutLogsRequest) {
|
|
2151
|
+
this.sdk = g;
|
|
2152
|
+
return this.sdk;
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
// 尽量同步 require(小程序/webpack 里最稳),失败再走 import()
|
|
2156
|
+
const reqMod = tryRequire(moduleName);
|
|
2157
|
+
if (reqMod?.AsyncClient && reqMod?.Log && reqMod?.LogGroup && reqMod?.PutLogsRequest) {
|
|
2158
|
+
this.sdk = reqMod;
|
|
2159
|
+
return this.sdk;
|
|
2160
|
+
}
|
|
2161
|
+
this.sdkPromise = import(moduleName)
|
|
2162
|
+
.then((m) => {
|
|
2163
|
+
const mod = (m?.default && m.default.AsyncClient ? m.default : m);
|
|
2164
|
+
const sdk = {
|
|
2165
|
+
AsyncClient: mod.AsyncClient,
|
|
2166
|
+
Log: mod.Log,
|
|
2167
|
+
LogGroup: mod.LogGroup,
|
|
2168
|
+
PutLogsRequest: mod.PutLogsRequest,
|
|
2169
|
+
};
|
|
2170
|
+
this.sdk = sdk;
|
|
2171
|
+
return sdk;
|
|
2172
|
+
})
|
|
2173
|
+
.catch((err) => {
|
|
2174
|
+
this.sdkPromise = null;
|
|
2175
|
+
throw err;
|
|
2083
2176
|
});
|
|
2084
|
-
return this.
|
|
2177
|
+
return this.sdkPromise;
|
|
2085
2178
|
}
|
|
2086
2179
|
detectEnvType() {
|
|
2087
2180
|
const wxAny = globalThis.wx;
|
|
@@ -2113,22 +2206,33 @@ class ClsLogger {
|
|
|
2113
2206
|
appVersion: this.appVersion || undefined,
|
|
2114
2207
|
...normalizedFields,
|
|
2115
2208
|
});
|
|
2116
|
-
|
|
2117
|
-
|
|
2209
|
+
// 同步 API:内部异步发送,避免把网络异常冒泡到业务(尤其小程序)
|
|
2210
|
+
void this.putAsync(finalFields).catch(() => {
|
|
2211
|
+
// ignore
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
2214
|
+
async putAsync(finalFields) {
|
|
2215
|
+
if (!this.topicId)
|
|
2216
|
+
return;
|
|
2217
|
+
const sdk = await this.loadSdk();
|
|
2218
|
+
const client = await this.getInstance();
|
|
2219
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2118
2220
|
logGroup.setSource(this.source);
|
|
2119
|
-
const log = new Log(Date.now());
|
|
2221
|
+
const log = new sdk.Log(Date.now());
|
|
2120
2222
|
for (const key of Object.keys(finalFields)) {
|
|
2121
2223
|
log.addContent(key, stringifyLogValue(finalFields[key]));
|
|
2122
2224
|
}
|
|
2123
2225
|
logGroup.addLog(log);
|
|
2124
|
-
const request = new PutLogsRequest(this.topicId, logGroup);
|
|
2226
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2125
2227
|
const exit = enterClsSendingGuard();
|
|
2228
|
+
let p;
|
|
2126
2229
|
try {
|
|
2127
|
-
client.PutLogs(request);
|
|
2230
|
+
p = client.PutLogs(request);
|
|
2128
2231
|
}
|
|
2129
2232
|
finally {
|
|
2130
2233
|
exit();
|
|
2131
2234
|
}
|
|
2235
|
+
await p;
|
|
2132
2236
|
}
|
|
2133
2237
|
/**
|
|
2134
2238
|
* 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
|
|
@@ -2187,11 +2291,19 @@ class ClsLogger {
|
|
|
2187
2291
|
console.warn('ClsLogger.putBatch:未初始化 topic_id');
|
|
2188
2292
|
return;
|
|
2189
2293
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2294
|
+
void this.putBatchAsync(queue).catch(() => {
|
|
2295
|
+
// ignore
|
|
2296
|
+
});
|
|
2297
|
+
}
|
|
2298
|
+
async putBatchAsync(queue) {
|
|
2299
|
+
if (!this.topicId)
|
|
2300
|
+
return;
|
|
2301
|
+
const sdk = await this.loadSdk();
|
|
2302
|
+
const client = await this.getInstance();
|
|
2303
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2192
2304
|
logGroup.setSource(this.source);
|
|
2193
2305
|
for (const item of queue) {
|
|
2194
|
-
const log = new Log(item.time);
|
|
2306
|
+
const log = new sdk.Log(item.time);
|
|
2195
2307
|
const data = item.data ?? {};
|
|
2196
2308
|
for (const key of Object.keys(data)) {
|
|
2197
2309
|
log.addContent(key, stringifyLogValue(data[key]));
|
|
@@ -2200,14 +2312,16 @@ class ClsLogger {
|
|
|
2200
2312
|
}
|
|
2201
2313
|
if (logGroup.getLogs().length === 0)
|
|
2202
2314
|
return;
|
|
2203
|
-
const request = new PutLogsRequest(this.topicId, logGroup);
|
|
2315
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2204
2316
|
const exit = enterClsSendingGuard();
|
|
2317
|
+
let p;
|
|
2205
2318
|
try {
|
|
2206
|
-
client.PutLogs(request);
|
|
2319
|
+
p = client.PutLogs(request);
|
|
2207
2320
|
}
|
|
2208
2321
|
finally {
|
|
2209
2322
|
exit();
|
|
2210
2323
|
}
|
|
2324
|
+
await p;
|
|
2211
2325
|
}
|
|
2212
2326
|
/**
|
|
2213
2327
|
* 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
|
|
@@ -2320,12 +2434,13 @@ class ClsLogger {
|
|
|
2320
2434
|
async sendReportLogs(logs) {
|
|
2321
2435
|
if (!this.topicId)
|
|
2322
2436
|
return;
|
|
2323
|
-
const
|
|
2324
|
-
const
|
|
2437
|
+
const sdk = await this.loadSdk();
|
|
2438
|
+
const client = await this.getInstance();
|
|
2439
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2325
2440
|
logGroup.setSource(this.source);
|
|
2326
2441
|
for (const item of logs) {
|
|
2327
2442
|
const fields = this.buildReportFields(item);
|
|
2328
|
-
const log = new Log(fields.timestamp);
|
|
2443
|
+
const log = new sdk.Log(fields.timestamp);
|
|
2329
2444
|
for (const key of Object.keys(fields)) {
|
|
2330
2445
|
if (key === 'timestamp')
|
|
2331
2446
|
continue;
|
|
@@ -2333,7 +2448,7 @@ class ClsLogger {
|
|
|
2333
2448
|
}
|
|
2334
2449
|
logGroup.addLog(log);
|
|
2335
2450
|
}
|
|
2336
|
-
const request = new PutLogsRequest(this.topicId, logGroup);
|
|
2451
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2337
2452
|
// 只在“发起网络请求”的同步阶段打标记,避免 requestMonitor 监控 CLS 上报请求导致递归
|
|
2338
2453
|
const exit = enterClsSendingGuard();
|
|
2339
2454
|
let p;
|
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
|
}
|
|
@@ -1900,6 +1898,27 @@ function createAutoDeviceInfoBaseFields(envType, opts) {
|
|
|
1900
1898
|
};
|
|
1901
1899
|
}
|
|
1902
1900
|
|
|
1901
|
+
function readGlobal(key) {
|
|
1902
|
+
try {
|
|
1903
|
+
const g = globalThis;
|
|
1904
|
+
return g[key] ?? null;
|
|
1905
|
+
}
|
|
1906
|
+
catch {
|
|
1907
|
+
return null;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
function tryRequire(moduleName) {
|
|
1911
|
+
try {
|
|
1912
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
1913
|
+
const req = (typeof require === 'function' ? require : null);
|
|
1914
|
+
if (!req)
|
|
1915
|
+
return null;
|
|
1916
|
+
return req(moduleName);
|
|
1917
|
+
}
|
|
1918
|
+
catch {
|
|
1919
|
+
return null;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1903
1922
|
function enterClsSendingGuard() {
|
|
1904
1923
|
const g = globalThis;
|
|
1905
1924
|
const next = (g.__beLinkClsLoggerSendingCount__ ?? 0) + 1;
|
|
@@ -1911,7 +1930,10 @@ function enterClsSendingGuard() {
|
|
|
1911
1930
|
}
|
|
1912
1931
|
class ClsLogger {
|
|
1913
1932
|
constructor() {
|
|
1933
|
+
this.sdk = null;
|
|
1934
|
+
this.sdkPromise = null;
|
|
1914
1935
|
this.client = null;
|
|
1936
|
+
this.clientPromise = null;
|
|
1915
1937
|
this.topicId = null;
|
|
1916
1938
|
this.endpoint = 'ap-shanghai.cls.tencentcs.com';
|
|
1917
1939
|
this.retryTimes = 10;
|
|
@@ -1953,6 +1975,19 @@ class ClsLogger {
|
|
|
1953
1975
|
console.warn('ClsLogger.init 没有传 topicID/topic_id');
|
|
1954
1976
|
return;
|
|
1955
1977
|
}
|
|
1978
|
+
const nextEnvType = options.envType ?? this.detectEnvType();
|
|
1979
|
+
// envType/endpoint/retryTimes 变化时:重置 client(以及可能的 sdk)
|
|
1980
|
+
const envChanged = nextEnvType !== this.envType;
|
|
1981
|
+
const endpointChanged = endpoint !== this.endpoint;
|
|
1982
|
+
const retryChanged = retryTimes !== this.retryTimes;
|
|
1983
|
+
if (envChanged || endpointChanged || retryChanged) {
|
|
1984
|
+
this.client = null;
|
|
1985
|
+
this.clientPromise = null;
|
|
1986
|
+
}
|
|
1987
|
+
if (envChanged) {
|
|
1988
|
+
this.sdk = null;
|
|
1989
|
+
this.sdkPromise = null;
|
|
1990
|
+
}
|
|
1956
1991
|
this.topicId = topicId;
|
|
1957
1992
|
this.endpoint = endpoint;
|
|
1958
1993
|
this.retryTimes = retryTimes;
|
|
@@ -1963,7 +1998,7 @@ class ClsLogger {
|
|
|
1963
1998
|
this.projectName = options.projectName ?? this.projectName;
|
|
1964
1999
|
this.appId = options.appId ?? this.appId;
|
|
1965
2000
|
this.appVersion = options.appVersion ?? this.appVersion;
|
|
1966
|
-
this.envType =
|
|
2001
|
+
this.envType = nextEnvType;
|
|
1967
2002
|
this.userGenerateBaseFields = options.generateBaseFields ?? this.userGenerateBaseFields;
|
|
1968
2003
|
this.autoGenerateBaseFields = createAutoDeviceInfoBaseFields(this.envType, options.deviceInfo);
|
|
1969
2004
|
this.storageKey = options.storageKey ?? this.storageKey;
|
|
@@ -1973,8 +2008,10 @@ class ClsLogger {
|
|
|
1973
2008
|
this.startupDelayMs = options.batch?.startupDelayMs ?? this.startupDelayMs;
|
|
1974
2009
|
this.failedCacheKey = options.failedCacheKey ?? this.failedCacheKey;
|
|
1975
2010
|
this.failedCacheMax = options.failedCacheMax ?? this.failedCacheMax;
|
|
1976
|
-
//
|
|
1977
|
-
this.getInstance()
|
|
2011
|
+
// 预热(避免首条日志触发 import/初始化开销)
|
|
2012
|
+
void this.getInstance().catch(() => {
|
|
2013
|
+
// ignore
|
|
2014
|
+
});
|
|
1978
2015
|
// 启动时尝试发送失败缓存
|
|
1979
2016
|
this.flushFailed();
|
|
1980
2017
|
// 初始化后立即启动请求监听
|
|
@@ -2078,14 +2115,70 @@ class ClsLogger {
|
|
|
2078
2115
|
this.behaviorMonitorCleanup = null;
|
|
2079
2116
|
this.behaviorMonitorStarted = false;
|
|
2080
2117
|
}
|
|
2081
|
-
|
|
2118
|
+
/**
|
|
2119
|
+
* 获取 CLS client(按环境懒加载 SDK)
|
|
2120
|
+
* - browser: 优先走 UMD 全局变量 `tencentcloudClsSdkJsWeb`
|
|
2121
|
+
* - miniprogram: 优先走 require(webpack/taro 可解析),否则 fallback import()
|
|
2122
|
+
*/
|
|
2123
|
+
async getInstance() {
|
|
2082
2124
|
if (this.client)
|
|
2083
2125
|
return this.client;
|
|
2084
|
-
this.
|
|
2085
|
-
|
|
2086
|
-
|
|
2126
|
+
if (this.clientPromise)
|
|
2127
|
+
return this.clientPromise;
|
|
2128
|
+
this.clientPromise = this.loadSdk()
|
|
2129
|
+
.then(({ AsyncClient }) => {
|
|
2130
|
+
const client = new AsyncClient({
|
|
2131
|
+
endpoint: this.endpoint,
|
|
2132
|
+
retry_times: this.retryTimes,
|
|
2133
|
+
});
|
|
2134
|
+
this.client = client;
|
|
2135
|
+
return client;
|
|
2136
|
+
})
|
|
2137
|
+
.catch((err) => {
|
|
2138
|
+
// 失败后允许下次重试
|
|
2139
|
+
this.clientPromise = null;
|
|
2140
|
+
throw err;
|
|
2141
|
+
});
|
|
2142
|
+
return this.clientPromise;
|
|
2143
|
+
}
|
|
2144
|
+
async loadSdk() {
|
|
2145
|
+
if (this.sdk)
|
|
2146
|
+
return this.sdk;
|
|
2147
|
+
if (this.sdkPromise)
|
|
2148
|
+
return this.sdkPromise;
|
|
2149
|
+
const isMini = this.envType === 'miniprogram';
|
|
2150
|
+
const moduleName = isMini ? 'tencentcloud-cls-sdk-js-mini' : 'tencentcloud-cls-sdk-js-web';
|
|
2151
|
+
// UMD(浏览器脚本)优先读全局变量
|
|
2152
|
+
if (!isMini) {
|
|
2153
|
+
const g = readGlobal('tencentcloudClsSdkJsWeb');
|
|
2154
|
+
if (g?.AsyncClient && g?.Log && g?.LogGroup && g?.PutLogsRequest) {
|
|
2155
|
+
this.sdk = g;
|
|
2156
|
+
return this.sdk;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
// 尽量同步 require(小程序/webpack 里最稳),失败再走 import()
|
|
2160
|
+
const reqMod = tryRequire(moduleName);
|
|
2161
|
+
if (reqMod?.AsyncClient && reqMod?.Log && reqMod?.LogGroup && reqMod?.PutLogsRequest) {
|
|
2162
|
+
this.sdk = reqMod;
|
|
2163
|
+
return this.sdk;
|
|
2164
|
+
}
|
|
2165
|
+
this.sdkPromise = import(moduleName)
|
|
2166
|
+
.then((m) => {
|
|
2167
|
+
const mod = (m?.default && m.default.AsyncClient ? m.default : m);
|
|
2168
|
+
const sdk = {
|
|
2169
|
+
AsyncClient: mod.AsyncClient,
|
|
2170
|
+
Log: mod.Log,
|
|
2171
|
+
LogGroup: mod.LogGroup,
|
|
2172
|
+
PutLogsRequest: mod.PutLogsRequest,
|
|
2173
|
+
};
|
|
2174
|
+
this.sdk = sdk;
|
|
2175
|
+
return sdk;
|
|
2176
|
+
})
|
|
2177
|
+
.catch((err) => {
|
|
2178
|
+
this.sdkPromise = null;
|
|
2179
|
+
throw err;
|
|
2087
2180
|
});
|
|
2088
|
-
return this.
|
|
2181
|
+
return this.sdkPromise;
|
|
2089
2182
|
}
|
|
2090
2183
|
detectEnvType() {
|
|
2091
2184
|
const wxAny = globalThis.wx;
|
|
@@ -2117,22 +2210,33 @@ class ClsLogger {
|
|
|
2117
2210
|
appVersion: this.appVersion || undefined,
|
|
2118
2211
|
...normalizedFields,
|
|
2119
2212
|
});
|
|
2120
|
-
|
|
2121
|
-
|
|
2213
|
+
// 同步 API:内部异步发送,避免把网络异常冒泡到业务(尤其小程序)
|
|
2214
|
+
void this.putAsync(finalFields).catch(() => {
|
|
2215
|
+
// ignore
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
async putAsync(finalFields) {
|
|
2219
|
+
if (!this.topicId)
|
|
2220
|
+
return;
|
|
2221
|
+
const sdk = await this.loadSdk();
|
|
2222
|
+
const client = await this.getInstance();
|
|
2223
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2122
2224
|
logGroup.setSource(this.source);
|
|
2123
|
-
const log = new
|
|
2225
|
+
const log = new sdk.Log(Date.now());
|
|
2124
2226
|
for (const key of Object.keys(finalFields)) {
|
|
2125
2227
|
log.addContent(key, stringifyLogValue(finalFields[key]));
|
|
2126
2228
|
}
|
|
2127
2229
|
logGroup.addLog(log);
|
|
2128
|
-
const request = new
|
|
2230
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2129
2231
|
const exit = enterClsSendingGuard();
|
|
2232
|
+
let p;
|
|
2130
2233
|
try {
|
|
2131
|
-
client.PutLogs(request);
|
|
2234
|
+
p = client.PutLogs(request);
|
|
2132
2235
|
}
|
|
2133
2236
|
finally {
|
|
2134
2237
|
exit();
|
|
2135
2238
|
}
|
|
2239
|
+
await p;
|
|
2136
2240
|
}
|
|
2137
2241
|
/**
|
|
2138
2242
|
* 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
|
|
@@ -2191,11 +2295,19 @@ class ClsLogger {
|
|
|
2191
2295
|
console.warn('ClsLogger.putBatch:未初始化 topic_id');
|
|
2192
2296
|
return;
|
|
2193
2297
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2298
|
+
void this.putBatchAsync(queue).catch(() => {
|
|
2299
|
+
// ignore
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
async putBatchAsync(queue) {
|
|
2303
|
+
if (!this.topicId)
|
|
2304
|
+
return;
|
|
2305
|
+
const sdk = await this.loadSdk();
|
|
2306
|
+
const client = await this.getInstance();
|
|
2307
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2196
2308
|
logGroup.setSource(this.source);
|
|
2197
2309
|
for (const item of queue) {
|
|
2198
|
-
const log = new
|
|
2310
|
+
const log = new sdk.Log(item.time);
|
|
2199
2311
|
const data = item.data ?? {};
|
|
2200
2312
|
for (const key of Object.keys(data)) {
|
|
2201
2313
|
log.addContent(key, stringifyLogValue(data[key]));
|
|
@@ -2204,14 +2316,16 @@ class ClsLogger {
|
|
|
2204
2316
|
}
|
|
2205
2317
|
if (logGroup.getLogs().length === 0)
|
|
2206
2318
|
return;
|
|
2207
|
-
const request = new
|
|
2319
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2208
2320
|
const exit = enterClsSendingGuard();
|
|
2321
|
+
let p;
|
|
2209
2322
|
try {
|
|
2210
|
-
client.PutLogs(request);
|
|
2323
|
+
p = client.PutLogs(request);
|
|
2211
2324
|
}
|
|
2212
2325
|
finally {
|
|
2213
2326
|
exit();
|
|
2214
2327
|
}
|
|
2328
|
+
await p;
|
|
2215
2329
|
}
|
|
2216
2330
|
/**
|
|
2217
2331
|
* 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
|
|
@@ -2324,12 +2438,13 @@ class ClsLogger {
|
|
|
2324
2438
|
async sendReportLogs(logs) {
|
|
2325
2439
|
if (!this.topicId)
|
|
2326
2440
|
return;
|
|
2327
|
-
const
|
|
2328
|
-
const
|
|
2441
|
+
const sdk = await this.loadSdk();
|
|
2442
|
+
const client = await this.getInstance();
|
|
2443
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2329
2444
|
logGroup.setSource(this.source);
|
|
2330
2445
|
for (const item of logs) {
|
|
2331
2446
|
const fields = this.buildReportFields(item);
|
|
2332
|
-
const log = new
|
|
2447
|
+
const log = new sdk.Log(fields.timestamp);
|
|
2333
2448
|
for (const key of Object.keys(fields)) {
|
|
2334
2449
|
if (key === 'timestamp')
|
|
2335
2450
|
continue;
|
|
@@ -2337,7 +2452,7 @@ class ClsLogger {
|
|
|
2337
2452
|
}
|
|
2338
2453
|
logGroup.addLog(log);
|
|
2339
2454
|
}
|
|
2340
|
-
const request = new
|
|
2455
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2341
2456
|
// 只在“发起网络请求”的同步阶段打标记,避免 requestMonitor 监控 CLS 上报请求导致递归
|
|
2342
2457
|
const exit = enterClsSendingGuard();
|
|
2343
2458
|
let p;
|
package/dist/index.umd.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports'
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.BeLinkClsLogger = {}
|
|
5
|
-
})(this, (function (exports
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.BeLinkClsLogger = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function isPlainObject(value) {
|
|
8
8
|
return Object.prototype.toString.call(value) === '[object Object]';
|
|
@@ -1900,6 +1900,27 @@
|
|
|
1900
1900
|
};
|
|
1901
1901
|
}
|
|
1902
1902
|
|
|
1903
|
+
function readGlobal(key) {
|
|
1904
|
+
try {
|
|
1905
|
+
const g = globalThis;
|
|
1906
|
+
return g[key] ?? null;
|
|
1907
|
+
}
|
|
1908
|
+
catch {
|
|
1909
|
+
return null;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
function tryRequire(moduleName) {
|
|
1913
|
+
try {
|
|
1914
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
1915
|
+
const req = (typeof require === 'function' ? require : null);
|
|
1916
|
+
if (!req)
|
|
1917
|
+
return null;
|
|
1918
|
+
return req(moduleName);
|
|
1919
|
+
}
|
|
1920
|
+
catch {
|
|
1921
|
+
return null;
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1903
1924
|
function enterClsSendingGuard() {
|
|
1904
1925
|
const g = globalThis;
|
|
1905
1926
|
const next = (g.__beLinkClsLoggerSendingCount__ ?? 0) + 1;
|
|
@@ -1911,7 +1932,10 @@
|
|
|
1911
1932
|
}
|
|
1912
1933
|
class ClsLogger {
|
|
1913
1934
|
constructor() {
|
|
1935
|
+
this.sdk = null;
|
|
1936
|
+
this.sdkPromise = null;
|
|
1914
1937
|
this.client = null;
|
|
1938
|
+
this.clientPromise = null;
|
|
1915
1939
|
this.topicId = null;
|
|
1916
1940
|
this.endpoint = 'ap-shanghai.cls.tencentcs.com';
|
|
1917
1941
|
this.retryTimes = 10;
|
|
@@ -1953,6 +1977,19 @@
|
|
|
1953
1977
|
console.warn('ClsLogger.init 没有传 topicID/topic_id');
|
|
1954
1978
|
return;
|
|
1955
1979
|
}
|
|
1980
|
+
const nextEnvType = options.envType ?? this.detectEnvType();
|
|
1981
|
+
// envType/endpoint/retryTimes 变化时:重置 client(以及可能的 sdk)
|
|
1982
|
+
const envChanged = nextEnvType !== this.envType;
|
|
1983
|
+
const endpointChanged = endpoint !== this.endpoint;
|
|
1984
|
+
const retryChanged = retryTimes !== this.retryTimes;
|
|
1985
|
+
if (envChanged || endpointChanged || retryChanged) {
|
|
1986
|
+
this.client = null;
|
|
1987
|
+
this.clientPromise = null;
|
|
1988
|
+
}
|
|
1989
|
+
if (envChanged) {
|
|
1990
|
+
this.sdk = null;
|
|
1991
|
+
this.sdkPromise = null;
|
|
1992
|
+
}
|
|
1956
1993
|
this.topicId = topicId;
|
|
1957
1994
|
this.endpoint = endpoint;
|
|
1958
1995
|
this.retryTimes = retryTimes;
|
|
@@ -1963,7 +2000,7 @@
|
|
|
1963
2000
|
this.projectName = options.projectName ?? this.projectName;
|
|
1964
2001
|
this.appId = options.appId ?? this.appId;
|
|
1965
2002
|
this.appVersion = options.appVersion ?? this.appVersion;
|
|
1966
|
-
this.envType =
|
|
2003
|
+
this.envType = nextEnvType;
|
|
1967
2004
|
this.userGenerateBaseFields = options.generateBaseFields ?? this.userGenerateBaseFields;
|
|
1968
2005
|
this.autoGenerateBaseFields = createAutoDeviceInfoBaseFields(this.envType, options.deviceInfo);
|
|
1969
2006
|
this.storageKey = options.storageKey ?? this.storageKey;
|
|
@@ -1973,8 +2010,10 @@
|
|
|
1973
2010
|
this.startupDelayMs = options.batch?.startupDelayMs ?? this.startupDelayMs;
|
|
1974
2011
|
this.failedCacheKey = options.failedCacheKey ?? this.failedCacheKey;
|
|
1975
2012
|
this.failedCacheMax = options.failedCacheMax ?? this.failedCacheMax;
|
|
1976
|
-
//
|
|
1977
|
-
this.getInstance()
|
|
2013
|
+
// 预热(避免首条日志触发 import/初始化开销)
|
|
2014
|
+
void this.getInstance().catch(() => {
|
|
2015
|
+
// ignore
|
|
2016
|
+
});
|
|
1978
2017
|
// 启动时尝试发送失败缓存
|
|
1979
2018
|
this.flushFailed();
|
|
1980
2019
|
// 初始化后立即启动请求监听
|
|
@@ -2078,14 +2117,70 @@
|
|
|
2078
2117
|
this.behaviorMonitorCleanup = null;
|
|
2079
2118
|
this.behaviorMonitorStarted = false;
|
|
2080
2119
|
}
|
|
2081
|
-
|
|
2120
|
+
/**
|
|
2121
|
+
* 获取 CLS client(按环境懒加载 SDK)
|
|
2122
|
+
* - browser: 优先走 UMD 全局变量 `tencentcloudClsSdkJsWeb`
|
|
2123
|
+
* - miniprogram: 优先走 require(webpack/taro 可解析),否则 fallback import()
|
|
2124
|
+
*/
|
|
2125
|
+
async getInstance() {
|
|
2082
2126
|
if (this.client)
|
|
2083
2127
|
return this.client;
|
|
2084
|
-
this.
|
|
2085
|
-
|
|
2086
|
-
|
|
2128
|
+
if (this.clientPromise)
|
|
2129
|
+
return this.clientPromise;
|
|
2130
|
+
this.clientPromise = this.loadSdk()
|
|
2131
|
+
.then(({ AsyncClient }) => {
|
|
2132
|
+
const client = new AsyncClient({
|
|
2133
|
+
endpoint: this.endpoint,
|
|
2134
|
+
retry_times: this.retryTimes,
|
|
2135
|
+
});
|
|
2136
|
+
this.client = client;
|
|
2137
|
+
return client;
|
|
2138
|
+
})
|
|
2139
|
+
.catch((err) => {
|
|
2140
|
+
// 失败后允许下次重试
|
|
2141
|
+
this.clientPromise = null;
|
|
2142
|
+
throw err;
|
|
2087
2143
|
});
|
|
2088
|
-
return this.
|
|
2144
|
+
return this.clientPromise;
|
|
2145
|
+
}
|
|
2146
|
+
async loadSdk() {
|
|
2147
|
+
if (this.sdk)
|
|
2148
|
+
return this.sdk;
|
|
2149
|
+
if (this.sdkPromise)
|
|
2150
|
+
return this.sdkPromise;
|
|
2151
|
+
const isMini = this.envType === 'miniprogram';
|
|
2152
|
+
const moduleName = isMini ? 'tencentcloud-cls-sdk-js-mini' : 'tencentcloud-cls-sdk-js-web';
|
|
2153
|
+
// UMD(浏览器脚本)优先读全局变量
|
|
2154
|
+
if (!isMini) {
|
|
2155
|
+
const g = readGlobal('tencentcloudClsSdkJsWeb');
|
|
2156
|
+
if (g?.AsyncClient && g?.Log && g?.LogGroup && g?.PutLogsRequest) {
|
|
2157
|
+
this.sdk = g;
|
|
2158
|
+
return this.sdk;
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
// 尽量同步 require(小程序/webpack 里最稳),失败再走 import()
|
|
2162
|
+
const reqMod = tryRequire(moduleName);
|
|
2163
|
+
if (reqMod?.AsyncClient && reqMod?.Log && reqMod?.LogGroup && reqMod?.PutLogsRequest) {
|
|
2164
|
+
this.sdk = reqMod;
|
|
2165
|
+
return this.sdk;
|
|
2166
|
+
}
|
|
2167
|
+
this.sdkPromise = import(moduleName)
|
|
2168
|
+
.then((m) => {
|
|
2169
|
+
const mod = (m?.default && m.default.AsyncClient ? m.default : m);
|
|
2170
|
+
const sdk = {
|
|
2171
|
+
AsyncClient: mod.AsyncClient,
|
|
2172
|
+
Log: mod.Log,
|
|
2173
|
+
LogGroup: mod.LogGroup,
|
|
2174
|
+
PutLogsRequest: mod.PutLogsRequest,
|
|
2175
|
+
};
|
|
2176
|
+
this.sdk = sdk;
|
|
2177
|
+
return sdk;
|
|
2178
|
+
})
|
|
2179
|
+
.catch((err) => {
|
|
2180
|
+
this.sdkPromise = null;
|
|
2181
|
+
throw err;
|
|
2182
|
+
});
|
|
2183
|
+
return this.sdkPromise;
|
|
2089
2184
|
}
|
|
2090
2185
|
detectEnvType() {
|
|
2091
2186
|
const wxAny = globalThis.wx;
|
|
@@ -2117,22 +2212,33 @@
|
|
|
2117
2212
|
appVersion: this.appVersion || undefined,
|
|
2118
2213
|
...normalizedFields,
|
|
2119
2214
|
});
|
|
2120
|
-
|
|
2121
|
-
|
|
2215
|
+
// 同步 API:内部异步发送,避免把网络异常冒泡到业务(尤其小程序)
|
|
2216
|
+
void this.putAsync(finalFields).catch(() => {
|
|
2217
|
+
// ignore
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
async putAsync(finalFields) {
|
|
2221
|
+
if (!this.topicId)
|
|
2222
|
+
return;
|
|
2223
|
+
const sdk = await this.loadSdk();
|
|
2224
|
+
const client = await this.getInstance();
|
|
2225
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2122
2226
|
logGroup.setSource(this.source);
|
|
2123
|
-
const log = new
|
|
2227
|
+
const log = new sdk.Log(Date.now());
|
|
2124
2228
|
for (const key of Object.keys(finalFields)) {
|
|
2125
2229
|
log.addContent(key, stringifyLogValue(finalFields[key]));
|
|
2126
2230
|
}
|
|
2127
2231
|
logGroup.addLog(log);
|
|
2128
|
-
const request = new
|
|
2232
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2129
2233
|
const exit = enterClsSendingGuard();
|
|
2234
|
+
let p;
|
|
2130
2235
|
try {
|
|
2131
|
-
client.PutLogs(request);
|
|
2236
|
+
p = client.PutLogs(request);
|
|
2132
2237
|
}
|
|
2133
2238
|
finally {
|
|
2134
2239
|
exit();
|
|
2135
2240
|
}
|
|
2241
|
+
await p;
|
|
2136
2242
|
}
|
|
2137
2243
|
/**
|
|
2138
2244
|
* 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
|
|
@@ -2191,11 +2297,19 @@
|
|
|
2191
2297
|
console.warn('ClsLogger.putBatch:未初始化 topic_id');
|
|
2192
2298
|
return;
|
|
2193
2299
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2300
|
+
void this.putBatchAsync(queue).catch(() => {
|
|
2301
|
+
// ignore
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
async putBatchAsync(queue) {
|
|
2305
|
+
if (!this.topicId)
|
|
2306
|
+
return;
|
|
2307
|
+
const sdk = await this.loadSdk();
|
|
2308
|
+
const client = await this.getInstance();
|
|
2309
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2196
2310
|
logGroup.setSource(this.source);
|
|
2197
2311
|
for (const item of queue) {
|
|
2198
|
-
const log = new
|
|
2312
|
+
const log = new sdk.Log(item.time);
|
|
2199
2313
|
const data = item.data ?? {};
|
|
2200
2314
|
for (const key of Object.keys(data)) {
|
|
2201
2315
|
log.addContent(key, stringifyLogValue(data[key]));
|
|
@@ -2204,14 +2318,16 @@
|
|
|
2204
2318
|
}
|
|
2205
2319
|
if (logGroup.getLogs().length === 0)
|
|
2206
2320
|
return;
|
|
2207
|
-
const request = new
|
|
2321
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2208
2322
|
const exit = enterClsSendingGuard();
|
|
2323
|
+
let p;
|
|
2209
2324
|
try {
|
|
2210
|
-
client.PutLogs(request);
|
|
2325
|
+
p = client.PutLogs(request);
|
|
2211
2326
|
}
|
|
2212
2327
|
finally {
|
|
2213
2328
|
exit();
|
|
2214
2329
|
}
|
|
2330
|
+
await p;
|
|
2215
2331
|
}
|
|
2216
2332
|
/**
|
|
2217
2333
|
* 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
|
|
@@ -2324,12 +2440,13 @@
|
|
|
2324
2440
|
async sendReportLogs(logs) {
|
|
2325
2441
|
if (!this.topicId)
|
|
2326
2442
|
return;
|
|
2327
|
-
const
|
|
2328
|
-
const
|
|
2443
|
+
const sdk = await this.loadSdk();
|
|
2444
|
+
const client = await this.getInstance();
|
|
2445
|
+
const logGroup = new sdk.LogGroup('127.0.0.1');
|
|
2329
2446
|
logGroup.setSource(this.source);
|
|
2330
2447
|
for (const item of logs) {
|
|
2331
2448
|
const fields = this.buildReportFields(item);
|
|
2332
|
-
const log = new
|
|
2449
|
+
const log = new sdk.Log(fields.timestamp);
|
|
2333
2450
|
for (const key of Object.keys(fields)) {
|
|
2334
2451
|
if (key === 'timestamp')
|
|
2335
2452
|
continue;
|
|
@@ -2337,7 +2454,7 @@
|
|
|
2337
2454
|
}
|
|
2338
2455
|
logGroup.addLog(log);
|
|
2339
2456
|
}
|
|
2340
|
-
const request = new
|
|
2457
|
+
const request = new sdk.PutLogsRequest(this.topicId, logGroup);
|
|
2341
2458
|
// 只在“发起网络请求”的同步阶段打标记,避免 requestMonitor 监控 CLS 上报请求导致递归
|
|
2342
2459
|
const exit = enterClsSendingGuard();
|
|
2343
2460
|
let p;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@be-link/cls-logger",
|
|
3
|
-
"version": "1.0.1-beta.
|
|
3
|
+
"version": "1.0.1-beta.5",
|
|
4
4
|
"description": "@be-link cls-logger - 腾讯云 CLS 日志上报封装",
|
|
5
5
|
"homepage": "https://github.com/snowmountain-top/be-link",
|
|
6
6
|
"author": "zhuiyi",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"tencentcloud-cls-sdk-js-web": "^1.0.11"
|
|
24
|
+
"tencentcloud-cls-sdk-js-web": "^1.0.11",
|
|
25
|
+
"tencentcloud-cls-sdk-js-mini": "^1.0.3"
|
|
25
26
|
},
|
|
26
27
|
"publishConfig": {
|
|
27
28
|
"access": "public"
|