@echoteam/signoz-react 1.0.7 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +222 -7
- package/dist/index.d.ts +7 -0
- package/dist/index.esm.js +297 -7
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +297 -7
- package/dist/index.js.map +1 -1
- package/dist/types/tracing.d.ts +7 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15283,17 +15283,13 @@ function getConfigValue(key) {
|
|
|
15283
15283
|
}
|
|
15284
15284
|
// Fungsi untuk memvalidasi konfigurasi
|
|
15285
15285
|
function validateConfig(config) {
|
|
15286
|
-
const requiredFields = ['serviceName', 'serviceVersion', 'environment', 'serviceNamespace', 'url'
|
|
15286
|
+
const requiredFields = ['serviceName', 'serviceVersion', 'environment', 'serviceNamespace', 'url'];
|
|
15287
15287
|
const missingFields = [];
|
|
15288
15288
|
for (const field of requiredFields) {
|
|
15289
15289
|
if (!config[field]) {
|
|
15290
15290
|
missingFields.push(field);
|
|
15291
15291
|
}
|
|
15292
15292
|
}
|
|
15293
|
-
// Khusus validasi allowedOrigins: pastikan array tidak kosong
|
|
15294
|
-
if (config.allowedOrigins && config.allowedOrigins.length === 0) {
|
|
15295
|
-
missingFields.push('allowedOrigins tidak boleh kosong demi keamanan CORS');
|
|
15296
|
-
}
|
|
15297
15293
|
return {
|
|
15298
15294
|
isValid: missingFields.length === 0,
|
|
15299
15295
|
missingFields
|
|
@@ -15317,6 +15313,255 @@ function parseAllowedOrigins(originsStr) {
|
|
|
15317
15313
|
return origin;
|
|
15318
15314
|
});
|
|
15319
15315
|
}
|
|
15316
|
+
// Fungsi helper untuk truncate body jika terlalu besar
|
|
15317
|
+
function truncateBody(body, maxSize) {
|
|
15318
|
+
try {
|
|
15319
|
+
const bodyStr = typeof body === 'string' ? body : JSON.stringify(body);
|
|
15320
|
+
if (bodyStr.length > maxSize) {
|
|
15321
|
+
return bodyStr.substring(0, maxSize) + '... [truncated]';
|
|
15322
|
+
}
|
|
15323
|
+
return bodyStr;
|
|
15324
|
+
}
|
|
15325
|
+
catch (e) {
|
|
15326
|
+
return '[Unable to serialize body]';
|
|
15327
|
+
}
|
|
15328
|
+
}
|
|
15329
|
+
// Fungsi untuk menambahkan logging ke fetch instrumentation
|
|
15330
|
+
function addFetchLogging(config) {
|
|
15331
|
+
if (!config.enableRequestLogging)
|
|
15332
|
+
return;
|
|
15333
|
+
const originalFetch = window.fetch;
|
|
15334
|
+
window.fetch = async function (...args) {
|
|
15335
|
+
const [resource, init] = args;
|
|
15336
|
+
const url = typeof resource === 'string' ? resource : (resource instanceof Request ? resource.url : resource.toString());
|
|
15337
|
+
const method = (init === null || init === void 0 ? void 0 : init.method) || 'GET';
|
|
15338
|
+
// Capture current page info
|
|
15339
|
+
const pageUrl = window.location.href;
|
|
15340
|
+
const pagePath = window.location.pathname;
|
|
15341
|
+
const tracer = trace.getTracer('fetch-logger');
|
|
15342
|
+
const span = tracer.startSpan(`HTTP ${method} ${url}`);
|
|
15343
|
+
try {
|
|
15344
|
+
// Log request data
|
|
15345
|
+
span.setAttribute('http.url', url);
|
|
15346
|
+
span.setAttribute('http.method', method);
|
|
15347
|
+
// Log page info (frontend URL)
|
|
15348
|
+
span.setAttribute('page.url', pageUrl);
|
|
15349
|
+
span.setAttribute('page.pathname', pagePath);
|
|
15350
|
+
span.setAttribute('page.search', window.location.search);
|
|
15351
|
+
span.setAttribute('page.hash', window.location.hash);
|
|
15352
|
+
if (config.logRequestBody && (init === null || init === void 0 ? void 0 : init.body) && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
|
|
15353
|
+
const bodyStr = truncateBody(init.body, config.maxBodyLogSize);
|
|
15354
|
+
span.setAttribute('http.request.body', bodyStr);
|
|
15355
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath}:`, bodyStr);
|
|
15356
|
+
}
|
|
15357
|
+
const response = await originalFetch.apply(this, args);
|
|
15358
|
+
// Log response data
|
|
15359
|
+
span.setAttribute('http.status_code', response.status);
|
|
15360
|
+
if (config.logResponseBody && response.ok) {
|
|
15361
|
+
const clonedResponse = response.clone();
|
|
15362
|
+
try {
|
|
15363
|
+
const responseData = await clonedResponse.text();
|
|
15364
|
+
const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
|
|
15365
|
+
span.setAttribute('http.response.body', truncatedData);
|
|
15366
|
+
console.log(`[SignOz] ${method} Response from ${url} (${response.status}) on page ${pagePath}:`, truncatedData);
|
|
15367
|
+
}
|
|
15368
|
+
catch (e) {
|
|
15369
|
+
console.warn('[SignOz] Failed to read response body:', e);
|
|
15370
|
+
}
|
|
15371
|
+
}
|
|
15372
|
+
else if (!response.ok) {
|
|
15373
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${response.status}`);
|
|
15374
|
+
}
|
|
15375
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
15376
|
+
return response;
|
|
15377
|
+
}
|
|
15378
|
+
catch (error) {
|
|
15379
|
+
span.recordException(error);
|
|
15380
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
15381
|
+
console.error(`[SignOz] ${method} Error for ${url} on page ${pagePath}:`, error);
|
|
15382
|
+
throw error;
|
|
15383
|
+
}
|
|
15384
|
+
finally {
|
|
15385
|
+
span.end();
|
|
15386
|
+
}
|
|
15387
|
+
};
|
|
15388
|
+
}
|
|
15389
|
+
// Fungsi untuk menambahkan logging ke XMLHttpRequest instrumentation
|
|
15390
|
+
function addXHRLogging(config) {
|
|
15391
|
+
if (!config.enableRequestLogging)
|
|
15392
|
+
return;
|
|
15393
|
+
const OriginalXHR = window.XMLHttpRequest;
|
|
15394
|
+
window.XMLHttpRequest = function () {
|
|
15395
|
+
const xhr = new OriginalXHR();
|
|
15396
|
+
let method = '';
|
|
15397
|
+
let url = '';
|
|
15398
|
+
// Capture current page info when XHR is created
|
|
15399
|
+
const pageUrl = window.location.href;
|
|
15400
|
+
const pagePath = window.location.pathname;
|
|
15401
|
+
const originalOpen = xhr.open;
|
|
15402
|
+
xhr.open = function (...args) {
|
|
15403
|
+
method = args[0];
|
|
15404
|
+
url = args[1];
|
|
15405
|
+
return originalOpen.apply(this, args);
|
|
15406
|
+
};
|
|
15407
|
+
const originalSend = xhr.send;
|
|
15408
|
+
xhr.send = function (body) {
|
|
15409
|
+
const tracer = trace.getTracer('xhr-logger');
|
|
15410
|
+
const span = tracer.startSpan(`HTTP ${method} ${url}`);
|
|
15411
|
+
span.setAttribute('http.url', url);
|
|
15412
|
+
span.setAttribute('http.method', method);
|
|
15413
|
+
// Log page info (frontend URL)
|
|
15414
|
+
span.setAttribute('page.url', pageUrl);
|
|
15415
|
+
span.setAttribute('page.pathname', pagePath);
|
|
15416
|
+
span.setAttribute('page.search', window.location.search);
|
|
15417
|
+
span.setAttribute('page.hash', window.location.hash);
|
|
15418
|
+
// Log request body
|
|
15419
|
+
if (config.logRequestBody && body && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
|
|
15420
|
+
const bodyStr = truncateBody(body, config.maxBodyLogSize);
|
|
15421
|
+
span.setAttribute('http.request.body', bodyStr);
|
|
15422
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath}:`, bodyStr);
|
|
15423
|
+
}
|
|
15424
|
+
this.addEventListener('load', function () {
|
|
15425
|
+
span.setAttribute('http.status_code', xhr.status);
|
|
15426
|
+
// Log response body
|
|
15427
|
+
if (config.logResponseBody && xhr.status >= 200 && xhr.status < 300) {
|
|
15428
|
+
const responseData = xhr.responseText;
|
|
15429
|
+
const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
|
|
15430
|
+
span.setAttribute('http.response.body', truncatedData);
|
|
15431
|
+
console.log(`[SignOz] ${method} Response from ${url} (${xhr.status}) on page ${pagePath}:`, truncatedData);
|
|
15432
|
+
}
|
|
15433
|
+
else if (xhr.status >= 300) {
|
|
15434
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${xhr.status}`);
|
|
15435
|
+
}
|
|
15436
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
15437
|
+
span.end();
|
|
15438
|
+
});
|
|
15439
|
+
this.addEventListener('error', function () {
|
|
15440
|
+
span.recordException(new Error('XHR request failed'));
|
|
15441
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: 'XHR request failed' });
|
|
15442
|
+
console.error(`[SignOz] ${method} Error for ${url} on page ${pagePath}`);
|
|
15443
|
+
span.end();
|
|
15444
|
+
});
|
|
15445
|
+
return originalSend.call(this, body);
|
|
15446
|
+
};
|
|
15447
|
+
return xhr;
|
|
15448
|
+
};
|
|
15449
|
+
}
|
|
15450
|
+
// Fungsi untuk menambahkan error tracking
|
|
15451
|
+
function addErrorTracking() {
|
|
15452
|
+
// Track unhandled errors
|
|
15453
|
+
window.addEventListener('error', (event) => {
|
|
15454
|
+
var _a;
|
|
15455
|
+
const tracer = trace.getTracer('error-tracker');
|
|
15456
|
+
const span = tracer.startSpan('Unhandled Error');
|
|
15457
|
+
span.setAttribute('error.type', 'unhandled');
|
|
15458
|
+
span.setAttribute('error.message', event.message);
|
|
15459
|
+
span.setAttribute('error.filename', event.filename || 'unknown');
|
|
15460
|
+
span.setAttribute('error.lineno', event.lineno || 0);
|
|
15461
|
+
span.setAttribute('error.colno', event.colno || 0);
|
|
15462
|
+
if (event.error) {
|
|
15463
|
+
span.recordException(event.error);
|
|
15464
|
+
span.setAttribute('error.stack', event.error.stack || '');
|
|
15465
|
+
}
|
|
15466
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: event.message });
|
|
15467
|
+
console.error('[SignOz] Unhandled Error:', {
|
|
15468
|
+
message: event.message,
|
|
15469
|
+
filename: event.filename,
|
|
15470
|
+
lineno: event.lineno,
|
|
15471
|
+
colno: event.colno,
|
|
15472
|
+
stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack
|
|
15473
|
+
});
|
|
15474
|
+
span.end();
|
|
15475
|
+
});
|
|
15476
|
+
// Track unhandled promise rejections
|
|
15477
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
15478
|
+
const tracer = trace.getTracer('error-tracker');
|
|
15479
|
+
const span = tracer.startSpan('Unhandled Promise Rejection');
|
|
15480
|
+
span.setAttribute('error.type', 'unhandled_rejection');
|
|
15481
|
+
span.setAttribute('error.reason', String(event.reason));
|
|
15482
|
+
if (event.reason instanceof Error) {
|
|
15483
|
+
span.recordException(event.reason);
|
|
15484
|
+
span.setAttribute('error.message', event.reason.message);
|
|
15485
|
+
span.setAttribute('error.stack', event.reason.stack || '');
|
|
15486
|
+
}
|
|
15487
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(event.reason) });
|
|
15488
|
+
console.error('[SignOz] Unhandled Promise Rejection:', event.reason);
|
|
15489
|
+
span.end();
|
|
15490
|
+
});
|
|
15491
|
+
}
|
|
15492
|
+
// Fungsi untuk menambahkan navigation tracking
|
|
15493
|
+
function addNavigationTracking() {
|
|
15494
|
+
let previousUrl = window.location.href;
|
|
15495
|
+
// Track initial page load
|
|
15496
|
+
const tracer = trace.getTracer('navigation-tracker');
|
|
15497
|
+
const initialSpan = tracer.startSpan('Page Load');
|
|
15498
|
+
initialSpan.setAttribute('navigation.type', 'initial');
|
|
15499
|
+
initialSpan.setAttribute('navigation.url', window.location.href);
|
|
15500
|
+
initialSpan.setAttribute('navigation.pathname', window.location.pathname);
|
|
15501
|
+
initialSpan.setAttribute('navigation.search', window.location.search);
|
|
15502
|
+
initialSpan.setAttribute('navigation.hash', window.location.hash);
|
|
15503
|
+
console.log('[SignOz] Page Load:', {
|
|
15504
|
+
url: window.location.href,
|
|
15505
|
+
pathname: window.location.pathname
|
|
15506
|
+
});
|
|
15507
|
+
initialSpan.end();
|
|
15508
|
+
// Track popstate (browser back/forward)
|
|
15509
|
+
window.addEventListener('popstate', () => {
|
|
15510
|
+
const span = tracer.startSpan('Navigation');
|
|
15511
|
+
span.setAttribute('navigation.type', 'popstate');
|
|
15512
|
+
span.setAttribute('navigation.from', previousUrl);
|
|
15513
|
+
span.setAttribute('navigation.to', window.location.href);
|
|
15514
|
+
span.setAttribute('navigation.pathname', window.location.pathname);
|
|
15515
|
+
span.setAttribute('navigation.search', window.location.search);
|
|
15516
|
+
span.setAttribute('navigation.hash', window.location.hash);
|
|
15517
|
+
console.log('[SignOz] Navigation (popstate):', {
|
|
15518
|
+
from: previousUrl,
|
|
15519
|
+
to: window.location.href,
|
|
15520
|
+
pathname: window.location.pathname
|
|
15521
|
+
});
|
|
15522
|
+
previousUrl = window.location.href;
|
|
15523
|
+
span.end();
|
|
15524
|
+
});
|
|
15525
|
+
// Track pushState and replaceState (SPA navigation)
|
|
15526
|
+
const originalPushState = history.pushState;
|
|
15527
|
+
history.pushState = function (...args) {
|
|
15528
|
+
const span = tracer.startSpan('Navigation');
|
|
15529
|
+
span.setAttribute('navigation.type', 'pushState');
|
|
15530
|
+
span.setAttribute('navigation.from', previousUrl);
|
|
15531
|
+
const result = originalPushState.apply(this, args);
|
|
15532
|
+
span.setAttribute('navigation.to', window.location.href);
|
|
15533
|
+
span.setAttribute('navigation.pathname', window.location.pathname);
|
|
15534
|
+
span.setAttribute('navigation.search', window.location.search);
|
|
15535
|
+
span.setAttribute('navigation.hash', window.location.hash);
|
|
15536
|
+
console.log('[SignOz] Navigation (pushState):', {
|
|
15537
|
+
from: previousUrl,
|
|
15538
|
+
to: window.location.href,
|
|
15539
|
+
pathname: window.location.pathname
|
|
15540
|
+
});
|
|
15541
|
+
previousUrl = window.location.href;
|
|
15542
|
+
span.end();
|
|
15543
|
+
return result;
|
|
15544
|
+
};
|
|
15545
|
+
const originalReplaceState = history.replaceState;
|
|
15546
|
+
history.replaceState = function (...args) {
|
|
15547
|
+
const span = tracer.startSpan('Navigation');
|
|
15548
|
+
span.setAttribute('navigation.type', 'replaceState');
|
|
15549
|
+
span.setAttribute('navigation.from', previousUrl);
|
|
15550
|
+
const result = originalReplaceState.apply(this, args);
|
|
15551
|
+
span.setAttribute('navigation.to', window.location.href);
|
|
15552
|
+
span.setAttribute('navigation.pathname', window.location.pathname);
|
|
15553
|
+
span.setAttribute('navigation.search', window.location.search);
|
|
15554
|
+
span.setAttribute('navigation.hash', window.location.hash);
|
|
15555
|
+
console.log('[SignOz] Navigation (replaceState):', {
|
|
15556
|
+
from: previousUrl,
|
|
15557
|
+
to: window.location.href,
|
|
15558
|
+
pathname: window.location.pathname
|
|
15559
|
+
});
|
|
15560
|
+
previousUrl = window.location.href;
|
|
15561
|
+
span.end();
|
|
15562
|
+
return result;
|
|
15563
|
+
};
|
|
15564
|
+
}
|
|
15320
15565
|
/**
|
|
15321
15566
|
* Inisialisasi SignOz tracing untuk aplikasi React
|
|
15322
15567
|
* @param config - Konfigurasi SignOz (opsional, akan menggunakan environment variables jika tidak disediakan)
|
|
@@ -15340,7 +15585,14 @@ function initializeSignOzTracing(config) {
|
|
|
15340
15585
|
scheduledDelayMillis: 5000,
|
|
15341
15586
|
exportTimeoutMillis: 30000
|
|
15342
15587
|
},
|
|
15343
|
-
allowedOrigins: (config === null || config === void 0 ? void 0 : config.allowedOrigins) || parseAllowedOrigins(getConfigValue('REACT_APP_SIGNOZ_ALLOWED_ORIGINS'))
|
|
15588
|
+
allowedOrigins: (config === null || config === void 0 ? void 0 : config.allowedOrigins) || parseAllowedOrigins(getConfigValue('REACT_APP_SIGNOZ_ALLOWED_ORIGINS')),
|
|
15589
|
+
enableRequestLogging: (config === null || config === void 0 ? void 0 : config.enableRequestLogging) !== undefined ? config.enableRequestLogging : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_REQUEST_LOGGING') === 'true' || true),
|
|
15590
|
+
logRequestBody: (config === null || config === void 0 ? void 0 : config.logRequestBody) !== undefined ? config.logRequestBody : (getConfigValue('REACT_APP_SIGNOZ_LOG_REQUEST_BODY') === 'true' || true),
|
|
15591
|
+
logResponseBody: (config === null || config === void 0 ? void 0 : config.logResponseBody) !== undefined ? config.logResponseBody : (getConfigValue('REACT_APP_SIGNOZ_LOG_RESPONSE_BODY') === 'true' || true),
|
|
15592
|
+
maxBodyLogSize: (config === null || config === void 0 ? void 0 : config.maxBodyLogSize) || parseInt(getConfigValue('REACT_APP_SIGNOZ_MAX_BODY_LOG_SIZE') || '10000') || 10000,
|
|
15593
|
+
enableDocumentLoad: (config === null || config === void 0 ? void 0 : config.enableDocumentLoad) !== undefined ? config.enableDocumentLoad : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD') !== 'false'),
|
|
15594
|
+
enableErrorTracking: (config === null || config === void 0 ? void 0 : config.enableErrorTracking) !== undefined ? config.enableErrorTracking : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_ERROR_TRACKING') !== 'false'),
|
|
15595
|
+
enableNavigationTracking: (config === null || config === void 0 ? void 0 : config.enableNavigationTracking) !== undefined ? config.enableNavigationTracking : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING') !== 'false')
|
|
15344
15596
|
};
|
|
15345
15597
|
// Validasi konfigurasi
|
|
15346
15598
|
const { isValid, missingFields } = validateConfig(effectiveConfig);
|
|
@@ -15390,14 +15642,52 @@ function initializeSignOzTracing(config) {
|
|
|
15390
15642
|
'@opentelemetry/instrumentation-fetch': {
|
|
15391
15643
|
propagateTraceHeaderCorsUrls: effectiveConfig.allowedOrigins,
|
|
15392
15644
|
},
|
|
15645
|
+
// Nonaktifkan user interaction instrumentation (click events)
|
|
15646
|
+
'@opentelemetry/instrumentation-user-interaction': {
|
|
15647
|
+
enabled: false,
|
|
15648
|
+
},
|
|
15649
|
+
// Document load instrumentation untuk page load performance
|
|
15650
|
+
'@opentelemetry/instrumentation-document-load': {
|
|
15651
|
+
enabled: effectiveConfig.enableDocumentLoad,
|
|
15652
|
+
},
|
|
15393
15653
|
}),
|
|
15394
15654
|
],
|
|
15395
15655
|
});
|
|
15656
|
+
// Tambahkan custom logging untuk request/response
|
|
15657
|
+
if (effectiveConfig.enableRequestLogging) {
|
|
15658
|
+
addFetchLogging({
|
|
15659
|
+
enableRequestLogging: effectiveConfig.enableRequestLogging,
|
|
15660
|
+
logRequestBody: effectiveConfig.logRequestBody,
|
|
15661
|
+
logResponseBody: effectiveConfig.logResponseBody,
|
|
15662
|
+
maxBodyLogSize: effectiveConfig.maxBodyLogSize
|
|
15663
|
+
});
|
|
15664
|
+
addXHRLogging({
|
|
15665
|
+
enableRequestLogging: effectiveConfig.enableRequestLogging,
|
|
15666
|
+
logRequestBody: effectiveConfig.logRequestBody,
|
|
15667
|
+
logResponseBody: effectiveConfig.logResponseBody,
|
|
15668
|
+
maxBodyLogSize: effectiveConfig.maxBodyLogSize
|
|
15669
|
+
});
|
|
15670
|
+
}
|
|
15671
|
+
// Tambahkan error tracking
|
|
15672
|
+
if (effectiveConfig.enableErrorTracking) {
|
|
15673
|
+
addErrorTracking();
|
|
15674
|
+
}
|
|
15675
|
+
// Tambahkan navigation tracking
|
|
15676
|
+
if (effectiveConfig.enableNavigationTracking) {
|
|
15677
|
+
addNavigationTracking();
|
|
15678
|
+
}
|
|
15396
15679
|
console.log('SignOz: Konfigurasi tracing:', {
|
|
15397
15680
|
serviceName: effectiveConfig.serviceName,
|
|
15398
15681
|
environment: effectiveConfig.environment,
|
|
15399
15682
|
allowedOrigins: effectiveConfig.allowedOrigins,
|
|
15400
|
-
traceSampleRate: effectiveConfig.traceSampleRate
|
|
15683
|
+
traceSampleRate: effectiveConfig.traceSampleRate,
|
|
15684
|
+
enableRequestLogging: effectiveConfig.enableRequestLogging,
|
|
15685
|
+
logRequestBody: effectiveConfig.logRequestBody,
|
|
15686
|
+
logResponseBody: effectiveConfig.logResponseBody,
|
|
15687
|
+
maxBodyLogSize: effectiveConfig.maxBodyLogSize,
|
|
15688
|
+
enableDocumentLoad: effectiveConfig.enableDocumentLoad,
|
|
15689
|
+
enableErrorTracking: effectiveConfig.enableErrorTracking,
|
|
15690
|
+
enableNavigationTracking: effectiveConfig.enableNavigationTracking
|
|
15401
15691
|
});
|
|
15402
15692
|
console.log('SignOz: Tracing berhasil diinisialisasi');
|
|
15403
15693
|
}
|