@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.
@@ -1,98 +1,11 @@
1
- import { AsyncClient } from 'tencentcloud-cls-sdk-js-web';
2
- import type { ClsLoggerInitOptions, FlatFields, PutOptions, QueueItem, ReportLog } from './types';
3
- export declare class ClsLogger {
4
- private client;
5
- private topicId;
6
- private endpoint;
7
- private retryTimes;
8
- private source;
9
- private projectId;
10
- private projectName;
11
- private appId;
12
- private appVersion;
13
- private envType;
14
- private userGenerateBaseFields;
15
- private autoGenerateBaseFields;
16
- private storageKey;
17
- private batchSize;
18
- private memoryQueue;
19
- private batchMaxSize;
20
- private batchIntervalMs;
21
- private batchTimer;
22
- private batchTimerDueAt;
23
- private initTs;
24
- private startupDelayMs;
25
- private failedCacheKey;
26
- private failedCacheMax;
27
- private requestMonitorStarted;
28
- private errorMonitorStarted;
29
- private performanceMonitorStarted;
30
- private behaviorMonitorStarted;
31
- private behaviorMonitorCleanup;
32
- userId: unknown;
33
- userName: unknown;
34
- init(options: ClsLoggerInitOptions): void;
35
- private getBaseFields;
36
- private startRequestMonitor;
37
- private startErrorMonitor;
38
- private startPerformanceMonitor;
39
- private startBehaviorMonitor;
40
- /**
41
- * 停止行为埋点监听(PV/UV/点击)
42
- * - 如需重启:可再次调用 init(或自行调用 init 后的默认启动逻辑)
43
- */
44
- stopBehaviorMonitor(): void;
45
- getInstance(): AsyncClient;
46
- private detectEnvType;
47
- /**
48
- * 直接上报:埋点入参必须是一维(扁平)Object
49
- * - 非原始值(对象/数组等)会被自动 stringify 成 string
50
- * - 最终会把 fields 展开成 CLS 的 content(key/value 都会转成 string)
51
- */
52
- put(fields: FlatFields, options?: PutOptions): void;
53
- /**
54
- * 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
55
- */
56
- putJson(data: unknown, clsLoggerKey?: string, options?: PutOptions): void;
57
- /**
58
- * 入队:写入 localStorage 队列;达到 batchSize 自动 flush
59
- * - 埋点入参必须是一维(扁平)Object,非原始值会被 stringify
60
- */
61
- enqueue(fields: FlatFields, options?: PutOptions): void;
62
- /**
63
- * 从 localStorage 读取队列并批量上报
64
- */
65
- flush(): void;
66
- /**
67
- * 批量上报(每条 item.data 展开为 log content)
68
- */
69
- putBatch(queue: QueueItem[]): void;
70
- /**
71
- * 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
72
- */
73
- report(log: ReportLog): void;
74
- private getDesiredBatchFlushDueAt;
75
- info(message: string, data?: FlatFields): void;
76
- warn(message: string, data?: FlatFields): void;
77
- error(message: string, data?: FlatFields): void;
78
- track(trackType: string, data?: FlatFields): void;
79
- /**
80
- * 立即发送内存队列
81
- */
82
- flushBatch(): Promise<void>;
83
- private buildReportFields;
84
- private sendReportLogs;
85
- private retrySendReportLogs;
86
- private cacheFailedReportLogs;
87
- flushFailed(): void;
88
- /**
89
- * 统计/计数类日志:按字段展开上报(若 data 为空默认 1)
90
- */
91
- stat(param: {
92
- pageName: string;
93
- scene: string;
94
- subScene: string;
95
- data?: number | string;
96
- }): void;
1
+ import { ClsLoggerCore } from './ClsLoggerCore';
2
+ import type { ClsSdkModule } from './clsSdkTypes';
3
+ /**
4
+ * 兼容版 ClsLogger(默认入口)
5
+ * - 保留了自动识别环境 + 动态 import 的逻辑
6
+ * - 如果业务想瘦身,建议改用 @be-link/cls-logger/web 或 /mini
7
+ */
8
+ export declare class ClsLogger extends ClsLoggerCore {
9
+ protected loadSdk(): Promise<ClsSdkModule>;
97
10
  }
98
11
  //# sourceMappingURL=ClsLogger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClsLogger.d.ts","sourceRoot":"","sources":["../src/ClsLogger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClsLogger.d.ts","sourceRoot":"","sources":["../src/ClsLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,aAAa;cAC1B,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;CA8EjD"}
@@ -0,0 +1,127 @@
1
+ import type { ClsLoggerInitOptions, EnvType, FlatFields, PutOptions, QueueItem, ReportLog } from './types';
2
+ import type { ClsSdkModule } from './clsSdkTypes';
3
+ /**
4
+ * CLS Logger 核心基类
5
+ * - 负责所有上报、队列、监控逻辑
6
+ * - 不包含具体的 SDK 加载实现(由子类负责)
7
+ * - 这样可以把 web/mini 的 SDK 依赖彻底解耦到子入口
8
+ */
9
+ export declare abstract class ClsLoggerCore {
10
+ protected sdk: ClsSdkModule | null;
11
+ protected sdkPromise: Promise<ClsSdkModule> | null;
12
+ protected sdkOverride: unknown | null;
13
+ protected sdkLoaderOverride: (() => unknown | Promise<unknown>) | null;
14
+ protected client: {
15
+ PutLogs: (request: unknown) => Promise<unknown> | unknown;
16
+ } | null;
17
+ protected clientPromise: Promise<{
18
+ PutLogs: (request: unknown) => Promise<unknown> | unknown;
19
+ }> | null;
20
+ protected topicId: string | null;
21
+ protected endpoint: string;
22
+ protected retryTimes: number;
23
+ protected source: string;
24
+ protected projectId: string;
25
+ protected projectName: string;
26
+ protected appId: string;
27
+ protected appVersion: string;
28
+ protected envType: EnvType;
29
+ protected userGenerateBaseFields: (() => FlatFields) | null;
30
+ protected autoGenerateBaseFields: (() => FlatFields) | null;
31
+ protected storageKey: string;
32
+ protected batchSize: number;
33
+ protected memoryQueue: ReportLog[];
34
+ protected batchMaxSize: number;
35
+ protected batchIntervalMs: number;
36
+ protected batchTimer: ReturnType<typeof setTimeout> | null;
37
+ protected batchTimerDueAt: number | null;
38
+ protected initTs: number;
39
+ protected startupDelayMs: number;
40
+ protected failedCacheKey: string;
41
+ protected failedCacheMax: number;
42
+ protected requestMonitorStarted: boolean;
43
+ protected errorMonitorStarted: boolean;
44
+ protected performanceMonitorStarted: boolean;
45
+ protected behaviorMonitorStarted: boolean;
46
+ protected behaviorMonitorCleanup: (() => void) | null;
47
+ userId: unknown;
48
+ userName: unknown;
49
+ /**
50
+ * 子类必须实现此方法来加载 SDK
51
+ */
52
+ protected abstract loadSdk(): Promise<ClsSdkModule>;
53
+ /**
54
+ * 子类可按需重写(默认检测 wx)
55
+ */
56
+ protected detectEnvType(): EnvType;
57
+ init(options: ClsLoggerInitOptions): void;
58
+ private getBaseFields;
59
+ private startRequestMonitor;
60
+ private startErrorMonitor;
61
+ private startPerformanceMonitor;
62
+ private startBehaviorMonitor;
63
+ /**
64
+ * 停止行为埋点监听(PV/UV/点击)
65
+ * - 如需重启:可再次调用 init(或自行调用 init 后的默认启动逻辑)
66
+ */
67
+ stopBehaviorMonitor(): void;
68
+ /**
69
+ * 获取 CLS client(按环境懒加载 SDK)
70
+ */
71
+ getInstance(): Promise<{
72
+ PutLogs: (request: unknown) => Promise<unknown> | unknown;
73
+ }>;
74
+ /**
75
+ * 直接上报:埋点入参必须是一维(扁平)Object
76
+ * - 非原始值(对象/数组等)会被自动 stringify 成 string
77
+ * - 最终会把 fields 展开成 CLS 的 content(key/value 都会转成 string)
78
+ */
79
+ put(fields: FlatFields, options?: PutOptions): void;
80
+ private putAsync;
81
+ /**
82
+ * 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
83
+ */
84
+ putJson(data: unknown, clsLoggerKey?: string, options?: PutOptions): void;
85
+ /**
86
+ * 入队:写入 localStorage 队列;达到 batchSize 自动 flush
87
+ * - 埋点入参必须是一维(扁平)Object,非原始值会被 stringify
88
+ */
89
+ enqueue(fields: FlatFields, options?: PutOptions): void;
90
+ /**
91
+ * 从 localStorage 读取队列并批量上报
92
+ */
93
+ flush(): void;
94
+ /**
95
+ * 批量上报(每条 item.data 展开为 log content)
96
+ */
97
+ putBatch(queue: QueueItem[]): void;
98
+ private putBatchAsync;
99
+ /**
100
+ * 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
101
+ */
102
+ report(log: ReportLog): void;
103
+ private getDesiredBatchFlushDueAt;
104
+ info(message: string, data?: FlatFields): void;
105
+ warn(message: string, data?: FlatFields): void;
106
+ error(message: string, data?: FlatFields): void;
107
+ track(trackType: string, data?: FlatFields): void;
108
+ /**
109
+ * 立即发送内存队列
110
+ */
111
+ flushBatch(): Promise<void>;
112
+ private buildReportFields;
113
+ private sendReportLogs;
114
+ private retrySendReportLogs;
115
+ private cacheFailedReportLogs;
116
+ flushFailed(): void;
117
+ /**
118
+ * 统计/计数类日志:按字段展开上报(若 data 为空默认 1)
119
+ */
120
+ stat(param: {
121
+ pageName: string;
122
+ scene: string;
123
+ subScene: string;
124
+ data?: number | string;
125
+ }): void;
126
+ }
127
+ //# sourceMappingURL=ClsLoggerCore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClsLoggerCore.d.ts","sourceRoot":"","sources":["../src/ClsLoggerCore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { ClsLoggerCore } from './ClsLoggerCore';
2
+ import type { ClsSdkModule } from './clsSdkTypes';
3
+ export declare class ClsLoggerMini extends ClsLoggerCore {
4
+ protected envType: import('./types').EnvType;
5
+ protected loadSdk(): Promise<ClsSdkModule>;
6
+ private normalize;
7
+ }
8
+ //# sourceMappingURL=ClsLoggerMini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClsLoggerMini.d.ts","sourceRoot":"","sources":["../src/ClsLoggerMini.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAKlD,qBAAa,aAAc,SAAQ,aAAa;IAC9C,SAAS,CAAC,OAAO,EAAE,OAAO,SAAS,EAAE,OAAO,CAAiB;cAE7C,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAkBhD,OAAO,CAAC,SAAS;CAYlB"}
@@ -0,0 +1,8 @@
1
+ import { ClsLoggerCore } from './ClsLoggerCore';
2
+ import type { ClsSdkModule } from './clsSdkTypes';
3
+ export declare class ClsLoggerWeb extends ClsLoggerCore {
4
+ protected envType: import('./types').EnvType;
5
+ protected loadSdk(): Promise<ClsSdkModule>;
6
+ private normalize;
7
+ }
8
+ //# sourceMappingURL=ClsLoggerWeb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClsLoggerWeb.d.ts","sourceRoot":"","sources":["../src/ClsLoggerWeb.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAKlD,qBAAa,YAAa,SAAQ,aAAa;IAC7C,SAAS,CAAC,OAAO,EAAE,OAAO,SAAS,EAAE,OAAO,CAAa;cAEzC,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAahD,OAAO,CAAC,SAAS;CASlB"}
@@ -0,0 +1,18 @@
1
+ export type ClsSdkModule = {
2
+ AsyncClient: new (options: {
3
+ endpoint: string;
4
+ retry_times?: number;
5
+ }) => {
6
+ PutLogs: (request: unknown) => Promise<unknown> | unknown;
7
+ };
8
+ Log: new (time: number) => {
9
+ addContent: (k: string, v: string) => void;
10
+ };
11
+ LogGroup: new (source: string) => {
12
+ setSource: (source: string) => void;
13
+ addLog: (log: unknown) => void;
14
+ getLogs: () => unknown[];
15
+ };
16
+ PutLogsRequest: new (topicId: string, logGroup: unknown) => unknown;
17
+ };
18
+ //# sourceMappingURL=clsSdkTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clsSdkTypes.d.ts","sourceRoot":"","sources":["../src/clsSdkTypes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,KAAK,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK;QACxE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;KAC3D,CAAC;IACF,GAAG,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK;QAAE,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IAC1E,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,KAAK;QAChC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;QACpC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;QAC/B,OAAO,EAAE,MAAM,OAAO,EAAE,CAAC;KAC1B,CAAC;IACF,cAAc,EAAE,KAAK,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC;CACrE,CAAC"}
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
  }
@@ -1905,9 +1903,20 @@ function enterClsSendingGuard() {
1905
1903
  g.__beLinkClsLoggerSendingCount__ = cur > 0 ? cur - 1 : 0;
1906
1904
  };
1907
1905
  }
1908
- class ClsLogger {
1906
+ /**
1907
+ * CLS Logger 核心基类
1908
+ * - 负责所有上报、队列、监控逻辑
1909
+ * - 不包含具体的 SDK 加载实现(由子类负责)
1910
+ * - 这样可以把 web/mini 的 SDK 依赖彻底解耦到子入口
1911
+ */
1912
+ class ClsLoggerCore {
1909
1913
  constructor() {
1914
+ this.sdk = null;
1915
+ this.sdkPromise = null;
1916
+ this.sdkOverride = null;
1917
+ this.sdkLoaderOverride = null;
1910
1918
  this.client = null;
1919
+ this.clientPromise = null;
1911
1920
  this.topicId = null;
1912
1921
  this.endpoint = 'ap-shanghai.cls.tencentcs.com';
1913
1922
  this.retryTimes = 10;
@@ -1938,6 +1947,15 @@ class ClsLogger {
1938
1947
  this.behaviorMonitorStarted = false;
1939
1948
  this.behaviorMonitorCleanup = null;
1940
1949
  }
1950
+ /**
1951
+ * 子类可按需重写(默认检测 wx)
1952
+ */
1953
+ detectEnvType() {
1954
+ const wxAny = globalThis.wx;
1955
+ if (wxAny && typeof wxAny.getSystemInfoSync === 'function')
1956
+ return 'miniprogram';
1957
+ return 'browser';
1958
+ }
1941
1959
  init(options) {
1942
1960
  this.initTs = Date.now();
1943
1961
  const topicId = options?.tencentCloud?.topicID ?? options?.topic_id ?? options?.topicID ?? this.topicId ?? null;
@@ -1949,6 +1967,19 @@ class ClsLogger {
1949
1967
  console.warn('ClsLogger.init 没有传 topicID/topic_id');
1950
1968
  return;
1951
1969
  }
1970
+ const nextEnvType = options.envType ?? this.detectEnvType();
1971
+ // envType/endpoint/retryTimes 变化时:重置 client(以及可能的 sdk)
1972
+ const envChanged = nextEnvType !== this.envType;
1973
+ const endpointChanged = endpoint !== this.endpoint;
1974
+ const retryChanged = retryTimes !== this.retryTimes;
1975
+ if (envChanged || endpointChanged || retryChanged) {
1976
+ this.client = null;
1977
+ this.clientPromise = null;
1978
+ }
1979
+ if (envChanged) {
1980
+ this.sdk = null;
1981
+ this.sdkPromise = null;
1982
+ }
1952
1983
  this.topicId = topicId;
1953
1984
  this.endpoint = endpoint;
1954
1985
  this.retryTimes = retryTimes;
@@ -1959,7 +1990,10 @@ class ClsLogger {
1959
1990
  this.projectName = options.projectName ?? this.projectName;
1960
1991
  this.appId = options.appId ?? this.appId;
1961
1992
  this.appVersion = options.appVersion ?? this.appVersion;
1962
- this.envType = options.envType ?? this.detectEnvType();
1993
+ this.envType = nextEnvType;
1994
+ // 可选:外部注入 SDK(优先级:sdkLoader > sdk)
1995
+ this.sdkLoaderOverride = options.sdkLoader ?? this.sdkLoaderOverride;
1996
+ this.sdkOverride = options.sdk ?? this.sdkOverride;
1963
1997
  this.userGenerateBaseFields = options.generateBaseFields ?? this.userGenerateBaseFields;
1964
1998
  this.autoGenerateBaseFields = createAutoDeviceInfoBaseFields(this.envType, options.deviceInfo);
1965
1999
  this.storageKey = options.storageKey ?? this.storageKey;
@@ -1969,8 +2003,10 @@ class ClsLogger {
1969
2003
  this.startupDelayMs = options.batch?.startupDelayMs ?? this.startupDelayMs;
1970
2004
  this.failedCacheKey = options.failedCacheKey ?? this.failedCacheKey;
1971
2005
  this.failedCacheMax = options.failedCacheMax ?? this.failedCacheMax;
1972
- // 预热 client
1973
- this.getInstance();
2006
+ // 预热(避免首条日志触发 import/初始化开销)
2007
+ void this.getInstance().catch(() => {
2008
+ // ignore
2009
+ });
1974
2010
  // 启动时尝试发送失败缓存
1975
2011
  this.flushFailed();
1976
2012
  // 初始化后立即启动请求监听
@@ -2074,20 +2110,29 @@ class ClsLogger {
2074
2110
  this.behaviorMonitorCleanup = null;
2075
2111
  this.behaviorMonitorStarted = false;
2076
2112
  }
2077
- getInstance() {
2113
+ /**
2114
+ * 获取 CLS client(按环境懒加载 SDK)
2115
+ */
2116
+ async getInstance() {
2078
2117
  if (this.client)
2079
2118
  return this.client;
2080
- this.client = new AsyncClient({
2081
- endpoint: this.endpoint,
2082
- retry_times: this.retryTimes,
2119
+ if (this.clientPromise)
2120
+ return this.clientPromise;
2121
+ this.clientPromise = this.loadSdk()
2122
+ .then(({ AsyncClient }) => {
2123
+ const client = new AsyncClient({
2124
+ endpoint: this.endpoint,
2125
+ retry_times: this.retryTimes,
2126
+ });
2127
+ this.client = client;
2128
+ return client;
2129
+ })
2130
+ .catch((err) => {
2131
+ // 失败后允许下次重试
2132
+ this.clientPromise = null;
2133
+ throw err;
2083
2134
  });
2084
- return this.client;
2085
- }
2086
- detectEnvType() {
2087
- const wxAny = globalThis.wx;
2088
- if (wxAny && typeof wxAny.getSystemInfoSync === 'function')
2089
- return 'miniprogram';
2090
- return 'browser';
2135
+ return this.clientPromise;
2091
2136
  }
2092
2137
  /**
2093
2138
  * 直接上报:埋点入参必须是一维(扁平)Object
@@ -2113,22 +2158,33 @@ class ClsLogger {
2113
2158
  appVersion: this.appVersion || undefined,
2114
2159
  ...normalizedFields,
2115
2160
  });
2116
- const client = this.getInstance();
2117
- const logGroup = new LogGroup('127.0.0.1');
2161
+ // 同步 API:内部异步发送,避免把网络异常冒泡到业务(尤其小程序)
2162
+ void this.putAsync(finalFields).catch(() => {
2163
+ // ignore
2164
+ });
2165
+ }
2166
+ async putAsync(finalFields) {
2167
+ if (!this.topicId)
2168
+ return;
2169
+ const sdk = await this.loadSdk();
2170
+ const client = await this.getInstance();
2171
+ const logGroup = new sdk.LogGroup('127.0.0.1');
2118
2172
  logGroup.setSource(this.source);
2119
- const log = new Log(Date.now());
2173
+ const log = new sdk.Log(Date.now());
2120
2174
  for (const key of Object.keys(finalFields)) {
2121
2175
  log.addContent(key, stringifyLogValue(finalFields[key]));
2122
2176
  }
2123
2177
  logGroup.addLog(log);
2124
- const request = new PutLogsRequest(this.topicId, logGroup);
2178
+ const request = new sdk.PutLogsRequest(this.topicId, logGroup);
2125
2179
  const exit = enterClsSendingGuard();
2180
+ let p;
2126
2181
  try {
2127
- client.PutLogs(request);
2182
+ p = client.PutLogs(request);
2128
2183
  }
2129
2184
  finally {
2130
2185
  exit();
2131
2186
  }
2187
+ await p;
2132
2188
  }
2133
2189
  /**
2134
2190
  * 直接上报:把 data 序列化后放入指定 key(默认 “日志内容”)
@@ -2187,11 +2243,19 @@ class ClsLogger {
2187
2243
  console.warn('ClsLogger.putBatch:未初始化 topic_id');
2188
2244
  return;
2189
2245
  }
2190
- const client = this.getInstance();
2191
- const logGroup = new LogGroup('127.0.0.1');
2246
+ void this.putBatchAsync(queue).catch(() => {
2247
+ // ignore
2248
+ });
2249
+ }
2250
+ async putBatchAsync(queue) {
2251
+ if (!this.topicId)
2252
+ return;
2253
+ const sdk = await this.loadSdk();
2254
+ const client = await this.getInstance();
2255
+ const logGroup = new sdk.LogGroup('127.0.0.1');
2192
2256
  logGroup.setSource(this.source);
2193
2257
  for (const item of queue) {
2194
- const log = new Log(item.time);
2258
+ const log = new sdk.Log(item.time);
2195
2259
  const data = item.data ?? {};
2196
2260
  for (const key of Object.keys(data)) {
2197
2261
  log.addContent(key, stringifyLogValue(data[key]));
@@ -2200,14 +2264,16 @@ class ClsLogger {
2200
2264
  }
2201
2265
  if (logGroup.getLogs().length === 0)
2202
2266
  return;
2203
- const request = new PutLogsRequest(this.topicId, logGroup);
2267
+ const request = new sdk.PutLogsRequest(this.topicId, logGroup);
2204
2268
  const exit = enterClsSendingGuard();
2269
+ let p;
2205
2270
  try {
2206
- client.PutLogs(request);
2271
+ p = client.PutLogs(request);
2207
2272
  }
2208
2273
  finally {
2209
2274
  exit();
2210
2275
  }
2276
+ await p;
2211
2277
  }
2212
2278
  /**
2213
2279
  * 参考《一、概述》:统一上报入口(内存队列 + 批量发送)
@@ -2320,12 +2386,13 @@ class ClsLogger {
2320
2386
  async sendReportLogs(logs) {
2321
2387
  if (!this.topicId)
2322
2388
  return;
2323
- const client = this.getInstance();
2324
- const logGroup = new LogGroup('127.0.0.1');
2389
+ const sdk = await this.loadSdk();
2390
+ const client = await this.getInstance();
2391
+ const logGroup = new sdk.LogGroup('127.0.0.1');
2325
2392
  logGroup.setSource(this.source);
2326
2393
  for (const item of logs) {
2327
2394
  const fields = this.buildReportFields(item);
2328
- const log = new Log(fields.timestamp);
2395
+ const log = new sdk.Log(fields.timestamp);
2329
2396
  for (const key of Object.keys(fields)) {
2330
2397
  if (key === 'timestamp')
2331
2398
  continue;
@@ -2333,7 +2400,7 @@ class ClsLogger {
2333
2400
  }
2334
2401
  logGroup.addLog(log);
2335
2402
  }
2336
- const request = new PutLogsRequest(this.topicId, logGroup);
2403
+ const request = new sdk.PutLogsRequest(this.topicId, logGroup);
2337
2404
  // 只在“发起网络请求”的同步阶段打标记,避免 requestMonitor 监控 CLS 上报请求导致递归
2338
2405
  const exit = enterClsSendingGuard();
2339
2406
  let p;
@@ -2409,6 +2476,122 @@ class ClsLogger {
2409
2476
  }
2410
2477
  }
2411
2478
 
2479
+ function readGlobal(key) {
2480
+ try {
2481
+ const g = globalThis;
2482
+ return g[key] ?? null;
2483
+ }
2484
+ catch {
2485
+ return null;
2486
+ }
2487
+ }
2488
+ function tryRequire(moduleName) {
2489
+ try {
2490
+ // 说明:
2491
+ // - ESM 构建(exports.import/module)里通常不存在模块作用域的 require
2492
+ // - 一些小程序运行时/构建链路会把 require 挂到 globalThis 上
2493
+ // 因此这里同时探测“模块作用域 require”与 “globalThis.require”
2494
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
2495
+ const localReq = (typeof require === 'function' ? require : null);
2496
+ const globalReq = readGlobal('require');
2497
+ const candidates = [localReq, globalReq].filter((fn) => typeof fn === 'function');
2498
+ for (const fn of candidates) {
2499
+ try {
2500
+ return fn(moduleName);
2501
+ }
2502
+ catch {
2503
+ // continue
2504
+ }
2505
+ }
2506
+ return null;
2507
+ }
2508
+ catch {
2509
+ return null;
2510
+ }
2511
+ }
2512
+
2513
+ /**
2514
+ * 兼容版 ClsLogger(默认入口)
2515
+ * - 保留了自动识别环境 + 动态 import 的逻辑
2516
+ * - 如果业务想瘦身,建议改用 @be-link/cls-logger/web 或 /mini
2517
+ */
2518
+ class ClsLogger extends ClsLoggerCore {
2519
+ async loadSdk() {
2520
+ if (this.sdk)
2521
+ return this.sdk;
2522
+ if (this.sdkPromise)
2523
+ return this.sdkPromise;
2524
+ const normalizeSdk = (m) => {
2525
+ const mod = (m?.default && m.default.AsyncClient ? m.default : m);
2526
+ if (mod?.AsyncClient && mod?.Log && mod?.LogGroup && mod?.PutLogsRequest) {
2527
+ return {
2528
+ AsyncClient: mod.AsyncClient,
2529
+ Log: mod.Log,
2530
+ LogGroup: mod.LogGroup,
2531
+ PutLogsRequest: mod.PutLogsRequest,
2532
+ };
2533
+ }
2534
+ return null;
2535
+ };
2536
+ // 1) 外部注入的 loader(最高优先级)
2537
+ if (this.sdkLoaderOverride) {
2538
+ try {
2539
+ const loaded = await this.sdkLoaderOverride();
2540
+ const sdk = normalizeSdk(loaded);
2541
+ if (sdk) {
2542
+ this.sdk = sdk;
2543
+ return sdk;
2544
+ }
2545
+ }
2546
+ catch {
2547
+ // ignore and fallback
2548
+ }
2549
+ }
2550
+ // 2) 外部直接注入的 sdk
2551
+ if (this.sdkOverride) {
2552
+ const sdk = normalizeSdk(this.sdkOverride);
2553
+ if (sdk) {
2554
+ this.sdk = sdk;
2555
+ return sdk;
2556
+ }
2557
+ }
2558
+ const isMini = this.envType === 'miniprogram';
2559
+ // 静态字面量,方便打包器识别(但在此兼容入口里,仍然可能被一起分析)
2560
+ const WEB_SDK = 'tencentcloud-cls-sdk-js-web';
2561
+ const MINI_SDK = 'tencentcloud-cls-sdk-js-mini';
2562
+ // UMD(浏览器脚本)优先读全局变量
2563
+ if (!isMini) {
2564
+ const g = readGlobal('tencentcloudClsSdkJsWeb');
2565
+ const sdk = normalizeSdk(g);
2566
+ if (sdk) {
2567
+ this.sdk = sdk;
2568
+ return sdk;
2569
+ }
2570
+ }
2571
+ // 尽量同步 require
2572
+ const reqMod = tryRequire(isMini ? MINI_SDK : WEB_SDK);
2573
+ const reqSdk = normalizeSdk(reqMod);
2574
+ if (reqSdk) {
2575
+ this.sdk = reqSdk;
2576
+ return reqSdk;
2577
+ }
2578
+ // 动态 import
2579
+ this.sdkPromise = (isMini ? import(MINI_SDK) : import(WEB_SDK))
2580
+ .then((m) => {
2581
+ const sdk = normalizeSdk(m);
2582
+ if (!sdk)
2583
+ throw new Error(`ClsLogger.loadSdk: invalid sdk module for ${isMini ? MINI_SDK : WEB_SDK}`);
2584
+ this.sdk = sdk;
2585
+ return sdk;
2586
+ })
2587
+ .catch((err) => {
2588
+ this.sdkPromise = null;
2589
+ throw err;
2590
+ });
2591
+ return this.sdkPromise;
2592
+ }
2593
+ }
2594
+
2412
2595
  const clsLogger = new ClsLogger();
2413
2596
 
2414
2597
  export { ClsLogger, clsLogger, clsLogger as default };