@echoteam/signoz-react 1.2.2 → 1.2.4

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 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
@@ -71,6 +77,10 @@ REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD=false # default: false
71
77
  REACT_APP_SIGNOZ_ENABLE_ERROR_TRACKING=true # default: true
72
78
  REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING=false # default: false
73
79
 
80
+ # WebSocket Logging (opsional, default: false)
81
+ REACT_APP_SIGNOZ_ENABLE_WEBSOCKET_LOGGING=false
82
+ REACT_APP_SIGNOZ_LOG_WEBSOCKET_MESSAGES=false
83
+
74
84
  # Console Logging (opsional, default: false)
75
85
  REACT_APP_SIGNOZ_ENABLE_CONSOLE_LOG=false
76
86
  ```
@@ -137,6 +147,9 @@ initializeSignOzTracing({
137
147
  enableDocumentLoad: false, // Track page load performance (default: false)
138
148
  enableErrorTracking: true, // Track unhandled errors (default: true)
139
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
140
153
  // Console logging (default: false, hanya kirim ke SignOz tanpa console.log)
141
154
  enableConsoleLog: false // Set true untuk enable console.log di browser
142
155
  });
@@ -177,9 +190,11 @@ Library ini secara otomatis melog semua HTTP request dan response yang dilakukan
177
190
  4. Lihat span attributes:
178
191
  - `http.request.body`: Body dari request (untuk POST/PUT/PATCH)
179
192
  - `response.data`: Body dari response
193
+ - `response.message`: Message dari response JSON (jika ada field `message`)
180
194
  - `http.url`: URL endpoint
181
195
  - `http.method`: HTTP method
182
196
  - `http.status_code`: Status code response
197
+ - `duration_ms`: Durasi request dalam milliseconds
183
198
  - `page.url`: URL halaman frontend yang melakukan request
184
199
  - `page.pathname`: Pathname halaman frontend
185
200
  - `page.search`: Query parameters halaman frontend
@@ -303,6 +318,66 @@ initializeSignOzTracing({
303
318
  });
304
319
  ```
305
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
+ - `response.data`: Data yang diterima dari WebSocket (untuk receive messages)
355
+ - `response.message`: Message yang diterima (jika ada field `message` di JSON)
356
+ - `websocket.close.code`: Close code
357
+ - `websocket.close.reason`: Alasan close
358
+ - `websocket.close.wasClean`: Apakah close dengan clean
359
+ - `duration_ms`: Durasi connection
360
+ - `page.url`: URL halaman frontend
361
+ - `page.pathname`: Pathname halaman frontend
362
+
363
+ **Mengaktifkan WebSocket Logging:**
364
+ ```typescript
365
+ // WebSocket logging disabled by default
366
+ // Untuk mengaktifkan:
367
+ initializeSignOzTracing({
368
+ // ... konfigurasi lainnya
369
+ enableWebSocketLogging: true,
370
+ logWebSocketMessages: true // Enable message logging
371
+ });
372
+
373
+ // Atau hanya track connection tanpa log messages
374
+ initializeSignOzTracing({
375
+ // ... konfigurasi lainnya
376
+ enableWebSocketLogging: true,
377
+ logWebSocketMessages: false // Hanya track connection, tidak log messages
378
+ });
379
+ ```
380
+
306
381
  ### Error Boundary
307
382
 
308
383
  #### Penggunaan Dasar
@@ -461,6 +536,8 @@ Inisialisasi SignOz tracing untuk aplikasi React.
461
536
  - `enableErrorTracking` (opsional): Aktifkan automatic error tracking (default: true)
462
537
  - `enableNavigationTracking` (opsional): Aktifkan navigation/route tracking (default: false)
463
538
  - `enableConsoleLog` (opsional): Aktifkan console.log output di browser (default: false)
539
+ - `enableWebSocketLogging` (opsional): Aktifkan WebSocket connection dan message tracking (default: false)
540
+ - `logWebSocketMessages` (opsional): Log WebSocket message content (default: false)
464
541
 
465
542
  ### `ErrorBoundary`
466
543
 
package/dist/index.d.ts CHANGED
@@ -21,6 +21,8 @@ interface SignOzConfig {
21
21
  enableErrorTracking?: boolean;
22
22
  enableNavigationTracking?: boolean;
23
23
  enableConsoleLog?: boolean;
24
+ enableWebSocketLogging?: boolean;
25
+ logWebSocketMessages?: boolean;
24
26
  }
25
27
  declare global {
26
28
  interface Window {
package/dist/index.esm.js CHANGED
@@ -15350,6 +15350,16 @@ function addFetchLogging(config) {
15350
15350
  const responseData = await clonedResponse.text();
15351
15351
  const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15352
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
+ }
15353
15363
  if (config.enableConsoleLog) {
15354
15364
  console.log(`[SignOz] ${method} Response from ${url} (${response.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15355
15365
  }
@@ -15432,6 +15442,16 @@ function addXHRLogging(config) {
15432
15442
  const responseData = xhr.responseText;
15433
15443
  const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15434
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
+ }
15435
15455
  if (config.enableConsoleLog) {
15436
15456
  console.log(`[SignOz] ${method} Response from ${url} (${xhr.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15437
15457
  }
@@ -15585,6 +15605,172 @@ function addNavigationTracking(enableConsoleLog = false) {
15585
15605
  return result;
15586
15606
  };
15587
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
+ messageSpan.setAttribute('response.data', truncatedData); // Add response.data for consistency
15700
+ // Try to parse JSON and extract message if exists
15701
+ try {
15702
+ const jsonData = JSON.parse(event.data);
15703
+ if (jsonData.message) {
15704
+ messageSpan.setAttribute('websocket.message.text', jsonData.message);
15705
+ messageSpan.setAttribute('response.message', jsonData.message); // Add response.message for consistency
15706
+ }
15707
+ if (jsonData.type || jsonData.event) {
15708
+ messageSpan.setAttribute('websocket.message.type', jsonData.type || jsonData.event);
15709
+ }
15710
+ }
15711
+ catch (e) {
15712
+ // Not JSON, ignore
15713
+ }
15714
+ if (config.enableConsoleLog) {
15715
+ console.log(`[SignOz] WebSocket Receive from ${wsUrl} on page ${pagePath}:`, truncatedData);
15716
+ }
15717
+ }
15718
+ else {
15719
+ messageSpan.setAttribute('websocket.message', '[Binary Data]');
15720
+ messageSpan.setAttribute('websocket.message.type', 'binary');
15721
+ messageSpan.setAttribute('response.data', '[Binary Data]'); // Add response.data for consistency
15722
+ if (config.enableConsoleLog) {
15723
+ console.log(`[SignOz] WebSocket Receive from ${wsUrl} on page ${pagePath}: [Binary Data]`);
15724
+ }
15725
+ }
15726
+ messageSpan.setStatus({ code: SpanStatusCode.OK });
15727
+ messageSpan.end();
15728
+ }
15729
+ if (originalOnMessage) {
15730
+ originalOnMessage.call(ws, event);
15731
+ }
15732
+ });
15733
+ // Track connection errors
15734
+ const originalOnError = ws.onerror;
15735
+ ws.addEventListener('error', function (event) {
15736
+ const errorSpan = tracer.startSpan('WebSocket Error');
15737
+ errorSpan.setAttribute('websocket.url', wsUrl);
15738
+ errorSpan.setAttribute('websocket.state', 'error');
15739
+ errorSpan.setAttribute('page.url', pageUrl);
15740
+ errorSpan.setAttribute('page.pathname', pagePath);
15741
+ errorSpan.recordException(new Error('WebSocket connection error'));
15742
+ errorSpan.setStatus({ code: SpanStatusCode.ERROR, message: 'WebSocket connection error' });
15743
+ if (config.enableConsoleLog) {
15744
+ console.error(`[SignOz] WebSocket Error for ${wsUrl} on page ${pagePath}`);
15745
+ }
15746
+ errorSpan.end();
15747
+ if (originalOnError) {
15748
+ originalOnError.call(ws, event);
15749
+ }
15750
+ });
15751
+ // Track connection close
15752
+ const originalOnClose = ws.onclose;
15753
+ ws.addEventListener('close', function (event) {
15754
+ const closeSpan = tracer.startSpan('WebSocket Close');
15755
+ closeSpan.setAttribute('websocket.url', wsUrl);
15756
+ closeSpan.setAttribute('websocket.state', 'closed');
15757
+ closeSpan.setAttribute('websocket.close.code', event.code);
15758
+ closeSpan.setAttribute('websocket.close.reason', event.reason || 'No reason provided');
15759
+ closeSpan.setAttribute('websocket.close.wasClean', event.wasClean);
15760
+ closeSpan.setAttribute('page.url', pageUrl);
15761
+ closeSpan.setAttribute('page.pathname', pagePath);
15762
+ if (config.enableConsoleLog) {
15763
+ console.log(`[SignOz] WebSocket Closed ${wsUrl} on page ${pagePath} - Code: ${event.code}, Reason: ${event.reason || 'No reason'}, Clean: ${event.wasClean}`);
15764
+ }
15765
+ closeSpan.setStatus({ code: SpanStatusCode.OK });
15766
+ closeSpan.end();
15767
+ if (originalOnClose) {
15768
+ originalOnClose.call(ws, event);
15769
+ }
15770
+ });
15771
+ return ws;
15772
+ };
15773
+ }
15588
15774
  /**
15589
15775
  * Inisialisasi SignOz tracing untuk aplikasi React
15590
15776
  * @param config - Konfigurasi SignOz (opsional, akan menggunakan environment variables jika tidak disediakan)
@@ -15616,7 +15802,9 @@ function initializeSignOzTracing(config) {
15616
15802
  enableDocumentLoad: (config === null || config === void 0 ? void 0 : config.enableDocumentLoad) !== undefined ? config.enableDocumentLoad : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD') === 'true'),
15617
15803
  enableErrorTracking: (config === null || config === void 0 ? void 0 : config.enableErrorTracking) !== undefined ? config.enableErrorTracking : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_ERROR_TRACKING') !== 'false'),
15618
15804
  enableNavigationTracking: (config === null || config === void 0 ? void 0 : config.enableNavigationTracking) !== undefined ? config.enableNavigationTracking : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING') === 'true'),
15619
- enableConsoleLog: (config === null || config === void 0 ? void 0 : config.enableConsoleLog) !== undefined ? config.enableConsoleLog : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_CONSOLE_LOG') === 'true')
15805
+ enableConsoleLog: (config === null || config === void 0 ? void 0 : config.enableConsoleLog) !== undefined ? config.enableConsoleLog : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_CONSOLE_LOG') === 'true'),
15806
+ enableWebSocketLogging: (config === null || config === void 0 ? void 0 : config.enableWebSocketLogging) !== undefined ? config.enableWebSocketLogging : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_WEBSOCKET_LOGGING') === 'true'),
15807
+ logWebSocketMessages: (config === null || config === void 0 ? void 0 : config.logWebSocketMessages) !== undefined ? config.logWebSocketMessages : (getConfigValue('REACT_APP_SIGNOZ_LOG_WEBSOCKET_MESSAGES') === 'true')
15620
15808
  };
15621
15809
  // Validasi konfigurasi
15622
15810
  const { isValid, missingFields } = validateConfig(effectiveConfig);
@@ -15704,6 +15892,15 @@ function initializeSignOzTracing(config) {
15704
15892
  if (effectiveConfig.enableNavigationTracking) {
15705
15893
  addNavigationTracking(effectiveConfig.enableConsoleLog);
15706
15894
  }
15895
+ // Tambahkan WebSocket logging
15896
+ if (effectiveConfig.enableWebSocketLogging) {
15897
+ addWebSocketLogging({
15898
+ enableWebSocketLogging: effectiveConfig.enableWebSocketLogging,
15899
+ logWebSocketMessages: effectiveConfig.logWebSocketMessages,
15900
+ maxBodyLogSize: effectiveConfig.maxBodyLogSize,
15901
+ enableConsoleLog: effectiveConfig.enableConsoleLog
15902
+ });
15903
+ }
15707
15904
  console.log('SignOz: Konfigurasi tracing:', {
15708
15905
  serviceName: effectiveConfig.serviceName,
15709
15906
  environment: effectiveConfig.environment,
@@ -15715,7 +15912,9 @@ function initializeSignOzTracing(config) {
15715
15912
  maxBodyLogSize: effectiveConfig.maxBodyLogSize,
15716
15913
  enableDocumentLoad: effectiveConfig.enableDocumentLoad,
15717
15914
  enableErrorTracking: effectiveConfig.enableErrorTracking,
15718
- enableNavigationTracking: effectiveConfig.enableNavigationTracking
15915
+ enableNavigationTracking: effectiveConfig.enableNavigationTracking,
15916
+ enableWebSocketLogging: effectiveConfig.enableWebSocketLogging,
15917
+ logWebSocketMessages: effectiveConfig.logWebSocketMessages
15719
15918
  });
15720
15919
  console.log('SignOz: Tracing berhasil diinisialisasi');
15721
15920
  }