@echoteam/signoz-react 1.2.1 → 1.2.3
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 +90 -9
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +291 -49
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +291 -49
- package/dist/index.js.map +1 -1
- package/dist/types/tracing.d.ts +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,12 @@ Library React untuk monitoring dan tracing aplikasi menggunakan OpenTelemetry da
|
|
|
24
24
|
- First Paint, First Contentful Paint
|
|
25
25
|
- DOM Content Loaded, Load Complete
|
|
26
26
|
- Resource timing
|
|
27
|
+
- **WebSocket Logging**: Otomatis track WebSocket connections dan messages
|
|
28
|
+
- Track connection open, close, error
|
|
29
|
+
- Log messages sent dan received
|
|
30
|
+
- Extract message type dan text dari JSON
|
|
31
|
+
- Connection duration tracking
|
|
32
|
+
- Data tersimpan di SignOz span attributes
|
|
27
33
|
- **No Click Tracking**: User interaction (click events) tidak di-track untuk privacy dan performa
|
|
28
34
|
- **Error Boundary**: Komponen React untuk menangkap dan melaporkan error dengan tracing
|
|
29
35
|
- **Error Page**: Halaman error untuk React Router dengan integrasi tracing
|
|
@@ -66,10 +72,17 @@ REACT_APP_SIGNOZ_LOG_REQUEST_BODY=true
|
|
|
66
72
|
REACT_APP_SIGNOZ_LOG_RESPONSE_BODY=true
|
|
67
73
|
REACT_APP_SIGNOZ_MAX_BODY_LOG_SIZE=10000
|
|
68
74
|
|
|
69
|
-
# Konfigurasi Tracking (opsional
|
|
70
|
-
REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD=
|
|
71
|
-
REACT_APP_SIGNOZ_ENABLE_ERROR_TRACKING=true
|
|
72
|
-
REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING=
|
|
75
|
+
# Konfigurasi Tracking (opsional)
|
|
76
|
+
REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD=false # default: false
|
|
77
|
+
REACT_APP_SIGNOZ_ENABLE_ERROR_TRACKING=true # default: true
|
|
78
|
+
REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING=false # default: false
|
|
79
|
+
|
|
80
|
+
# WebSocket Logging (opsional, default: false)
|
|
81
|
+
REACT_APP_SIGNOZ_ENABLE_WEBSOCKET_LOGGING=false
|
|
82
|
+
REACT_APP_SIGNOZ_LOG_WEBSOCKET_MESSAGES=false
|
|
83
|
+
|
|
84
|
+
# Console Logging (opsional, default: false)
|
|
85
|
+
REACT_APP_SIGNOZ_ENABLE_CONSOLE_LOG=false
|
|
73
86
|
```
|
|
74
87
|
|
|
75
88
|
> **Catatan untuk REACT_APP_SIGNOZ_ALLOWED_ORIGINS:**
|
|
@@ -131,9 +144,14 @@ initializeSignOzTracing({
|
|
|
131
144
|
logResponseBody: true, // Log response body (default: true)
|
|
132
145
|
maxBodyLogSize: 10000, // Maksimal 10KB per log (default: 10000)
|
|
133
146
|
// Konfigurasi tracking
|
|
134
|
-
enableDocumentLoad:
|
|
147
|
+
enableDocumentLoad: false, // Track page load performance (default: false)
|
|
135
148
|
enableErrorTracking: true, // Track unhandled errors (default: true)
|
|
136
|
-
enableNavigationTracking:
|
|
149
|
+
enableNavigationTracking: false, // Track route changes (default: false)
|
|
150
|
+
// WebSocket logging (default: false)
|
|
151
|
+
enableWebSocketLogging: false, // Track WebSocket connections and messages
|
|
152
|
+
logWebSocketMessages: false, // Log WebSocket message content
|
|
153
|
+
// Console logging (default: false, hanya kirim ke SignOz tanpa console.log)
|
|
154
|
+
enableConsoleLog: false // Set true untuk enable console.log di browser
|
|
137
155
|
});
|
|
138
156
|
```
|
|
139
157
|
|
|
@@ -171,10 +189,12 @@ Library ini secara otomatis melog semua HTTP request dan response yang dilakukan
|
|
|
171
189
|
3. Pilih trace yang ingin dilihat
|
|
172
190
|
4. Lihat span attributes:
|
|
173
191
|
- `http.request.body`: Body dari request (untuk POST/PUT/PATCH)
|
|
174
|
-
- `
|
|
192
|
+
- `response.data`: Body dari response
|
|
193
|
+
- `response.message`: Message dari response JSON (jika ada field `message`)
|
|
175
194
|
- `http.url`: URL endpoint
|
|
176
195
|
- `http.method`: HTTP method
|
|
177
196
|
- `http.status_code`: Status code response
|
|
197
|
+
- `duration_ms`: Durasi request dalam milliseconds
|
|
178
198
|
- `page.url`: URL halaman frontend yang melakukan request
|
|
179
199
|
- `page.pathname`: Pathname halaman frontend
|
|
180
200
|
- `page.search`: Query parameters halaman frontend
|
|
@@ -298,6 +318,64 @@ initializeSignOzTracing({
|
|
|
298
318
|
});
|
|
299
319
|
```
|
|
300
320
|
|
|
321
|
+
### WebSocket Logging
|
|
322
|
+
|
|
323
|
+
Library ini otomatis track semua WebSocket connections dan messages.
|
|
324
|
+
|
|
325
|
+
**Contoh Output di Console:**
|
|
326
|
+
```
|
|
327
|
+
[SignOz] WebSocket Connected to wss://api.example.com/ws from page /dashboard [45ms]
|
|
328
|
+
[SignOz] WebSocket Send to wss://api.example.com/ws from page /dashboard: {"type":"subscribe","channel":"updates"}
|
|
329
|
+
[SignOz] WebSocket Receive from wss://api.example.com/ws on page /dashboard: {"type":"message","data":"Hello"}
|
|
330
|
+
[SignOz] WebSocket Closed wss://api.example.com/ws on page /dashboard - Code: 1000, Reason: Normal closure, Clean: true
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Data yang Di-track:**
|
|
334
|
+
- WebSocket connection (open, close, error)
|
|
335
|
+
- Connection duration
|
|
336
|
+
- Messages sent (dengan content)
|
|
337
|
+
- Messages received (dengan content)
|
|
338
|
+
- Close code dan reason
|
|
339
|
+
- URL halaman frontend yang membuat connection
|
|
340
|
+
- Message type (jika ada field `type` atau `event` di JSON)
|
|
341
|
+
- Message text (jika ada field `message` di JSON)
|
|
342
|
+
|
|
343
|
+
**Melihat di SignOz:**
|
|
344
|
+
1. Navigasi ke **Traces**
|
|
345
|
+
2. Filter by span name: "WebSocket Connection", "WebSocket Send", "WebSocket Receive", "WebSocket Close", atau "WebSocket Error"
|
|
346
|
+
3. Lihat span attributes:
|
|
347
|
+
- `websocket.url`: URL WebSocket
|
|
348
|
+
- `websocket.protocols`: Protocols yang digunakan
|
|
349
|
+
- `websocket.state`: State connection (open, closed, error)
|
|
350
|
+
- `websocket.direction`: Arah message (send/receive)
|
|
351
|
+
- `websocket.message`: Content message
|
|
352
|
+
- `websocket.message.type`: Tipe message (jika ada)
|
|
353
|
+
- `websocket.message.text`: Text message (jika ada field `message`)
|
|
354
|
+
- `websocket.close.code`: Close code
|
|
355
|
+
- `websocket.close.reason`: Alasan close
|
|
356
|
+
- `websocket.close.wasClean`: Apakah close dengan clean
|
|
357
|
+
- `duration_ms`: Durasi connection
|
|
358
|
+
- `page.url`: URL halaman frontend
|
|
359
|
+
- `page.pathname`: Pathname halaman frontend
|
|
360
|
+
|
|
361
|
+
**Mengaktifkan WebSocket Logging:**
|
|
362
|
+
```typescript
|
|
363
|
+
// WebSocket logging disabled by default
|
|
364
|
+
// Untuk mengaktifkan:
|
|
365
|
+
initializeSignOzTracing({
|
|
366
|
+
// ... konfigurasi lainnya
|
|
367
|
+
enableWebSocketLogging: true,
|
|
368
|
+
logWebSocketMessages: true // Enable message logging
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Atau hanya track connection tanpa log messages
|
|
372
|
+
initializeSignOzTracing({
|
|
373
|
+
// ... konfigurasi lainnya
|
|
374
|
+
enableWebSocketLogging: true,
|
|
375
|
+
logWebSocketMessages: false // Hanya track connection, tidak log messages
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
301
379
|
### Error Boundary
|
|
302
380
|
|
|
303
381
|
#### Penggunaan Dasar
|
|
@@ -452,9 +530,12 @@ Inisialisasi SignOz tracing untuk aplikasi React.
|
|
|
452
530
|
- `logRequestBody` (opsional): Log request body untuk POST/PUT/PATCH (default: true)
|
|
453
531
|
- `logResponseBody` (opsional): Log response body untuk semua request (default: true)
|
|
454
532
|
- `maxBodyLogSize` (opsional): Maksimal ukuran body yang di-log dalam bytes (default: 10000)
|
|
455
|
-
- `enableDocumentLoad` (opsional): Aktifkan document load instrumentation (default:
|
|
533
|
+
- `enableDocumentLoad` (opsional): Aktifkan document load instrumentation (default: false)
|
|
456
534
|
- `enableErrorTracking` (opsional): Aktifkan automatic error tracking (default: true)
|
|
457
|
-
- `enableNavigationTracking` (opsional): Aktifkan navigation/route tracking (default:
|
|
535
|
+
- `enableNavigationTracking` (opsional): Aktifkan navigation/route tracking (default: false)
|
|
536
|
+
- `enableConsoleLog` (opsional): Aktifkan console.log output di browser (default: false)
|
|
537
|
+
- `enableWebSocketLogging` (opsional): Aktifkan WebSocket connection dan message tracking (default: false)
|
|
538
|
+
- `logWebSocketMessages` (opsional): Log WebSocket message content (default: false)
|
|
458
539
|
|
|
459
540
|
### `ErrorBoundary`
|
|
460
541
|
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,9 @@ interface SignOzConfig {
|
|
|
20
20
|
enableDocumentLoad?: boolean;
|
|
21
21
|
enableErrorTracking?: boolean;
|
|
22
22
|
enableNavigationTracking?: boolean;
|
|
23
|
+
enableConsoleLog?: boolean;
|
|
24
|
+
enableWebSocketLogging?: boolean;
|
|
25
|
+
logWebSocketMessages?: boolean;
|
|
23
26
|
}
|
|
24
27
|
declare global {
|
|
25
28
|
interface Window {
|
package/dist/index.esm.js
CHANGED
|
@@ -15318,6 +15318,8 @@ function addFetchLogging(config) {
|
|
|
15318
15318
|
// Capture current page info
|
|
15319
15319
|
const pageUrl = window.location.href;
|
|
15320
15320
|
const pagePath = window.location.pathname;
|
|
15321
|
+
// Track start time
|
|
15322
|
+
const startTime = performance.now();
|
|
15321
15323
|
const tracer = trace.getTracer('fetch-logger');
|
|
15322
15324
|
const span = tracer.startSpan(`HTTP ${method} ${url}`);
|
|
15323
15325
|
try {
|
|
@@ -15332,9 +15334,14 @@ function addFetchLogging(config) {
|
|
|
15332
15334
|
if (config.logRequestBody && (init === null || init === void 0 ? void 0 : init.body) && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
|
|
15333
15335
|
const bodyStr = truncateBody(init.body, config.maxBodyLogSize);
|
|
15334
15336
|
span.setAttribute('http.request.body', bodyStr);
|
|
15335
|
-
|
|
15337
|
+
if (config.enableConsoleLog) {
|
|
15338
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath}:`, bodyStr);
|
|
15339
|
+
}
|
|
15336
15340
|
}
|
|
15337
15341
|
const response = await originalFetch.apply(this, args);
|
|
15342
|
+
// Calculate duration
|
|
15343
|
+
const duration = performance.now() - startTime;
|
|
15344
|
+
span.setAttribute('duration_ms', Math.round(duration));
|
|
15338
15345
|
// Log response data
|
|
15339
15346
|
span.setAttribute('http.status_code', response.status);
|
|
15340
15347
|
if (config.logResponseBody && response.ok) {
|
|
@@ -15342,23 +15349,42 @@ function addFetchLogging(config) {
|
|
|
15342
15349
|
try {
|
|
15343
15350
|
const responseData = await clonedResponse.text();
|
|
15344
15351
|
const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
|
|
15345
|
-
span.setAttribute('
|
|
15346
|
-
|
|
15352
|
+
span.setAttribute('response.data', truncatedData);
|
|
15353
|
+
// Try to parse JSON and extract message if exists
|
|
15354
|
+
try {
|
|
15355
|
+
const jsonData = JSON.parse(responseData);
|
|
15356
|
+
if (jsonData.message) {
|
|
15357
|
+
span.setAttribute('response.message', jsonData.message);
|
|
15358
|
+
}
|
|
15359
|
+
}
|
|
15360
|
+
catch (e) {
|
|
15361
|
+
// Not JSON or no message field, ignore
|
|
15362
|
+
}
|
|
15363
|
+
if (config.enableConsoleLog) {
|
|
15364
|
+
console.log(`[SignOz] ${method} Response from ${url} (${response.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
|
|
15365
|
+
}
|
|
15347
15366
|
}
|
|
15348
15367
|
catch (e) {
|
|
15349
|
-
|
|
15368
|
+
if (config.enableConsoleLog) {
|
|
15369
|
+
console.warn('[SignOz] Failed to read response body:', e);
|
|
15370
|
+
}
|
|
15350
15371
|
}
|
|
15351
15372
|
}
|
|
15352
|
-
else if (!response.ok) {
|
|
15353
|
-
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${response.status}`);
|
|
15373
|
+
else if (!response.ok && config.enableConsoleLog) {
|
|
15374
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${response.status} [${Math.round(duration)}ms]`);
|
|
15354
15375
|
}
|
|
15355
15376
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
15356
15377
|
return response;
|
|
15357
15378
|
}
|
|
15358
15379
|
catch (error) {
|
|
15380
|
+
// Calculate duration even on error
|
|
15381
|
+
const duration = performance.now() - startTime;
|
|
15382
|
+
span.setAttribute('duration_ms', Math.round(duration));
|
|
15359
15383
|
span.recordException(error);
|
|
15360
15384
|
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
15361
|
-
|
|
15385
|
+
if (config.enableConsoleLog) {
|
|
15386
|
+
console.error(`[SignOz] ${method} Error for ${url} on page ${pagePath} [${Math.round(duration)}ms]:`, error);
|
|
15387
|
+
}
|
|
15362
15388
|
throw error;
|
|
15363
15389
|
}
|
|
15364
15390
|
finally {
|
|
@@ -15375,6 +15401,7 @@ function addXHRLogging(config) {
|
|
|
15375
15401
|
const xhr = new OriginalXHR();
|
|
15376
15402
|
let method = '';
|
|
15377
15403
|
let url = '';
|
|
15404
|
+
let startTime = 0;
|
|
15378
15405
|
// Capture current page info when XHR is created
|
|
15379
15406
|
const pageUrl = window.location.href;
|
|
15380
15407
|
const pagePath = window.location.pathname;
|
|
@@ -15386,6 +15413,8 @@ function addXHRLogging(config) {
|
|
|
15386
15413
|
};
|
|
15387
15414
|
const originalSend = xhr.send;
|
|
15388
15415
|
xhr.send = function (body) {
|
|
15416
|
+
// Track start time
|
|
15417
|
+
startTime = performance.now();
|
|
15389
15418
|
const tracer = trace.getTracer('xhr-logger');
|
|
15390
15419
|
const span = tracer.startSpan(`HTTP ${method} ${url}`);
|
|
15391
15420
|
span.setAttribute('http.url', url);
|
|
@@ -15399,27 +15428,49 @@ function addXHRLogging(config) {
|
|
|
15399
15428
|
if (config.logRequestBody && body && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
|
|
15400
15429
|
const bodyStr = truncateBody(body, config.maxBodyLogSize);
|
|
15401
15430
|
span.setAttribute('http.request.body', bodyStr);
|
|
15402
|
-
|
|
15431
|
+
if (config.enableConsoleLog) {
|
|
15432
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath}:`, bodyStr);
|
|
15433
|
+
}
|
|
15403
15434
|
}
|
|
15404
15435
|
this.addEventListener('load', function () {
|
|
15436
|
+
// Calculate duration
|
|
15437
|
+
const duration = performance.now() - startTime;
|
|
15438
|
+
span.setAttribute('duration_ms', Math.round(duration));
|
|
15405
15439
|
span.setAttribute('http.status_code', xhr.status);
|
|
15406
15440
|
// Log response body
|
|
15407
15441
|
if (config.logResponseBody && xhr.status >= 200 && xhr.status < 300) {
|
|
15408
15442
|
const responseData = xhr.responseText;
|
|
15409
15443
|
const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
|
|
15410
|
-
span.setAttribute('
|
|
15411
|
-
|
|
15444
|
+
span.setAttribute('response.data', truncatedData);
|
|
15445
|
+
// Try to parse JSON and extract message if exists
|
|
15446
|
+
try {
|
|
15447
|
+
const jsonData = JSON.parse(responseData);
|
|
15448
|
+
if (jsonData.message) {
|
|
15449
|
+
span.setAttribute('response.message', jsonData.message);
|
|
15450
|
+
}
|
|
15451
|
+
}
|
|
15452
|
+
catch (e) {
|
|
15453
|
+
// Not JSON or no message field, ignore
|
|
15454
|
+
}
|
|
15455
|
+
if (config.enableConsoleLog) {
|
|
15456
|
+
console.log(`[SignOz] ${method} Response from ${url} (${xhr.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
|
|
15457
|
+
}
|
|
15412
15458
|
}
|
|
15413
|
-
else if (xhr.status >= 300) {
|
|
15414
|
-
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${xhr.status}`);
|
|
15459
|
+
else if (xhr.status >= 300 && config.enableConsoleLog) {
|
|
15460
|
+
console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${xhr.status} [${Math.round(duration)}ms]`);
|
|
15415
15461
|
}
|
|
15416
15462
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
15417
15463
|
span.end();
|
|
15418
15464
|
});
|
|
15419
15465
|
this.addEventListener('error', function () {
|
|
15466
|
+
// Calculate duration even on error
|
|
15467
|
+
const duration = performance.now() - startTime;
|
|
15468
|
+
span.setAttribute('duration_ms', Math.round(duration));
|
|
15420
15469
|
span.recordException(new Error('XHR request failed'));
|
|
15421
15470
|
span.setStatus({ code: SpanStatusCode.ERROR, message: 'XHR request failed' });
|
|
15422
|
-
|
|
15471
|
+
if (config.enableConsoleLog) {
|
|
15472
|
+
console.error(`[SignOz] ${method} Error for ${url} on page ${pagePath} [${Math.round(duration)}ms]`);
|
|
15473
|
+
}
|
|
15423
15474
|
span.end();
|
|
15424
15475
|
});
|
|
15425
15476
|
return originalSend.call(this, body);
|
|
@@ -15428,7 +15479,7 @@ function addXHRLogging(config) {
|
|
|
15428
15479
|
};
|
|
15429
15480
|
}
|
|
15430
15481
|
// Fungsi untuk menambahkan error tracking
|
|
15431
|
-
function addErrorTracking() {
|
|
15482
|
+
function addErrorTracking(enableConsoleLog = false) {
|
|
15432
15483
|
// Track unhandled errors
|
|
15433
15484
|
window.addEventListener('error', (event) => {
|
|
15434
15485
|
var _a;
|
|
@@ -15444,13 +15495,15 @@ function addErrorTracking() {
|
|
|
15444
15495
|
span.setAttribute('error.stack', event.error.stack || '');
|
|
15445
15496
|
}
|
|
15446
15497
|
span.setStatus({ code: SpanStatusCode.ERROR, message: event.message });
|
|
15447
|
-
|
|
15448
|
-
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
|
|
15453
|
-
|
|
15498
|
+
if (enableConsoleLog) {
|
|
15499
|
+
console.error('[SignOz] Unhandled Error:', {
|
|
15500
|
+
message: event.message,
|
|
15501
|
+
filename: event.filename,
|
|
15502
|
+
lineno: event.lineno,
|
|
15503
|
+
colno: event.colno,
|
|
15504
|
+
stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack
|
|
15505
|
+
});
|
|
15506
|
+
}
|
|
15454
15507
|
span.end();
|
|
15455
15508
|
});
|
|
15456
15509
|
// Track unhandled promise rejections
|
|
@@ -15465,12 +15518,14 @@ function addErrorTracking() {
|
|
|
15465
15518
|
span.setAttribute('error.stack', event.reason.stack || '');
|
|
15466
15519
|
}
|
|
15467
15520
|
span.setStatus({ code: SpanStatusCode.ERROR, message: String(event.reason) });
|
|
15468
|
-
|
|
15521
|
+
if (enableConsoleLog) {
|
|
15522
|
+
console.error('[SignOz] Unhandled Promise Rejection:', event.reason);
|
|
15523
|
+
}
|
|
15469
15524
|
span.end();
|
|
15470
15525
|
});
|
|
15471
15526
|
}
|
|
15472
15527
|
// Fungsi untuk menambahkan navigation tracking
|
|
15473
|
-
function addNavigationTracking() {
|
|
15528
|
+
function addNavigationTracking(enableConsoleLog = false) {
|
|
15474
15529
|
let previousUrl = window.location.href;
|
|
15475
15530
|
// Track initial page load
|
|
15476
15531
|
const tracer = trace.getTracer('navigation-tracker');
|
|
@@ -15480,10 +15535,12 @@ function addNavigationTracking() {
|
|
|
15480
15535
|
initialSpan.setAttribute('navigation.pathname', window.location.pathname);
|
|
15481
15536
|
initialSpan.setAttribute('navigation.search', window.location.search);
|
|
15482
15537
|
initialSpan.setAttribute('navigation.hash', window.location.hash);
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15538
|
+
if (enableConsoleLog) {
|
|
15539
|
+
console.log('[SignOz] Page Load:', {
|
|
15540
|
+
url: window.location.href,
|
|
15541
|
+
pathname: window.location.pathname
|
|
15542
|
+
});
|
|
15543
|
+
}
|
|
15487
15544
|
initialSpan.end();
|
|
15488
15545
|
// Track popstate (browser back/forward)
|
|
15489
15546
|
window.addEventListener('popstate', () => {
|
|
@@ -15494,11 +15551,13 @@ function addNavigationTracking() {
|
|
|
15494
15551
|
span.setAttribute('navigation.pathname', window.location.pathname);
|
|
15495
15552
|
span.setAttribute('navigation.search', window.location.search);
|
|
15496
15553
|
span.setAttribute('navigation.hash', window.location.hash);
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
|
|
15501
|
-
|
|
15554
|
+
if (enableConsoleLog) {
|
|
15555
|
+
console.log('[SignOz] Navigation (popstate):', {
|
|
15556
|
+
from: previousUrl,
|
|
15557
|
+
to: window.location.href,
|
|
15558
|
+
pathname: window.location.pathname
|
|
15559
|
+
});
|
|
15560
|
+
}
|
|
15502
15561
|
previousUrl = window.location.href;
|
|
15503
15562
|
span.end();
|
|
15504
15563
|
});
|
|
@@ -15513,11 +15572,13 @@ function addNavigationTracking() {
|
|
|
15513
15572
|
span.setAttribute('navigation.pathname', window.location.pathname);
|
|
15514
15573
|
span.setAttribute('navigation.search', window.location.search);
|
|
15515
15574
|
span.setAttribute('navigation.hash', window.location.hash);
|
|
15516
|
-
|
|
15517
|
-
|
|
15518
|
-
|
|
15519
|
-
|
|
15520
|
-
|
|
15575
|
+
if (enableConsoleLog) {
|
|
15576
|
+
console.log('[SignOz] Navigation (pushState):', {
|
|
15577
|
+
from: previousUrl,
|
|
15578
|
+
to: window.location.href,
|
|
15579
|
+
pathname: window.location.pathname
|
|
15580
|
+
});
|
|
15581
|
+
}
|
|
15521
15582
|
previousUrl = window.location.href;
|
|
15522
15583
|
span.end();
|
|
15523
15584
|
return result;
|
|
@@ -15532,16 +15593,181 @@ function addNavigationTracking() {
|
|
|
15532
15593
|
span.setAttribute('navigation.pathname', window.location.pathname);
|
|
15533
15594
|
span.setAttribute('navigation.search', window.location.search);
|
|
15534
15595
|
span.setAttribute('navigation.hash', window.location.hash);
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
|
|
15538
|
-
|
|
15539
|
-
|
|
15596
|
+
if (enableConsoleLog) {
|
|
15597
|
+
console.log('[SignOz] Navigation (replaceState):', {
|
|
15598
|
+
from: previousUrl,
|
|
15599
|
+
to: window.location.href,
|
|
15600
|
+
pathname: window.location.pathname
|
|
15601
|
+
});
|
|
15602
|
+
}
|
|
15540
15603
|
previousUrl = window.location.href;
|
|
15541
15604
|
span.end();
|
|
15542
15605
|
return result;
|
|
15543
15606
|
};
|
|
15544
15607
|
}
|
|
15608
|
+
// Fungsi untuk menambahkan WebSocket logging
|
|
15609
|
+
function addWebSocketLogging(config) {
|
|
15610
|
+
if (!config.enableWebSocketLogging)
|
|
15611
|
+
return;
|
|
15612
|
+
const OriginalWebSocket = window.WebSocket;
|
|
15613
|
+
window.WebSocket = function (url, protocols) {
|
|
15614
|
+
const ws = new OriginalWebSocket(url, protocols);
|
|
15615
|
+
const wsUrl = typeof url === 'string' ? url : url.toString();
|
|
15616
|
+
// Capture current page info
|
|
15617
|
+
const pageUrl = window.location.href;
|
|
15618
|
+
const pagePath = window.location.pathname;
|
|
15619
|
+
const tracer = trace.getTracer('websocket-logger');
|
|
15620
|
+
let connectionSpan = tracer.startSpan('WebSocket Connection');
|
|
15621
|
+
const connectionStartTime = performance.now();
|
|
15622
|
+
connectionSpan.setAttribute('websocket.url', wsUrl);
|
|
15623
|
+
connectionSpan.setAttribute('websocket.protocols', Array.isArray(protocols) ? protocols.join(',') : (protocols || 'none'));
|
|
15624
|
+
connectionSpan.setAttribute('page.url', pageUrl);
|
|
15625
|
+
connectionSpan.setAttribute('page.pathname', pagePath);
|
|
15626
|
+
// Track connection open
|
|
15627
|
+
const originalOnOpen = ws.onopen;
|
|
15628
|
+
ws.addEventListener('open', function (event) {
|
|
15629
|
+
const duration = performance.now() - connectionStartTime;
|
|
15630
|
+
connectionSpan.setAttribute('websocket.state', 'open');
|
|
15631
|
+
connectionSpan.setAttribute('duration_ms', Math.round(duration));
|
|
15632
|
+
connectionSpan.setStatus({ code: SpanStatusCode.OK });
|
|
15633
|
+
if (config.enableConsoleLog) {
|
|
15634
|
+
console.log(`[SignOz] WebSocket Connected to ${wsUrl} from page ${pagePath} [${Math.round(duration)}ms]`);
|
|
15635
|
+
}
|
|
15636
|
+
connectionSpan.end();
|
|
15637
|
+
if (originalOnOpen) {
|
|
15638
|
+
originalOnOpen.call(ws, event);
|
|
15639
|
+
}
|
|
15640
|
+
});
|
|
15641
|
+
// Track messages sent
|
|
15642
|
+
const originalSend = ws.send;
|
|
15643
|
+
ws.send = function (data) {
|
|
15644
|
+
if (config.logWebSocketMessages) {
|
|
15645
|
+
const messageSpan = tracer.startSpan('WebSocket Send');
|
|
15646
|
+
const sendStartTime = performance.now();
|
|
15647
|
+
messageSpan.setAttribute('websocket.url', wsUrl);
|
|
15648
|
+
messageSpan.setAttribute('websocket.direction', 'send');
|
|
15649
|
+
messageSpan.setAttribute('page.url', pageUrl);
|
|
15650
|
+
messageSpan.setAttribute('page.pathname', pagePath);
|
|
15651
|
+
// Log message data
|
|
15652
|
+
if (typeof data === 'string') {
|
|
15653
|
+
const truncatedData = truncateBody(data, config.maxBodyLogSize);
|
|
15654
|
+
messageSpan.setAttribute('websocket.message', truncatedData);
|
|
15655
|
+
// Try to parse JSON and extract message if exists
|
|
15656
|
+
try {
|
|
15657
|
+
const jsonData = JSON.parse(data);
|
|
15658
|
+
if (jsonData.message) {
|
|
15659
|
+
messageSpan.setAttribute('websocket.message.text', jsonData.message);
|
|
15660
|
+
}
|
|
15661
|
+
if (jsonData.type || jsonData.event) {
|
|
15662
|
+
messageSpan.setAttribute('websocket.message.type', jsonData.type || jsonData.event);
|
|
15663
|
+
}
|
|
15664
|
+
}
|
|
15665
|
+
catch (e) {
|
|
15666
|
+
// Not JSON, ignore
|
|
15667
|
+
}
|
|
15668
|
+
if (config.enableConsoleLog) {
|
|
15669
|
+
console.log(`[SignOz] WebSocket Send to ${wsUrl} from page ${pagePath}:`, truncatedData);
|
|
15670
|
+
}
|
|
15671
|
+
}
|
|
15672
|
+
else {
|
|
15673
|
+
messageSpan.setAttribute('websocket.message', '[Binary Data]');
|
|
15674
|
+
messageSpan.setAttribute('websocket.message.type', 'binary');
|
|
15675
|
+
if (config.enableConsoleLog) {
|
|
15676
|
+
console.log(`[SignOz] WebSocket Send to ${wsUrl} from page ${pagePath}: [Binary Data]`);
|
|
15677
|
+
}
|
|
15678
|
+
}
|
|
15679
|
+
const duration = performance.now() - sendStartTime;
|
|
15680
|
+
messageSpan.setAttribute('duration_ms', Math.round(duration));
|
|
15681
|
+
messageSpan.setStatus({ code: SpanStatusCode.OK });
|
|
15682
|
+
messageSpan.end();
|
|
15683
|
+
}
|
|
15684
|
+
return originalSend.call(ws, data);
|
|
15685
|
+
};
|
|
15686
|
+
// Track messages received
|
|
15687
|
+
const originalOnMessage = ws.onmessage;
|
|
15688
|
+
ws.addEventListener('message', function (event) {
|
|
15689
|
+
if (config.logWebSocketMessages) {
|
|
15690
|
+
const messageSpan = tracer.startSpan('WebSocket Receive');
|
|
15691
|
+
messageSpan.setAttribute('websocket.url', wsUrl);
|
|
15692
|
+
messageSpan.setAttribute('websocket.direction', 'receive');
|
|
15693
|
+
messageSpan.setAttribute('page.url', pageUrl);
|
|
15694
|
+
messageSpan.setAttribute('page.pathname', pagePath);
|
|
15695
|
+
// Log message data
|
|
15696
|
+
if (typeof event.data === 'string') {
|
|
15697
|
+
const truncatedData = truncateBody(event.data, config.maxBodyLogSize);
|
|
15698
|
+
messageSpan.setAttribute('websocket.message', truncatedData);
|
|
15699
|
+
// Try to parse JSON and extract message if exists
|
|
15700
|
+
try {
|
|
15701
|
+
const jsonData = JSON.parse(event.data);
|
|
15702
|
+
if (jsonData.message) {
|
|
15703
|
+
messageSpan.setAttribute('websocket.message.text', jsonData.message);
|
|
15704
|
+
}
|
|
15705
|
+
if (jsonData.type || jsonData.event) {
|
|
15706
|
+
messageSpan.setAttribute('websocket.message.type', jsonData.type || jsonData.event);
|
|
15707
|
+
}
|
|
15708
|
+
}
|
|
15709
|
+
catch (e) {
|
|
15710
|
+
// Not JSON, ignore
|
|
15711
|
+
}
|
|
15712
|
+
if (config.enableConsoleLog) {
|
|
15713
|
+
console.log(`[SignOz] WebSocket Receive from ${wsUrl} on page ${pagePath}:`, truncatedData);
|
|
15714
|
+
}
|
|
15715
|
+
}
|
|
15716
|
+
else {
|
|
15717
|
+
messageSpan.setAttribute('websocket.message', '[Binary Data]');
|
|
15718
|
+
messageSpan.setAttribute('websocket.message.type', 'binary');
|
|
15719
|
+
if (config.enableConsoleLog) {
|
|
15720
|
+
console.log(`[SignOz] WebSocket Receive from ${wsUrl} on page ${pagePath}: [Binary Data]`);
|
|
15721
|
+
}
|
|
15722
|
+
}
|
|
15723
|
+
messageSpan.setStatus({ code: SpanStatusCode.OK });
|
|
15724
|
+
messageSpan.end();
|
|
15725
|
+
}
|
|
15726
|
+
if (originalOnMessage) {
|
|
15727
|
+
originalOnMessage.call(ws, event);
|
|
15728
|
+
}
|
|
15729
|
+
});
|
|
15730
|
+
// Track connection errors
|
|
15731
|
+
const originalOnError = ws.onerror;
|
|
15732
|
+
ws.addEventListener('error', function (event) {
|
|
15733
|
+
const errorSpan = tracer.startSpan('WebSocket Error');
|
|
15734
|
+
errorSpan.setAttribute('websocket.url', wsUrl);
|
|
15735
|
+
errorSpan.setAttribute('websocket.state', 'error');
|
|
15736
|
+
errorSpan.setAttribute('page.url', pageUrl);
|
|
15737
|
+
errorSpan.setAttribute('page.pathname', pagePath);
|
|
15738
|
+
errorSpan.recordException(new Error('WebSocket connection error'));
|
|
15739
|
+
errorSpan.setStatus({ code: SpanStatusCode.ERROR, message: 'WebSocket connection error' });
|
|
15740
|
+
if (config.enableConsoleLog) {
|
|
15741
|
+
console.error(`[SignOz] WebSocket Error for ${wsUrl} on page ${pagePath}`);
|
|
15742
|
+
}
|
|
15743
|
+
errorSpan.end();
|
|
15744
|
+
if (originalOnError) {
|
|
15745
|
+
originalOnError.call(ws, event);
|
|
15746
|
+
}
|
|
15747
|
+
});
|
|
15748
|
+
// Track connection close
|
|
15749
|
+
const originalOnClose = ws.onclose;
|
|
15750
|
+
ws.addEventListener('close', function (event) {
|
|
15751
|
+
const closeSpan = tracer.startSpan('WebSocket Close');
|
|
15752
|
+
closeSpan.setAttribute('websocket.url', wsUrl);
|
|
15753
|
+
closeSpan.setAttribute('websocket.state', 'closed');
|
|
15754
|
+
closeSpan.setAttribute('websocket.close.code', event.code);
|
|
15755
|
+
closeSpan.setAttribute('websocket.close.reason', event.reason || 'No reason provided');
|
|
15756
|
+
closeSpan.setAttribute('websocket.close.wasClean', event.wasClean);
|
|
15757
|
+
closeSpan.setAttribute('page.url', pageUrl);
|
|
15758
|
+
closeSpan.setAttribute('page.pathname', pagePath);
|
|
15759
|
+
if (config.enableConsoleLog) {
|
|
15760
|
+
console.log(`[SignOz] WebSocket Closed ${wsUrl} on page ${pagePath} - Code: ${event.code}, Reason: ${event.reason || 'No reason'}, Clean: ${event.wasClean}`);
|
|
15761
|
+
}
|
|
15762
|
+
closeSpan.setStatus({ code: SpanStatusCode.OK });
|
|
15763
|
+
closeSpan.end();
|
|
15764
|
+
if (originalOnClose) {
|
|
15765
|
+
originalOnClose.call(ws, event);
|
|
15766
|
+
}
|
|
15767
|
+
});
|
|
15768
|
+
return ws;
|
|
15769
|
+
};
|
|
15770
|
+
}
|
|
15545
15771
|
/**
|
|
15546
15772
|
* Inisialisasi SignOz tracing untuk aplikasi React
|
|
15547
15773
|
* @param config - Konfigurasi SignOz (opsional, akan menggunakan environment variables jika tidak disediakan)
|
|
@@ -15570,9 +15796,12 @@ function initializeSignOzTracing(config) {
|
|
|
15570
15796
|
logRequestBody: (config === null || config === void 0 ? void 0 : config.logRequestBody) !== undefined ? config.logRequestBody : (getConfigValue('REACT_APP_SIGNOZ_LOG_REQUEST_BODY') === 'true' || true),
|
|
15571
15797
|
logResponseBody: (config === null || config === void 0 ? void 0 : config.logResponseBody) !== undefined ? config.logResponseBody : (getConfigValue('REACT_APP_SIGNOZ_LOG_RESPONSE_BODY') === 'true' || true),
|
|
15572
15798
|
maxBodyLogSize: (config === null || config === void 0 ? void 0 : config.maxBodyLogSize) || parseInt(getConfigValue('REACT_APP_SIGNOZ_MAX_BODY_LOG_SIZE') || '10000') || 10000,
|
|
15573
|
-
enableDocumentLoad: (config === null || config === void 0 ? void 0 : config.enableDocumentLoad) !== undefined ? config.enableDocumentLoad : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD')
|
|
15799
|
+
enableDocumentLoad: (config === null || config === void 0 ? void 0 : config.enableDocumentLoad) !== undefined ? config.enableDocumentLoad : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD') === 'true'),
|
|
15574
15800
|
enableErrorTracking: (config === null || config === void 0 ? void 0 : config.enableErrorTracking) !== undefined ? config.enableErrorTracking : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_ERROR_TRACKING') !== 'false'),
|
|
15575
|
-
enableNavigationTracking: (config === null || config === void 0 ? void 0 : config.enableNavigationTracking) !== undefined ? config.enableNavigationTracking : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING')
|
|
15801
|
+
enableNavigationTracking: (config === null || config === void 0 ? void 0 : config.enableNavigationTracking) !== undefined ? config.enableNavigationTracking : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING') === 'true'),
|
|
15802
|
+
enableConsoleLog: (config === null || config === void 0 ? void 0 : config.enableConsoleLog) !== undefined ? config.enableConsoleLog : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_CONSOLE_LOG') === 'true'),
|
|
15803
|
+
enableWebSocketLogging: (config === null || config === void 0 ? void 0 : config.enableWebSocketLogging) !== undefined ? config.enableWebSocketLogging : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_WEBSOCKET_LOGGING') === 'true'),
|
|
15804
|
+
logWebSocketMessages: (config === null || config === void 0 ? void 0 : config.logWebSocketMessages) !== undefined ? config.logWebSocketMessages : (getConfigValue('REACT_APP_SIGNOZ_LOG_WEBSOCKET_MESSAGES') === 'true')
|
|
15576
15805
|
};
|
|
15577
15806
|
// Validasi konfigurasi
|
|
15578
15807
|
const { isValid, missingFields } = validateConfig(effectiveConfig);
|
|
@@ -15641,22 +15870,33 @@ function initializeSignOzTracing(config) {
|
|
|
15641
15870
|
enableRequestLogging: effectiveConfig.enableRequestLogging,
|
|
15642
15871
|
logRequestBody: effectiveConfig.logRequestBody,
|
|
15643
15872
|
logResponseBody: effectiveConfig.logResponseBody,
|
|
15644
|
-
maxBodyLogSize: effectiveConfig.maxBodyLogSize
|
|
15873
|
+
maxBodyLogSize: effectiveConfig.maxBodyLogSize,
|
|
15874
|
+
enableConsoleLog: effectiveConfig.enableConsoleLog
|
|
15645
15875
|
});
|
|
15646
15876
|
addXHRLogging({
|
|
15647
15877
|
enableRequestLogging: effectiveConfig.enableRequestLogging,
|
|
15648
15878
|
logRequestBody: effectiveConfig.logRequestBody,
|
|
15649
15879
|
logResponseBody: effectiveConfig.logResponseBody,
|
|
15650
|
-
maxBodyLogSize: effectiveConfig.maxBodyLogSize
|
|
15880
|
+
maxBodyLogSize: effectiveConfig.maxBodyLogSize,
|
|
15881
|
+
enableConsoleLog: effectiveConfig.enableConsoleLog
|
|
15651
15882
|
});
|
|
15652
15883
|
}
|
|
15653
15884
|
// Tambahkan error tracking
|
|
15654
15885
|
if (effectiveConfig.enableErrorTracking) {
|
|
15655
|
-
addErrorTracking();
|
|
15886
|
+
addErrorTracking(effectiveConfig.enableConsoleLog);
|
|
15656
15887
|
}
|
|
15657
15888
|
// Tambahkan navigation tracking
|
|
15658
15889
|
if (effectiveConfig.enableNavigationTracking) {
|
|
15659
|
-
addNavigationTracking();
|
|
15890
|
+
addNavigationTracking(effectiveConfig.enableConsoleLog);
|
|
15891
|
+
}
|
|
15892
|
+
// Tambahkan WebSocket logging
|
|
15893
|
+
if (effectiveConfig.enableWebSocketLogging) {
|
|
15894
|
+
addWebSocketLogging({
|
|
15895
|
+
enableWebSocketLogging: effectiveConfig.enableWebSocketLogging,
|
|
15896
|
+
logWebSocketMessages: effectiveConfig.logWebSocketMessages,
|
|
15897
|
+
maxBodyLogSize: effectiveConfig.maxBodyLogSize,
|
|
15898
|
+
enableConsoleLog: effectiveConfig.enableConsoleLog
|
|
15899
|
+
});
|
|
15660
15900
|
}
|
|
15661
15901
|
console.log('SignOz: Konfigurasi tracing:', {
|
|
15662
15902
|
serviceName: effectiveConfig.serviceName,
|
|
@@ -15669,7 +15909,9 @@ function initializeSignOzTracing(config) {
|
|
|
15669
15909
|
maxBodyLogSize: effectiveConfig.maxBodyLogSize,
|
|
15670
15910
|
enableDocumentLoad: effectiveConfig.enableDocumentLoad,
|
|
15671
15911
|
enableErrorTracking: effectiveConfig.enableErrorTracking,
|
|
15672
|
-
enableNavigationTracking: effectiveConfig.enableNavigationTracking
|
|
15912
|
+
enableNavigationTracking: effectiveConfig.enableNavigationTracking,
|
|
15913
|
+
enableWebSocketLogging: effectiveConfig.enableWebSocketLogging,
|
|
15914
|
+
logWebSocketMessages: effectiveConfig.logWebSocketMessages
|
|
15673
15915
|
});
|
|
15674
15916
|
console.log('SignOz: Tracing berhasil diinisialisasi');
|
|
15675
15917
|
}
|