@echoteam/signoz-react 1.2.7 → 1.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,81 @@
1
1
  # Troubleshooting Guide
2
2
 
3
+ ## Error: Timeout from BatchSpanProcessor
4
+
5
+ ### Masalah
6
+ Jika Anda mendapatkan error seperti ini di console:
7
+ ```
8
+ Unhandled Promise rejection: Timeout ; Zone: <root> ; Task: Promise.then ; Value: Error: Timeout
9
+ at BatchSpanProcessorBase.js:132:1
10
+ ```
11
+
12
+ ### Penyebab
13
+ Error ini terjadi ketika BatchSpanProcessor mencoba mengirim spans ke backend SignOz tetapi mengalami timeout. Ini biasanya terjadi karena:
14
+ 1. Backend SignOz tidak dapat dijangkau
15
+ 2. Network lambat atau tidak stabil
16
+ 3. CORS tidak dikonfigurasi dengan benar di backend
17
+ 4. Timeout terlalu pendek untuk koneksi Anda
18
+
19
+ ### Solusi
20
+
21
+ #### 1. Verifikasi Backend SignOz Dapat Dijangkau
22
+ Pastikan URL SignOz Anda benar dan dapat diakses dari browser:
23
+ ```javascript
24
+ // Test di browser console
25
+ fetch('http://your-signoz-url:4318/v1/traces', {
26
+ method: 'POST',
27
+ headers: { 'Content-Type': 'application/json' }
28
+ })
29
+ ```
30
+
31
+ #### 2. Periksa CORS Configuration
32
+ Pastikan backend SignOz Anda mengizinkan request dari domain frontend Anda. Lihat [BACKEND_CORS_SETUP.md](./BACKEND_CORS_SETUP.md) untuk panduan lengkap.
33
+
34
+ #### 3. Tingkatkan Timeout (Recommended)
35
+ Sejak versi 1.2.10, timeout default sudah ditingkatkan menjadi 60 detik. Jika masih timeout, Anda bisa meningkatkannya lebih lanjut:
36
+
37
+ ```javascript
38
+ import { initializeSignOzTracing } from '@echoteam/signoz-react';
39
+
40
+ initializeSignOzTracing({
41
+ serviceName: 'my-app',
42
+ serviceVersion: '1.0.0',
43
+ environment: 'production',
44
+ serviceNamespace: 'frontend',
45
+ url: 'http://your-signoz-url:4318/v1/traces',
46
+ batchSpanProcessorConfig: {
47
+ maxQueueSize: 100,
48
+ scheduledDelayMillis: 5000,
49
+ exportTimeoutMillis: 120000, // 120 seconds
50
+ maxExportBatchSize: 50
51
+ }
52
+ });
53
+ ```
54
+
55
+ #### 4. Suppress Timeout Errors (Jika Tidak Mengganggu)
56
+ Sejak versi 1.2.10, timeout errors dari BatchSpanProcessor secara otomatis di-suppress untuk menghindari noise di console. Error ini biasanya aman untuk diabaikan karena spans akan di-retry atau di-queue ulang.
57
+
58
+ Jika Anda ingin melihat warning untuk timeout ini, aktifkan console logging:
59
+ ```javascript
60
+ initializeSignOzTracing({
61
+ // ... config lainnya
62
+ enableConsoleLog: true
63
+ });
64
+ ```
65
+
66
+ #### 5. Gunakan Network yang Lebih Stabil
67
+ Jika Anda mengalami timeout secara konsisten, pertimbangkan:
68
+ - Menggunakan koneksi internet yang lebih stabil
69
+ - Mengurangi ukuran batch dengan `maxExportBatchSize`
70
+ - Meningkatkan `scheduledDelayMillis` untuk mengirim spans lebih jarang
71
+
72
+ ### Catatan Penting
73
+ - Timeout errors biasanya tidak mempengaruhi fungsionalitas aplikasi Anda
74
+ - Spans yang gagal dikirim akan di-queue ulang dan dicoba lagi
75
+ - Jika backend SignOz tidak dapat dijangkau sama sekali, spans akan di-drop setelah queue penuh
76
+
77
+ ---
78
+
3
79
  ## Error: Can't resolve 'perf_hooks'
4
80
 
5
81
  ### Masalah
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ interface SignOzConfig {
11
11
  maxQueueSize?: number;
12
12
  scheduledDelayMillis?: number;
13
13
  exportTimeoutMillis?: number;
14
+ maxExportBatchSize?: number;
14
15
  };
15
16
  allowedOrigins?: (string | RegExp)[];
16
17
  enableRequestLogging?: boolean;
package/dist/index.esm.js CHANGED
@@ -15349,7 +15349,8 @@ function addFetchLogging(config) {
15349
15349
  if (contentLength) {
15350
15350
  span.setAttribute('http.response_content_length', parseInt(contentLength));
15351
15351
  }
15352
- if (config.logResponseBody && response.ok) {
15352
+ // Log response body for both success and error responses
15353
+ if (config.logResponseBody) {
15353
15354
  const clonedResponse = response.clone();
15354
15355
  try {
15355
15356
  const responseData = await clonedResponse.text();
@@ -15365,12 +15366,27 @@ function addFetchLogging(config) {
15365
15366
  if (jsonData.message) {
15366
15367
  span.setAttribute('response.message', jsonData.message);
15367
15368
  }
15369
+ // Also log error details if present
15370
+ if (jsonData.errors) {
15371
+ span.setAttribute('response.errors', JSON.stringify(jsonData.errors));
15372
+ }
15373
+ if (jsonData.status !== undefined) {
15374
+ span.setAttribute('response.status', jsonData.status);
15375
+ }
15376
+ if (jsonData.status_code !== undefined) {
15377
+ span.setAttribute('response.status_code', jsonData.status_code);
15378
+ }
15368
15379
  }
15369
15380
  catch (e) {
15370
15381
  // Not JSON or no message field, ignore
15371
15382
  }
15372
15383
  if (config.enableConsoleLog) {
15373
- console.log(`[SignOz] ${method} Response from ${url} (${response.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15384
+ if (response.ok) {
15385
+ console.log(`[SignOz] ${method} Response from ${url} (${response.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15386
+ }
15387
+ else {
15388
+ console.error(`[SignOz] ${method} Error Response from ${url} (${response.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15389
+ }
15374
15390
  }
15375
15391
  }
15376
15392
  catch (e) {
@@ -15380,7 +15396,7 @@ function addFetchLogging(config) {
15380
15396
  }
15381
15397
  }
15382
15398
  else if (!response.ok && config.enableConsoleLog) {
15383
- console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${response.status} [${Math.round(duration)}ms]`);
15399
+ console.error(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${response.status} [${Math.round(duration)}ms]`);
15384
15400
  }
15385
15401
  span.setStatus({ code: SpanStatusCode.OK });
15386
15402
  return response;
@@ -15451,31 +15467,66 @@ function addXHRLogging(config) {
15451
15467
  if (contentLength) {
15452
15468
  span.setAttribute('http.response_content_length', parseInt(contentLength));
15453
15469
  }
15454
- // Log response body
15455
- if (config.logResponseBody && xhr.status >= 200 && xhr.status < 300) {
15456
- const responseData = xhr.responseText;
15457
- const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15458
- span.setAttribute('response.data', truncatedData);
15459
- // If content-length header is not available, calculate from response data
15460
- if (!contentLength) {
15461
- span.setAttribute('http.response_content_length', responseData.length);
15462
- }
15463
- // Try to parse JSON and extract message if exists
15470
+ // Log response body for both success and error responses
15471
+ if (config.logResponseBody) {
15464
15472
  try {
15465
- const jsonData = JSON.parse(responseData);
15466
- if (jsonData.message) {
15467
- span.setAttribute('response.message', jsonData.message);
15473
+ // Only read responseText if responseType allows it
15474
+ if (xhr.responseType === '' || xhr.responseType === 'text') {
15475
+ const responseData = xhr.responseText;
15476
+ const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15477
+ span.setAttribute('response.data', truncatedData);
15478
+ // If content-length header is not available, calculate from response data
15479
+ if (!contentLength) {
15480
+ span.setAttribute('http.response_content_length', responseData.length);
15481
+ }
15482
+ // Try to parse JSON and extract message if exists
15483
+ try {
15484
+ const jsonData = JSON.parse(responseData);
15485
+ if (jsonData.message) {
15486
+ span.setAttribute('response.message', jsonData.message);
15487
+ }
15488
+ // Also log error details if present
15489
+ if (jsonData.errors) {
15490
+ span.setAttribute('response.errors', JSON.stringify(jsonData.errors));
15491
+ }
15492
+ if (jsonData.status !== undefined) {
15493
+ span.setAttribute('response.status', jsonData.status);
15494
+ }
15495
+ if (jsonData.status_code !== undefined) {
15496
+ span.setAttribute('response.status_code', jsonData.status_code);
15497
+ }
15498
+ }
15499
+ catch (e) {
15500
+ // Not JSON or no message field, ignore
15501
+ }
15502
+ if (config.enableConsoleLog) {
15503
+ if (xhr.status >= 200 && xhr.status < 300) {
15504
+ console.log(`[SignOz] ${method} Response from ${url} (${xhr.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15505
+ }
15506
+ else {
15507
+ console.error(`[SignOz] ${method} Error Response from ${url} (${xhr.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15508
+ }
15509
+ }
15510
+ }
15511
+ else {
15512
+ // For other response types (blob, arraybuffer, etc), just log the type
15513
+ span.setAttribute('response.data', `[${xhr.responseType} data]`);
15514
+ span.setAttribute('response.type', xhr.responseType);
15515
+ if (config.enableConsoleLog) {
15516
+ console.log(`[SignOz] ${method} Response from ${url} (${xhr.status}) on page ${pagePath} [${Math.round(duration)}ms]: [${xhr.responseType} data]`);
15517
+ }
15468
15518
  }
15469
15519
  }
15470
15520
  catch (e) {
15471
- // Not JSON or no message field, ignore
15472
- }
15473
- if (config.enableConsoleLog) {
15474
- console.log(`[SignOz] ${method} Response from ${url} (${xhr.status}) on page ${pagePath} [${Math.round(duration)}ms]:`, truncatedData);
15521
+ // If there's an error reading response, log it
15522
+ span.setAttribute('response.data', '[Error reading response]');
15523
+ if (config.enableConsoleLog) {
15524
+ console.warn(`[SignOz] Failed to read response from ${url}:`, e);
15525
+ }
15475
15526
  }
15476
15527
  }
15477
15528
  else if (xhr.status >= 300 && config.enableConsoleLog) {
15478
- console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${xhr.status} [${Math.round(duration)}ms]`);
15529
+ console.error(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${xhr.status} [${Math.round(duration)}ms]`);
15479
15530
  }
15480
15531
  span.setStatus({ code: SpanStatusCode.OK });
15481
15532
  span.end();
@@ -15508,9 +15559,15 @@ function addErrorTracking(enableConsoleLog = false) {
15508
15559
  span.setAttribute('error.filename', event.filename || 'unknown');
15509
15560
  span.setAttribute('error.lineno', event.lineno || 0);
15510
15561
  span.setAttribute('error.colno', event.colno || 0);
15562
+ // Add page context
15563
+ span.setAttribute('page.url', window.location.href);
15564
+ span.setAttribute('page.pathname', window.location.pathname);
15565
+ span.setAttribute('page.search', window.location.search);
15566
+ span.setAttribute('page.hash', window.location.hash);
15511
15567
  if (event.error) {
15512
15568
  span.recordException(event.error);
15513
15569
  span.setAttribute('error.stack', event.error.stack || '');
15570
+ span.setAttribute('error.name', event.error.name || 'Error');
15514
15571
  }
15515
15572
  span.setStatus({ code: SpanStatusCode.ERROR, message: event.message });
15516
15573
  if (enableConsoleLog) {
@@ -15519,28 +15576,102 @@ function addErrorTracking(enableConsoleLog = false) {
15519
15576
  filename: event.filename,
15520
15577
  lineno: event.lineno,
15521
15578
  colno: event.colno,
15522
- stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack
15579
+ stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack,
15580
+ page: window.location.pathname
15523
15581
  });
15524
15582
  }
15525
15583
  span.end();
15526
- });
15584
+ }, true); // Use capture phase to catch errors early
15527
15585
  // Track unhandled promise rejections
15528
15586
  window.addEventListener('unhandledrejection', (event) => {
15587
+ // Suppress BatchSpanProcessor timeout errors to avoid noise
15588
+ const reason = String(event.reason);
15589
+ if (reason.includes('Timeout') && reason.includes('BatchSpanProcessor')) {
15590
+ if (enableConsoleLog) {
15591
+ console.warn('[SignOz] Span export timeout (this is usually safe to ignore):', event.reason);
15592
+ }
15593
+ event.preventDefault(); // Prevent the error from being logged
15594
+ return;
15595
+ }
15529
15596
  const tracer = trace.getTracer('error-tracker');
15530
15597
  const span = tracer.startSpan('Unhandled Promise Rejection');
15531
15598
  span.setAttribute('error.type', 'unhandled_rejection');
15532
15599
  span.setAttribute('error.reason', String(event.reason));
15600
+ // Add page context
15601
+ span.setAttribute('page.url', window.location.href);
15602
+ span.setAttribute('page.pathname', window.location.pathname);
15603
+ span.setAttribute('page.search', window.location.search);
15604
+ span.setAttribute('page.hash', window.location.hash);
15533
15605
  if (event.reason instanceof Error) {
15534
15606
  span.recordException(event.reason);
15535
15607
  span.setAttribute('error.message', event.reason.message);
15536
15608
  span.setAttribute('error.stack', event.reason.stack || '');
15609
+ span.setAttribute('error.name', event.reason.name || 'Error');
15537
15610
  }
15538
15611
  span.setStatus({ code: SpanStatusCode.ERROR, message: String(event.reason) });
15539
15612
  if (enableConsoleLog) {
15540
- console.error('[SignOz] Unhandled Promise Rejection:', event.reason);
15613
+ console.error('[SignOz] Unhandled Promise Rejection:', event.reason, 'on page', window.location.pathname);
15541
15614
  }
15542
15615
  span.end();
15543
15616
  });
15617
+ // Track Zone.js errors (for Angular/React with zone.js)
15618
+ if (typeof Zone !== 'undefined' && Zone.current) {
15619
+ const currentZone = Zone.current;
15620
+ const originalHandleError = currentZone.handleError;
15621
+ if (originalHandleError) {
15622
+ currentZone.handleError = function (error) {
15623
+ const tracer = trace.getTracer('error-tracker');
15624
+ const span = tracer.startSpan('Zone.js Error');
15625
+ span.setAttribute('error.type', 'zone_error');
15626
+ span.setAttribute('error.message', error.message || String(error));
15627
+ span.setAttribute('error.name', error.name || 'Error');
15628
+ // Add page context
15629
+ span.setAttribute('page.url', window.location.href);
15630
+ span.setAttribute('page.pathname', window.location.pathname);
15631
+ span.setAttribute('page.search', window.location.search);
15632
+ span.setAttribute('page.hash', window.location.hash);
15633
+ if (error.stack) {
15634
+ span.setAttribute('error.stack', error.stack);
15635
+ }
15636
+ span.recordException(error);
15637
+ span.setStatus({ code: SpanStatusCode.ERROR, message: error.message || String(error) });
15638
+ if (enableConsoleLog) {
15639
+ console.error('[SignOz] Zone.js Error:', error, 'on page', window.location.pathname);
15640
+ }
15641
+ span.end();
15642
+ // Call original handler
15643
+ return originalHandleError.call(currentZone, error);
15644
+ };
15645
+ }
15646
+ }
15647
+ // Override console.error to catch React errors
15648
+ const originalConsoleError = console.error;
15649
+ console.error = function (...args) {
15650
+ // Check if this is a React error
15651
+ const errorMessage = args.map(arg => String(arg)).join(' ');
15652
+ if (errorMessage.includes('React') || errorMessage.includes('TypeError') || errorMessage.includes('Uncaught')) {
15653
+ const tracer = trace.getTracer('error-tracker');
15654
+ const span = tracer.startSpan('Console Error');
15655
+ span.setAttribute('error.type', 'console_error');
15656
+ span.setAttribute('error.message', errorMessage);
15657
+ // Add page context
15658
+ span.setAttribute('page.url', window.location.href);
15659
+ span.setAttribute('page.pathname', window.location.pathname);
15660
+ span.setAttribute('page.search', window.location.search);
15661
+ span.setAttribute('page.hash', window.location.hash);
15662
+ // Try to extract stack trace
15663
+ const errorObj = args.find(arg => arg instanceof Error);
15664
+ if (errorObj) {
15665
+ span.recordException(errorObj);
15666
+ span.setAttribute('error.stack', errorObj.stack || '');
15667
+ span.setAttribute('error.name', errorObj.name || 'Error');
15668
+ }
15669
+ span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
15670
+ span.end();
15671
+ }
15672
+ // Call original console.error
15673
+ return originalConsoleError.apply(console, args);
15674
+ };
15544
15675
  }
15545
15676
  // Fungsi untuk menambahkan navigation tracking
15546
15677
  function addNavigationTracking(enableConsoleLog = false) {
@@ -15862,7 +15993,8 @@ function initializeSignOzTracing(config) {
15862
15993
  batchSpanProcessorConfig: (config === null || config === void 0 ? void 0 : config.batchSpanProcessorConfig) || {
15863
15994
  maxQueueSize: 100,
15864
15995
  scheduledDelayMillis: 5000,
15865
- exportTimeoutMillis: 30000
15996
+ exportTimeoutMillis: 60000, // Increased to 60 seconds
15997
+ maxExportBatchSize: 50 // Smaller batches to avoid timeouts
15866
15998
  },
15867
15999
  allowedOrigins: (config === null || config === void 0 ? void 0 : config.allowedOrigins) || parseAllowedOrigins(getConfigValue('REACT_APP_SIGNOZ_ALLOWED_ORIGINS')),
15868
16000
  enableRequestLogging: (config === null || config === void 0 ? void 0 : config.enableRequestLogging) !== undefined ? config.enableRequestLogging : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_REQUEST_LOGGING') === 'true' || true),
@@ -15893,7 +16025,8 @@ function initializeSignOzTracing(config) {
15893
16025
  // Set up the OTLP trace exporter
15894
16026
  const exporter = new OTLPTraceExporter({
15895
16027
  url: effectiveConfig.url,
15896
- headers: effectiveConfig.headers
16028
+ headers: effectiveConfig.headers,
16029
+ timeoutMillis: 60000 // Set exporter timeout to 60 seconds
15897
16030
  });
15898
16031
  // Set up the span processor with configuration
15899
16032
  const processor = new BatchSpanProcessor(exporter, {
@@ -16103,17 +16236,6 @@ function hasArrayChanged() {
16103
16236
  }
16104
16237
 
16105
16238
  const DefaultErrorFallback = ({ error, resetErrorBoundary }) => {
16106
- const serviceName = window.REACT_APP_SIGNOZ_SERVICE_NAME || 'react-app';
16107
- const tracer = trace.getTracer(serviceName);
16108
- const span = tracer.startSpan(serviceName + ".error");
16109
- React2__default.useEffect(() => {
16110
- span.setAttribute('error.message', error.message);
16111
- span.setAttribute('error.stack', JSON.stringify(error.stack));
16112
- span.setAttribute('error.name', error.name);
16113
- span.recordException(error);
16114
- span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
16115
- span.end();
16116
- }, [error, span]);
16117
16239
  return (jsxs("div", { role: "alert", className: "error-boundary-fallback", children: [jsx("h1", { children: "Oops!" }), jsx("p", { children: "Terjadi kesalahan yang tidak terduga." }), jsx("p", { children: jsx("i", { children: error.statusText || error.message }) }), jsx("button", { onClick: resetErrorBoundary, children: "Coba lagi" })] }));
16118
16240
  };
16119
16241
  const ErrorBoundary = ({ children, fallback: FallbackComponent, onError, onReset, showResetButton = true, resetButtonText = "Coba lagi", fallbackClassName = "", }) => {
@@ -16122,10 +16244,16 @@ const ErrorBoundary = ({ children, fallback: FallbackComponent, onError, onReset
16122
16244
  const serviceName = window.REACT_APP_SIGNOZ_SERVICE_NAME || 'react-app';
16123
16245
  const tracer = trace.getTracer(serviceName);
16124
16246
  const span = tracer.startSpan(serviceName + ".error");
16247
+ span.setAttribute('error.type', 'react_error_boundary');
16125
16248
  span.setAttribute('error.message', error.message);
16126
- span.setAttribute('error.stack', JSON.stringify(error.stack));
16249
+ span.setAttribute('error.stack', error.stack || '');
16127
16250
  span.setAttribute('error.name', error.name);
16128
16251
  span.setAttribute('error.componentStack', errorInfo.componentStack || '');
16252
+ // Add page context
16253
+ span.setAttribute('page.url', window.location.href);
16254
+ span.setAttribute('page.pathname', window.location.pathname);
16255
+ span.setAttribute('page.search', window.location.search);
16256
+ span.setAttribute('page.hash', window.location.hash);
16129
16257
  span.recordException(error);
16130
16258
  span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
16131
16259
  span.end();