polyv-rum-sdk 0.1.8 → 0.1.11
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/index.js +0 -1
- package/dist/index.mjs +0 -1
- package/package.json +5 -3
- package/.github/workflows/publish.yml +0 -34
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/jest.config.cjs +0 -8
- package/src/__tests__/SLSWebTrackingAdapter.test.ts +0 -46
- package/src/__tests__/config.test.ts +0 -76
- package/src/core/MitoSLSAdapter.ts +0 -469
- package/src/core/config.ts +0 -338
- package/src/core/env.ts +0 -17
- package/src/index.ts +0 -26
- package/src/transport/SLSWebTrackingAdapter.ts +0 -626
- package/src/types/aliyun-web-track-browser-es.d.ts +0 -4
- package/src/types/external.d.ts +0 -8
- package/src/vue2/RUMManager.vue2.ts +0 -487
- package/src/vue2/plugin.vue2.ts +0 -56
- package/src/vue3/RUMManager.vue3.ts +0 -56
- package/src/vue3/plugin.vue3.ts +0 -40
- package/tsconfig.json +0 -16
|
@@ -1,626 +0,0 @@
|
|
|
1
|
-
import SlsTracker from '@aliyun-sls/web-track-browser/dist/web-track-browser.es.js';
|
|
2
|
-
import { getRUMEnv } from '../core/env';
|
|
3
|
-
|
|
4
|
-
const getEnv = (key: string, defaultValue = ''): string => {
|
|
5
|
-
const env = getRUMEnv();
|
|
6
|
-
if (env && Object.prototype.hasOwnProperty.call(env, key)) {
|
|
7
|
-
return (env as any)[key] || defaultValue;
|
|
8
|
-
}
|
|
9
|
-
return defaultValue;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export interface SLSAdapterConfig {
|
|
13
|
-
host?: string;
|
|
14
|
-
project?: string;
|
|
15
|
-
logstore?: string;
|
|
16
|
-
time?: number;
|
|
17
|
-
count?: number;
|
|
18
|
-
topic?: string;
|
|
19
|
-
source?: string;
|
|
20
|
-
environment?: string;
|
|
21
|
-
debug?: boolean;
|
|
22
|
-
enabled?: boolean;
|
|
23
|
-
userId?: string | null;
|
|
24
|
-
sessionId?: string;
|
|
25
|
-
appName?: string;
|
|
26
|
-
appVersion?: string;
|
|
27
|
-
retryCount?: number;
|
|
28
|
-
retryInterval?: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export class SLSWebTrackingAdapter {
|
|
32
|
-
private config: Required<SLSAdapterConfig>;
|
|
33
|
-
private slsTracker: any = null;
|
|
34
|
-
private isInitialized = false;
|
|
35
|
-
private isDestroyed = false;
|
|
36
|
-
private pendingLogs: any[] = [];
|
|
37
|
-
private retryQueue: Array<{
|
|
38
|
-
data: any;
|
|
39
|
-
error: Error;
|
|
40
|
-
timestamp: number;
|
|
41
|
-
retryCount: number;
|
|
42
|
-
}> = [];
|
|
43
|
-
|
|
44
|
-
constructor(config: SLSAdapterConfig = {}) {
|
|
45
|
-
this.config = {
|
|
46
|
-
host:
|
|
47
|
-
config.host || getEnv('VUE_APP_SLS_HOST') || '',
|
|
48
|
-
project:
|
|
49
|
-
config.project || getEnv('VUE_APP_SLS_PROJECT') || '',
|
|
50
|
-
logstore:
|
|
51
|
-
config.logstore || getEnv('VUE_APP_SLS_LOGSTORE') || '',
|
|
52
|
-
time: config.time ?? 10,
|
|
53
|
-
count: config.count ?? 10,
|
|
54
|
-
topic: config.topic || 'rum-monitor',
|
|
55
|
-
source: config.source || 'web',
|
|
56
|
-
environment: config.environment || getEnv('NODE_ENV', 'development'),
|
|
57
|
-
debug: config.debug ?? (getEnv('VUE_APP_RUM_DEBUG', 'false') === 'true'),
|
|
58
|
-
enabled: config.enabled ?? true,
|
|
59
|
-
userId: config.userId ?? null,
|
|
60
|
-
sessionId: config.sessionId || this.generateSessionId(),
|
|
61
|
-
appName:
|
|
62
|
-
config.appName || getEnv('VUE_APP_RUM_APP_NAME', 'rum-app'),
|
|
63
|
-
appVersion: config.appVersion || getEnv('PACKAGE_VERSION', '1.0.0'),
|
|
64
|
-
retryCount: config.retryCount ?? 3,
|
|
65
|
-
retryInterval: config.retryInterval ?? 2000
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
this.handleBeforeSend = this.handleBeforeSend.bind(this);
|
|
69
|
-
this.handleError = this.handleError.bind(this);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async init(): Promise<void> {
|
|
73
|
-
if (this.isInitialized) {
|
|
74
|
-
console.warn('SLSWebTrackingAdapter already initialized');
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (this.isDestroyed) {
|
|
79
|
-
throw new Error(
|
|
80
|
-
'SLSWebTrackingAdapter has been destroyed, cannot reinitialize'
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!this.config.enabled) {
|
|
85
|
-
if (this.config.debug) {
|
|
86
|
-
console.log('SLSWebTrackingAdapter is disabled');
|
|
87
|
-
}
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (this.config.debug) {
|
|
92
|
-
console.log('🚀 Initializing SLSWebTrackingAdapter...', {
|
|
93
|
-
config: this.config,
|
|
94
|
-
SlsTracker: typeof SlsTracker
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
this.slsTracker = new (SlsTracker as any)({
|
|
100
|
-
host: this.config.host,
|
|
101
|
-
project: this.config.project,
|
|
102
|
-
logstore: this.config.logstore,
|
|
103
|
-
time: this.config.time,
|
|
104
|
-
count: this.config.count,
|
|
105
|
-
topic: this.config.topic,
|
|
106
|
-
source: this.config.source,
|
|
107
|
-
autoPopulateFields: false,
|
|
108
|
-
beforeSend: this.handleBeforeSend
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
this.isInitialized = true;
|
|
112
|
-
|
|
113
|
-
if (this.config.debug) {
|
|
114
|
-
console.log('✅ SLSWebTrackingAdapter initialized successfully', {
|
|
115
|
-
project: this.config.project,
|
|
116
|
-
logstore: this.config.logstore,
|
|
117
|
-
host: this.config.host,
|
|
118
|
-
trackerInstance: !!this.slsTracker
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
await this.sendLog({
|
|
123
|
-
type: 'system',
|
|
124
|
-
category: 'init',
|
|
125
|
-
message: 'SLS WebTracking adapter initialized successfully',
|
|
126
|
-
level: 'info',
|
|
127
|
-
timestamp: Date.now()
|
|
128
|
-
});
|
|
129
|
-
} catch (error: any) {
|
|
130
|
-
console.error('❌ Failed to initialize SLSWebTrackingAdapter:', error);
|
|
131
|
-
this.handleError(error);
|
|
132
|
-
throw error;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async sendLog(data: Record<string, any>): Promise<void> {
|
|
137
|
-
if (this.config.debug) {
|
|
138
|
-
console.log('📤 Sending log to SLS...', {
|
|
139
|
-
originalData: data,
|
|
140
|
-
isReady: this.checkReady(),
|
|
141
|
-
hasTracker: !!this.slsTracker,
|
|
142
|
-
isInitialized: this.isInitialized
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (!this.checkReady()) {
|
|
147
|
-
if (this.config.debug) {
|
|
148
|
-
console.log('❌ SLS adapter not ready, skipping log send');
|
|
149
|
-
}
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
const logData = await this.transformLogData(data);
|
|
155
|
-
|
|
156
|
-
if (this.config.debug) {
|
|
157
|
-
console.log('🔧 Transformed SLS Log Data:', logData);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
await this.slsTracker.send(logData);
|
|
161
|
-
|
|
162
|
-
if (this.config.debug) {
|
|
163
|
-
console.log('✅ Log sent to SLS successfully');
|
|
164
|
-
}
|
|
165
|
-
} catch (error: any) {
|
|
166
|
-
console.error('❌ Failed to send log to SLS:', error);
|
|
167
|
-
await this.handleSendError(data, error);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async sendBatchLogs(logs: Record<string, any>[]): Promise<void> {
|
|
172
|
-
if (!this.checkReady()) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (!Array.isArray(logs) || logs.length === 0) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
const transformedLogs = await Promise.all(
|
|
182
|
-
logs.map((log) => this.transformLogData(log))
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
for (const logData of transformedLogs) {
|
|
186
|
-
await this.slsTracker.send(logData);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (this.config.debug) {
|
|
190
|
-
console.log(
|
|
191
|
-
`Batch sent ${transformedLogs.length} logs to SLS successfully`
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
} catch (error) {
|
|
195
|
-
console.error('Failed to send batch logs to SLS:', error);
|
|
196
|
-
|
|
197
|
-
for (const log of logs) {
|
|
198
|
-
await this.handleSendError(log, error as any);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
async transformLogData(data: Record<string, any>): Promise<Record<string, any>> {
|
|
204
|
-
const timestamp = Math.floor(Date.now() / 1000);
|
|
205
|
-
|
|
206
|
-
const logData: Record<string, any> = {
|
|
207
|
-
__time__: timestamp,
|
|
208
|
-
__source__: this.config.source,
|
|
209
|
-
|
|
210
|
-
// 基础信息
|
|
211
|
-
event_type: data.eventType || data.type || 'unknown',
|
|
212
|
-
category: data.category || 'general',
|
|
213
|
-
level: data.level || 'info',
|
|
214
|
-
client_timestamp: Date.now(),
|
|
215
|
-
|
|
216
|
-
// 应用信息
|
|
217
|
-
app_name: this.config.appName,
|
|
218
|
-
// app_version: this.config.appVersion,
|
|
219
|
-
environment: this.config.environment,
|
|
220
|
-
|
|
221
|
-
// 会话信息
|
|
222
|
-
session_id: this.config.sessionId,
|
|
223
|
-
|
|
224
|
-
// 页面信息
|
|
225
|
-
page_url:
|
|
226
|
-
typeof window !== 'undefined' && window.location
|
|
227
|
-
? window.location.href
|
|
228
|
-
: '',
|
|
229
|
-
page_title:
|
|
230
|
-
typeof document !== 'undefined' ? document.title : undefined,
|
|
231
|
-
page_path:
|
|
232
|
-
typeof window !== 'undefined' && window.location
|
|
233
|
-
? window.location.pathname
|
|
234
|
-
: '',
|
|
235
|
-
|
|
236
|
-
// 用户代理信息
|
|
237
|
-
user_agent:
|
|
238
|
-
typeof navigator !== 'undefined' ? navigator.userAgent : undefined,
|
|
239
|
-
language:
|
|
240
|
-
typeof navigator !== 'undefined' ? navigator.language : undefined
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
// 用户标识,优先使用上游数据
|
|
244
|
-
if (this.config.userId) {
|
|
245
|
-
logData.user_id = this.config.userId;
|
|
246
|
-
}
|
|
247
|
-
if (data.userId) {
|
|
248
|
-
logData.user_id = data.userId;
|
|
249
|
-
}
|
|
250
|
-
if (data.userName) {
|
|
251
|
-
logData.user_name = data.userName;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
let isInternalUser = false;
|
|
255
|
-
if (data.userEmail && typeof data.userEmail === 'string') {
|
|
256
|
-
const emailParts = data.userEmail.split('@');
|
|
257
|
-
if (emailParts.length === 2) {
|
|
258
|
-
const domain = emailParts[1].toLowerCase();
|
|
259
|
-
const internalDomains = getEnv(
|
|
260
|
-
'VUE_APP_RUM_INTERNAL_EMAIL_DOMAINS',
|
|
261
|
-
'polyv.net,polyv.com'
|
|
262
|
-
)
|
|
263
|
-
.split(',')
|
|
264
|
-
.map((item) => item.trim().toLowerCase())
|
|
265
|
-
.filter(Boolean);
|
|
266
|
-
if (internalDomains.length > 0 && domain) {
|
|
267
|
-
isInternalUser = internalDomains.some((internalDomain) => {
|
|
268
|
-
if (!internalDomain) return false;
|
|
269
|
-
return (
|
|
270
|
-
domain === internalDomain ||
|
|
271
|
-
domain.endsWith(`.${internalDomain}`)
|
|
272
|
-
);
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
logData.is_internal_user = isInternalUser;
|
|
279
|
-
|
|
280
|
-
// 根据事件类型添加特定字段
|
|
281
|
-
if (logData.event_type === 'error') {
|
|
282
|
-
this.addErrorFields(logData, data);
|
|
283
|
-
} else if (
|
|
284
|
-
logData.event_type === 'xhr' ||
|
|
285
|
-
logData.event_type === 'fetch'
|
|
286
|
-
) {
|
|
287
|
-
this.addApiFields(logData, data);
|
|
288
|
-
} else if (logData.event_type === 'click') {
|
|
289
|
-
this.addClickFields(logData, data);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// 添加 detail_json,仅保留 hash 信息
|
|
293
|
-
try {
|
|
294
|
-
let hash = '';
|
|
295
|
-
if (data && typeof data.hash === 'string') {
|
|
296
|
-
hash = data.hash;
|
|
297
|
-
} else if (
|
|
298
|
-
data &&
|
|
299
|
-
data.dimensions &&
|
|
300
|
-
typeof data.dimensions.hash === 'string'
|
|
301
|
-
) {
|
|
302
|
-
hash = data.dimensions.hash;
|
|
303
|
-
} else if (
|
|
304
|
-
typeof window !== 'undefined' &&
|
|
305
|
-
typeof window.location !== 'undefined'
|
|
306
|
-
) {
|
|
307
|
-
hash = window.location.hash || '';
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
logData.detail_json = JSON.stringify({ hash });
|
|
311
|
-
} catch (error) {
|
|
312
|
-
console.warn('Failed to serialize detail data:', error);
|
|
313
|
-
logData.detail_json = JSON.stringify({
|
|
314
|
-
error: 'Failed to serialize data'
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return logData;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
private addErrorFields(
|
|
322
|
-
logData: Record<string, any>,
|
|
323
|
-
data: Record<string, any>
|
|
324
|
-
): void {
|
|
325
|
-
if (data.message) {
|
|
326
|
-
logData.error_message = String(data.message);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (data.stack) {
|
|
330
|
-
logData.error_stack = String(data.stack);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (data.filename) {
|
|
334
|
-
logData.error_filename = data.filename;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (data.lineno) {
|
|
338
|
-
logData.error_lineno = String(data.lineno);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (data.colno) {
|
|
342
|
-
logData.error_colno = String(data.colno);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (data.name) {
|
|
346
|
-
logData.error_name = data.name;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
private addApiFields(
|
|
351
|
-
logData: Record<string, any>,
|
|
352
|
-
data: Record<string, any>
|
|
353
|
-
): void {
|
|
354
|
-
if (data.url) {
|
|
355
|
-
logData.api_url = data.url;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (data.method) {
|
|
359
|
-
logData.api_method = data.method;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (data.status !== undefined) {
|
|
363
|
-
logData.api_status = Number(data.status);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
if (data.duration !== undefined) {
|
|
367
|
-
logData.api_duration = Number(data.duration);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
if (data.responseSize !== undefined) {
|
|
371
|
-
logData.api_response_size = Number(data.responseSize);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
private addClickFields(
|
|
376
|
-
logData: Record<string, any>,
|
|
377
|
-
data: Record<string, any>
|
|
378
|
-
): void {
|
|
379
|
-
if (data.clickBizId || data.bizId) {
|
|
380
|
-
logData.click_biz_id = data.clickBizId || data.bizId;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (data.target) {
|
|
384
|
-
logData.click_target = data.target;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
if (data.selector) {
|
|
388
|
-
logData.click_selector = data.selector;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (data.text) {
|
|
392
|
-
logData.click_text = data.text;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
if (data.x !== undefined) {
|
|
396
|
-
logData.click_x = Number(data.x);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
if (data.y !== undefined) {
|
|
400
|
-
logData.click_y = Number(data.y);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
private filterSensitiveData(data: Record<string, any>): Record<string, any> {
|
|
405
|
-
const sensitivePatterns = [
|
|
406
|
-
/password/i,
|
|
407
|
-
/token/i,
|
|
408
|
-
/secret/i,
|
|
409
|
-
/key/i,
|
|
410
|
-
/auth/i,
|
|
411
|
-
/credential/i
|
|
412
|
-
];
|
|
413
|
-
|
|
414
|
-
const filtered: Record<string, any> = { ...data };
|
|
415
|
-
|
|
416
|
-
Object.keys(filtered).forEach((key) => {
|
|
417
|
-
const value = filtered[key];
|
|
418
|
-
if (typeof value === 'string') {
|
|
419
|
-
if (sensitivePatterns.some((pattern) => pattern.test(key))) {
|
|
420
|
-
filtered[key] = '[FILTERED]';
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
if (filtered[key].length > 500) {
|
|
424
|
-
filtered[key] = `${filtered[key].substring(0, 500)}...`;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
return filtered;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
private async handleSendError(data: any, error: Error): Promise<void> {
|
|
433
|
-
const retryItem = {
|
|
434
|
-
data,
|
|
435
|
-
error,
|
|
436
|
-
timestamp: Date.now(),
|
|
437
|
-
retryCount: 0
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
this.retryQueue.push(retryItem);
|
|
441
|
-
|
|
442
|
-
if (this.shouldRetry(error)) {
|
|
443
|
-
setTimeout(() => {
|
|
444
|
-
this.retryFailedLogs();
|
|
445
|
-
}, this.config.retryInterval);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
private async retryFailedLogs(): Promise<void> {
|
|
450
|
-
if (this.retryQueue.length === 0) {
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
const itemsToRetry = this.retryQueue.filter(
|
|
455
|
-
(item) => item.retryCount < this.config.retryCount
|
|
456
|
-
);
|
|
457
|
-
|
|
458
|
-
this.retryQueue = this.retryQueue.filter(
|
|
459
|
-
(item) => item.retryCount >= this.config.retryCount
|
|
460
|
-
);
|
|
461
|
-
|
|
462
|
-
for (const item of itemsToRetry) {
|
|
463
|
-
try {
|
|
464
|
-
item.retryCount++;
|
|
465
|
-
await this.sendLog(item.data);
|
|
466
|
-
|
|
467
|
-
const index = this.retryQueue.indexOf(item);
|
|
468
|
-
if (index > -1) {
|
|
469
|
-
this.retryQueue.splice(index, 1);
|
|
470
|
-
}
|
|
471
|
-
} catch (error) {
|
|
472
|
-
console.warn(
|
|
473
|
-
`Retry failed for log (attempt ${item.retryCount}):`,
|
|
474
|
-
error
|
|
475
|
-
);
|
|
476
|
-
|
|
477
|
-
if (item.retryCount < this.config.retryCount) {
|
|
478
|
-
setTimeout(() => {
|
|
479
|
-
this.retryFailedLogs();
|
|
480
|
-
}, this.config.retryInterval * item.retryCount);
|
|
481
|
-
} else {
|
|
482
|
-
console.error('Max retry attempts reached, dropping log:', item.data);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
private shouldRetry(error: Error): boolean {
|
|
489
|
-
const retryableErrors = [
|
|
490
|
-
'Network timeout',
|
|
491
|
-
'Connection failed',
|
|
492
|
-
'Service unavailable',
|
|
493
|
-
'Rate limit exceeded'
|
|
494
|
-
];
|
|
495
|
-
|
|
496
|
-
return retryableErrors.some(
|
|
497
|
-
(pattern) => (error.message && error.message.includes(pattern))
|
|
498
|
-
);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
private handleError(error: Error): void {
|
|
502
|
-
console.error('SLSWebTrackingAdapter Error:', error);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
private checkReady(): boolean {
|
|
506
|
-
if (!this.config.enabled) {
|
|
507
|
-
return false;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
if (!this.isInitialized) {
|
|
511
|
-
console.warn('SLSWebTrackingAdapter not initialized');
|
|
512
|
-
return false;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
if (!this.slsTracker) {
|
|
516
|
-
console.warn('SLS Tracker not available');
|
|
517
|
-
return false;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
return true;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
private generateSessionId(): string {
|
|
524
|
-
if (typeof sessionStorage !== 'undefined') {
|
|
525
|
-
let sessionId = sessionStorage.getItem('sls_session_id');
|
|
526
|
-
if (!sessionId) {
|
|
527
|
-
sessionId = `session_${Date.now()}_${Math.random()
|
|
528
|
-
.toString(36)
|
|
529
|
-
.substring(2, 9)}`;
|
|
530
|
-
sessionStorage.setItem('sls_session_id', sessionId);
|
|
531
|
-
}
|
|
532
|
-
return sessionId;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return `session_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
handleBeforeSend(logData: any): boolean | Record<string, any> {
|
|
539
|
-
try {
|
|
540
|
-
const dataSize = JSON.stringify(logData).length;
|
|
541
|
-
const maxSize = 1024 * 1024; // 1MB
|
|
542
|
-
|
|
543
|
-
if (dataSize > maxSize) {
|
|
544
|
-
console.warn('Log data too large, skipping:', dataSize);
|
|
545
|
-
return false;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
const filteredData = this.filterSensitiveData(logData);
|
|
549
|
-
|
|
550
|
-
if (this.config.debug) {
|
|
551
|
-
console.log('Log before send:', filteredData);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
return filteredData;
|
|
555
|
-
} catch (error) {
|
|
556
|
-
console.error('Error in beforeSend handler:', error);
|
|
557
|
-
return false;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
setUserId(userId: string): void {
|
|
562
|
-
this.config.userId = userId;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
updateConfig(newConfig: Partial<SLSAdapterConfig>): void {
|
|
566
|
-
this.config = { ...this.config, ...newConfig };
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
getConfig(): SLSAdapterConfig {
|
|
570
|
-
return { ...this.config };
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
getStats(): {
|
|
574
|
-
isInitialized: boolean;
|
|
575
|
-
isDestroyed: boolean;
|
|
576
|
-
pendingLogsCount: number;
|
|
577
|
-
retryQueueCount: number;
|
|
578
|
-
config: {
|
|
579
|
-
project: string | undefined;
|
|
580
|
-
logstore: string | undefined;
|
|
581
|
-
enabled: boolean | undefined;
|
|
582
|
-
};
|
|
583
|
-
} {
|
|
584
|
-
return {
|
|
585
|
-
isInitialized: this.isInitialized,
|
|
586
|
-
isDestroyed: this.isDestroyed,
|
|
587
|
-
pendingLogsCount: this.pendingLogs.length,
|
|
588
|
-
retryQueueCount: this.retryQueue.length,
|
|
589
|
-
config: {
|
|
590
|
-
project: this.config.project,
|
|
591
|
-
logstore: this.config.logstore,
|
|
592
|
-
enabled: this.config.enabled
|
|
593
|
-
}
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
destroy(): void {
|
|
598
|
-
if (this.isDestroyed) {
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
try {
|
|
603
|
-
if (this.retryQueue.length > 0 && this.config.debug) {
|
|
604
|
-
console.warn(
|
|
605
|
-
`Destroying adapter with ${this.retryQueue.length} items in retry queue`
|
|
606
|
-
);
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
if (this.slsTracker && this.slsTracker.destroy) {
|
|
610
|
-
this.slsTracker.destroy();
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
this.isDestroyed = true;
|
|
614
|
-
this.isInitialized = false;
|
|
615
|
-
this.slsTracker = null;
|
|
616
|
-
this.pendingLogs = [];
|
|
617
|
-
this.retryQueue = [];
|
|
618
|
-
|
|
619
|
-
if (this.config.debug) {
|
|
620
|
-
console.log('SLSWebTrackingAdapter destroyed');
|
|
621
|
-
}
|
|
622
|
-
} catch (error) {
|
|
623
|
-
console.error('Error destroying SLSWebTrackingAdapter:', error);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
}
|