@echoteam/signoz-react 1.2.6 → 1.2.8

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
@@ -194,6 +194,7 @@ Library ini secara otomatis melog semua HTTP request dan response yang dilakukan
194
194
  - `http.url`: URL endpoint
195
195
  - `http.method`: HTTP method
196
196
  - `http.status_code`: Status code response
197
+ - `http.response_content_length`: Ukuran response dalam bytes
197
198
  - `duration_ms`: Durasi request dalam milliseconds
198
199
  - `page.url`: URL halaman frontend yang melakukan request
199
200
  - `page.pathname`: Pathname halaman frontend
package/dist/index.esm.js CHANGED
@@ -15344,24 +15344,49 @@ function addFetchLogging(config) {
15344
15344
  span.setAttribute('duration_ms', Math.round(duration));
15345
15345
  // Log response data
15346
15346
  span.setAttribute('http.status_code', response.status);
15347
- if (config.logResponseBody && response.ok) {
15347
+ // Log response content length from headers
15348
+ const contentLength = response.headers.get('content-length');
15349
+ if (contentLength) {
15350
+ span.setAttribute('http.response_content_length', parseInt(contentLength));
15351
+ }
15352
+ // Log response body for both success and error responses
15353
+ if (config.logResponseBody) {
15348
15354
  const clonedResponse = response.clone();
15349
15355
  try {
15350
15356
  const responseData = await clonedResponse.text();
15351
15357
  const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15352
15358
  span.setAttribute('response.data', truncatedData);
15359
+ // If content-length header is not available, calculate from response data
15360
+ if (!contentLength) {
15361
+ span.setAttribute('http.response_content_length', responseData.length);
15362
+ }
15353
15363
  // Try to parse JSON and extract message if exists
15354
15364
  try {
15355
15365
  const jsonData = JSON.parse(responseData);
15356
15366
  if (jsonData.message) {
15357
15367
  span.setAttribute('response.message', jsonData.message);
15358
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
+ }
15359
15379
  }
15360
15380
  catch (e) {
15361
15381
  // Not JSON or no message field, ignore
15362
15382
  }
15363
15383
  if (config.enableConsoleLog) {
15364
- 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
+ }
15365
15390
  }
15366
15391
  }
15367
15392
  catch (e) {
@@ -15371,7 +15396,7 @@ function addFetchLogging(config) {
15371
15396
  }
15372
15397
  }
15373
15398
  else if (!response.ok && config.enableConsoleLog) {
15374
- 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]`);
15375
15400
  }
15376
15401
  span.setStatus({ code: SpanStatusCode.OK });
15377
15402
  return response;
@@ -15437,27 +15462,71 @@ function addXHRLogging(config) {
15437
15462
  const duration = performance.now() - startTime;
15438
15463
  span.setAttribute('duration_ms', Math.round(duration));
15439
15464
  span.setAttribute('http.status_code', xhr.status);
15440
- // Log response body
15441
- if (config.logResponseBody && xhr.status >= 200 && xhr.status < 300) {
15442
- const responseData = xhr.responseText;
15443
- const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15444
- span.setAttribute('response.data', truncatedData);
15445
- // Try to parse JSON and extract message if exists
15465
+ // Log response content length from headers
15466
+ const contentLength = xhr.getResponseHeader('content-length');
15467
+ if (contentLength) {
15468
+ span.setAttribute('http.response_content_length', parseInt(contentLength));
15469
+ }
15470
+ // Log response body for both success and error responses
15471
+ if (config.logResponseBody) {
15446
15472
  try {
15447
- const jsonData = JSON.parse(responseData);
15448
- if (jsonData.message) {
15449
- 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
+ }
15450
15518
  }
15451
15519
  }
15452
15520
  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);
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
+ }
15457
15526
  }
15458
15527
  }
15459
15528
  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]`);
15529
+ console.error(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${xhr.status} [${Math.round(duration)}ms]`);
15461
15530
  }
15462
15531
  span.setStatus({ code: SpanStatusCode.OK });
15463
15532
  span.end();
@@ -15490,9 +15559,15 @@ function addErrorTracking(enableConsoleLog = false) {
15490
15559
  span.setAttribute('error.filename', event.filename || 'unknown');
15491
15560
  span.setAttribute('error.lineno', event.lineno || 0);
15492
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);
15493
15567
  if (event.error) {
15494
15568
  span.recordException(event.error);
15495
15569
  span.setAttribute('error.stack', event.error.stack || '');
15570
+ span.setAttribute('error.name', event.error.name || 'Error');
15496
15571
  }
15497
15572
  span.setStatus({ code: SpanStatusCode.ERROR, message: event.message });
15498
15573
  if (enableConsoleLog) {
@@ -15501,28 +15576,93 @@ function addErrorTracking(enableConsoleLog = false) {
15501
15576
  filename: event.filename,
15502
15577
  lineno: event.lineno,
15503
15578
  colno: event.colno,
15504
- 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
15505
15581
  });
15506
15582
  }
15507
15583
  span.end();
15508
- });
15584
+ }, true); // Use capture phase to catch errors early
15509
15585
  // Track unhandled promise rejections
15510
15586
  window.addEventListener('unhandledrejection', (event) => {
15511
15587
  const tracer = trace.getTracer('error-tracker');
15512
15588
  const span = tracer.startSpan('Unhandled Promise Rejection');
15513
15589
  span.setAttribute('error.type', 'unhandled_rejection');
15514
15590
  span.setAttribute('error.reason', String(event.reason));
15591
+ // Add page context
15592
+ span.setAttribute('page.url', window.location.href);
15593
+ span.setAttribute('page.pathname', window.location.pathname);
15594
+ span.setAttribute('page.search', window.location.search);
15595
+ span.setAttribute('page.hash', window.location.hash);
15515
15596
  if (event.reason instanceof Error) {
15516
15597
  span.recordException(event.reason);
15517
15598
  span.setAttribute('error.message', event.reason.message);
15518
15599
  span.setAttribute('error.stack', event.reason.stack || '');
15600
+ span.setAttribute('error.name', event.reason.name || 'Error');
15519
15601
  }
15520
15602
  span.setStatus({ code: SpanStatusCode.ERROR, message: String(event.reason) });
15521
15603
  if (enableConsoleLog) {
15522
- console.error('[SignOz] Unhandled Promise Rejection:', event.reason);
15604
+ console.error('[SignOz] Unhandled Promise Rejection:', event.reason, 'on page', window.location.pathname);
15523
15605
  }
15524
15606
  span.end();
15525
15607
  });
15608
+ // Track Zone.js errors (for Angular/React with zone.js)
15609
+ if (typeof Zone !== 'undefined' && Zone.current) {
15610
+ const currentZone = Zone.current;
15611
+ const originalHandleError = currentZone.handleError;
15612
+ if (originalHandleError) {
15613
+ currentZone.handleError = function (error) {
15614
+ const tracer = trace.getTracer('error-tracker');
15615
+ const span = tracer.startSpan('Zone.js Error');
15616
+ span.setAttribute('error.type', 'zone_error');
15617
+ span.setAttribute('error.message', error.message || String(error));
15618
+ span.setAttribute('error.name', error.name || 'Error');
15619
+ // Add page context
15620
+ span.setAttribute('page.url', window.location.href);
15621
+ span.setAttribute('page.pathname', window.location.pathname);
15622
+ span.setAttribute('page.search', window.location.search);
15623
+ span.setAttribute('page.hash', window.location.hash);
15624
+ if (error.stack) {
15625
+ span.setAttribute('error.stack', error.stack);
15626
+ }
15627
+ span.recordException(error);
15628
+ span.setStatus({ code: SpanStatusCode.ERROR, message: error.message || String(error) });
15629
+ if (enableConsoleLog) {
15630
+ console.error('[SignOz] Zone.js Error:', error, 'on page', window.location.pathname);
15631
+ }
15632
+ span.end();
15633
+ // Call original handler
15634
+ return originalHandleError.call(currentZone, error);
15635
+ };
15636
+ }
15637
+ }
15638
+ // Override console.error to catch React errors
15639
+ const originalConsoleError = console.error;
15640
+ console.error = function (...args) {
15641
+ // Check if this is a React error
15642
+ const errorMessage = args.map(arg => String(arg)).join(' ');
15643
+ if (errorMessage.includes('React') || errorMessage.includes('TypeError') || errorMessage.includes('Uncaught')) {
15644
+ const tracer = trace.getTracer('error-tracker');
15645
+ const span = tracer.startSpan('Console Error');
15646
+ span.setAttribute('error.type', 'console_error');
15647
+ span.setAttribute('error.message', errorMessage);
15648
+ // Add page context
15649
+ span.setAttribute('page.url', window.location.href);
15650
+ span.setAttribute('page.pathname', window.location.pathname);
15651
+ span.setAttribute('page.search', window.location.search);
15652
+ span.setAttribute('page.hash', window.location.hash);
15653
+ // Try to extract stack trace
15654
+ const errorObj = args.find(arg => arg instanceof Error);
15655
+ if (errorObj) {
15656
+ span.recordException(errorObj);
15657
+ span.setAttribute('error.stack', errorObj.stack || '');
15658
+ span.setAttribute('error.name', errorObj.name || 'Error');
15659
+ }
15660
+ span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
15661
+ span.end();
15662
+ }
15663
+ // Call original console.error
15664
+ return originalConsoleError.apply(console, args);
15665
+ };
15526
15666
  }
15527
15667
  // Fungsi untuk menambahkan navigation tracking
15528
15668
  function addNavigationTracking(enableConsoleLog = false) {
@@ -16085,17 +16225,6 @@ function hasArrayChanged() {
16085
16225
  }
16086
16226
 
16087
16227
  const DefaultErrorFallback = ({ error, resetErrorBoundary }) => {
16088
- const serviceName = window.REACT_APP_SIGNOZ_SERVICE_NAME || 'react-app';
16089
- const tracer = trace.getTracer(serviceName);
16090
- const span = tracer.startSpan(serviceName + ".error");
16091
- React2__default.useEffect(() => {
16092
- span.setAttribute('error.message', error.message);
16093
- span.setAttribute('error.stack', JSON.stringify(error.stack));
16094
- span.setAttribute('error.name', error.name);
16095
- span.recordException(error);
16096
- span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
16097
- span.end();
16098
- }, [error, span]);
16099
16228
  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" })] }));
16100
16229
  };
16101
16230
  const ErrorBoundary = ({ children, fallback: FallbackComponent, onError, onReset, showResetButton = true, resetButtonText = "Coba lagi", fallbackClassName = "", }) => {
@@ -16104,10 +16233,16 @@ const ErrorBoundary = ({ children, fallback: FallbackComponent, onError, onReset
16104
16233
  const serviceName = window.REACT_APP_SIGNOZ_SERVICE_NAME || 'react-app';
16105
16234
  const tracer = trace.getTracer(serviceName);
16106
16235
  const span = tracer.startSpan(serviceName + ".error");
16236
+ span.setAttribute('error.type', 'react_error_boundary');
16107
16237
  span.setAttribute('error.message', error.message);
16108
- span.setAttribute('error.stack', JSON.stringify(error.stack));
16238
+ span.setAttribute('error.stack', error.stack || '');
16109
16239
  span.setAttribute('error.name', error.name);
16110
16240
  span.setAttribute('error.componentStack', errorInfo.componentStack || '');
16241
+ // Add page context
16242
+ span.setAttribute('page.url', window.location.href);
16243
+ span.setAttribute('page.pathname', window.location.pathname);
16244
+ span.setAttribute('page.search', window.location.search);
16245
+ span.setAttribute('page.hash', window.location.hash);
16111
16246
  span.recordException(error);
16112
16247
  span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
16113
16248
  span.end();