@echoteam/signoz-react 1.0.7 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,6 +5,26 @@ Library React untuk monitoring dan tracing aplikasi menggunakan OpenTelemetry da
5
5
  ## 🚀 Fitur
6
6
 
7
7
  - **Tracing Otomatis**: Integrasi OpenTelemetry untuk tracing HTTP requests, fetch, dan XMLHttpRequest
8
+ - **Request/Response Logging**: Otomatis melog data request dan response untuk debugging dan monitoring
9
+ - Log GET request dengan response data
10
+ - Log POST/PUT/PATCH request dengan request body dan response data
11
+ - **Log halaman frontend (page URL)** yang melakukan request
12
+ - Konfigurasi maksimal ukuran body yang di-log
13
+ - Data tersimpan di span attributes SignOz
14
+ - **Error Tracking**: Otomatis menangkap dan melog unhandled errors dan promise rejections
15
+ - Track JavaScript errors dengan stack trace
16
+ - Track unhandled promise rejections
17
+ - Error details tersimpan di SignOz untuk analisis
18
+ - **Navigation Tracking**: Track route changes dan page navigation
19
+ - Track initial page load
20
+ - Track SPA navigation (pushState/replaceState)
21
+ - Track browser back/forward (popstate)
22
+ - Navigation history tersimpan di SignOz
23
+ - **Document Load Performance**: Track page load performance metrics
24
+ - First Paint, First Contentful Paint
25
+ - DOM Content Loaded, Load Complete
26
+ - Resource timing
27
+ - **No Click Tracking**: User interaction (click events) tidak di-track untuk privacy dan performa
8
28
  - **Error Boundary**: Komponen React untuk menangkap dan melaporkan error dengan tracing
9
29
  - **Error Page**: Halaman error untuk React Router dengan integrasi tracing
10
30
  - **TypeScript Support**: Dukungan penuh untuk TypeScript
@@ -39,14 +59,33 @@ REACT_APP_SIGNOZ_SERVICE_NAMESPACE=frontend
39
59
  REACT_APP_SIGNOZ_URL=https://your-signoz-instance.com/v1/traces
40
60
  REACT_APP_SIGNOZ_TRACE_SAMPLE_RATE=1.0
41
61
  REACT_APP_SIGNOZ_ALLOWED_ORIGINS=https://api1.example.com,https://api2.example.com,/^https:\/\/.*\.your-domain\.com$/
62
+
63
+ # Konfigurasi Request/Response Logging (opsional)
64
+ REACT_APP_SIGNOZ_ENABLE_REQUEST_LOGGING=true
65
+ REACT_APP_SIGNOZ_LOG_REQUEST_BODY=true
66
+ REACT_APP_SIGNOZ_LOG_RESPONSE_BODY=true
67
+ REACT_APP_SIGNOZ_MAX_BODY_LOG_SIZE=10000
68
+
69
+ # Konfigurasi Tracking (opsional, default: true)
70
+ REACT_APP_SIGNOZ_ENABLE_DOCUMENT_LOAD=true
71
+ REACT_APP_SIGNOZ_ENABLE_ERROR_TRACKING=true
72
+ REACT_APP_SIGNOZ_ENABLE_NAVIGATION_TRACKING=true
42
73
  ```
43
74
 
44
75
  > **Catatan untuk REACT_APP_SIGNOZ_ALLOWED_ORIGINS:**
45
76
  > - Daftar URL yang diizinkan untuk CORS, dipisahkan dengan koma
46
77
  > - Untuk RegExp pattern, gunakan format `/pattern/` (contoh: `/^https:\/\/.*\.example\.com$/`)
47
- > - Jika tidak diisi, default ke semua origin (`/.+/g`)
78
+ > - Gunakan '*' untuk mengizinkan semua origin
79
+ > - Jika tidak diisi, default ke '*' (mengizinkan semua origin)
48
80
  > - Spasi di sekitar koma akan dihapus otomatis
49
81
 
82
+ > **Catatan untuk Request/Response Logging:**
83
+ > - `REACT_APP_SIGNOZ_ENABLE_REQUEST_LOGGING`: Aktifkan/nonaktifkan logging request/response (default: true)
84
+ > - `REACT_APP_SIGNOZ_LOG_REQUEST_BODY`: Log body untuk POST/PUT/PATCH request (default: true)
85
+ > - `REACT_APP_SIGNOZ_LOG_RESPONSE_BODY`: Log response body untuk semua request (default: true)
86
+ > - `REACT_APP_SIGNOZ_MAX_BODY_LOG_SIZE`: Maksimal ukuran body yang di-log dalam bytes (default: 10000)
87
+ > - Data akan di-log ke console browser dan dikirim sebagai span attributes ke SignOz
88
+
50
89
  ### Inisialisasi
51
90
 
52
91
  ```typescript
@@ -83,13 +122,182 @@ initializeSignOzTracing({
83
122
  },
84
123
  allowedOrigins: [
85
124
  'https://api.example.com',
86
- /^https:\/\/.*\.your-domain\.com$/
87
- ]
125
+ /^https:\/\/.*\.your-domain\.com$/,
126
+ '*' // Mengizinkan semua origin (default)
127
+ ],
128
+ // Konfigurasi logging request/response
129
+ enableRequestLogging: true, // Aktifkan logging (default: true)
130
+ logRequestBody: true, // Log request body untuk POST/PUT/PATCH (default: true)
131
+ logResponseBody: true, // Log response body (default: true)
132
+ maxBodyLogSize: 10000, // Maksimal 10KB per log (default: 10000)
133
+ // Konfigurasi tracking
134
+ enableDocumentLoad: true, // Track page load performance (default: true)
135
+ enableErrorTracking: true, // Track unhandled errors (default: true)
136
+ enableNavigationTracking: true // Track route changes (default: true)
88
137
  });
89
138
  ```
90
139
 
91
140
  ## 🎯 Penggunaan
92
141
 
142
+ ### Request/Response Logging
143
+
144
+ Library ini secara otomatis melog semua HTTP request dan response yang dilakukan melalui `fetch` atau `XMLHttpRequest`. Data yang di-log meliputi:
145
+
146
+ **Untuk GET Request:**
147
+ - URL endpoint
148
+ - HTTP method
149
+ - Status code response
150
+ - Response body (jika `logResponseBody: true`)
151
+ - **URL halaman frontend** yang melakukan request (page.url, page.pathname)
152
+
153
+ **Untuk POST/PUT/PATCH Request:**
154
+ - URL endpoint
155
+ - HTTP method
156
+ - Request body (jika `logRequestBody: true`)
157
+ - Status code response
158
+ - Response body (jika `logResponseBody: true`)
159
+ - **URL halaman frontend** yang melakukan request (page.url, page.pathname)
160
+
161
+ **Contoh Output di Console:**
162
+ ```
163
+ [SignOz] GET Response from https://api.example.com/users (200) on page /dashboard: {"users":[{"id":1,"name":"John"}]}
164
+ [SignOz] POST Request to https://api.example.com/users from page /users/create: {"name":"Jane","email":"jane@example.com"}
165
+ [SignOz] POST Response from https://api.example.com/users (201) on page /users/create: {"id":2,"name":"Jane","email":"jane@example.com"}
166
+ ```
167
+
168
+ **Melihat Data di SignOz Dashboard:**
169
+ 1. Buka SignOz dashboard
170
+ 2. Navigasi ke **Traces**
171
+ 3. Pilih trace yang ingin dilihat
172
+ 4. Lihat span attributes:
173
+ - `http.request.body`: Body dari request (untuk POST/PUT/PATCH)
174
+ - `http.response.body`: Body dari response
175
+ - `http.url`: URL endpoint
176
+ - `http.method`: HTTP method
177
+ - `http.status_code`: Status code response
178
+ - `page.url`: URL halaman frontend yang melakukan request
179
+ - `page.pathname`: Pathname halaman frontend
180
+ - `page.search`: Query parameters halaman frontend
181
+ - `page.hash`: Hash fragment halaman frontend
182
+
183
+ **Menonaktifkan Logging:**
184
+ ```typescript
185
+ // Nonaktifkan semua logging
186
+ initializeSignOzTracing({
187
+ // ... konfigurasi lainnya
188
+ enableRequestLogging: false
189
+ });
190
+
191
+ // Atau hanya nonaktifkan logging body tertentu
192
+ initializeSignOzTracing({
193
+ // ... konfigurasi lainnya
194
+ enableRequestLogging: true,
195
+ logRequestBody: false, // Tidak log request body
196
+ logResponseBody: true // Tetap log response body
197
+ });
198
+ ```
199
+
200
+ ### Error Tracking
201
+
202
+ Library ini otomatis menangkap dan melog semua unhandled errors dan promise rejections.
203
+
204
+ **Contoh Output di Console:**
205
+ ```
206
+ [SignOz] Unhandled Error: {
207
+ message: "Cannot read property 'foo' of undefined",
208
+ filename: "app.js",
209
+ lineno: 42,
210
+ colno: 15,
211
+ stack: "TypeError: Cannot read property 'foo' of undefined\n at App.js:42:15"
212
+ }
213
+
214
+ [SignOz] Unhandled Promise Rejection: Error: API call failed
215
+ ```
216
+
217
+ **Data yang Di-track:**
218
+ - Error message
219
+ - Stack trace
220
+ - Filename dan line number
221
+ - Error type (unhandled error atau promise rejection)
222
+
223
+ **Melihat di SignOz:**
224
+ 1. Navigasi ke **Traces**
225
+ 2. Filter by span name: "Unhandled Error" atau "Unhandled Promise Rejection"
226
+ 3. Lihat span attributes:
227
+ - `error.type`: Tipe error
228
+ - `error.message`: Pesan error
229
+ - `error.stack`: Stack trace
230
+ - `error.filename`: File yang error
231
+ - `error.lineno`: Line number
232
+
233
+ **Menonaktifkan Error Tracking:**
234
+ ```typescript
235
+ initializeSignOzTracing({
236
+ // ... konfigurasi lainnya
237
+ enableErrorTracking: false
238
+ });
239
+ ```
240
+
241
+ ### Navigation Tracking
242
+
243
+ Library ini otomatis track semua route changes dan page navigation.
244
+
245
+ **Contoh Output di Console:**
246
+ ```
247
+ [SignOz] Page Load: { url: "https://example.com/", pathname: "/" }
248
+ [SignOz] Navigation (pushState): { from: "/", to: "/users", pathname: "/users" }
249
+ [SignOz] Navigation (popstate): { from: "/users", to: "/", pathname: "/" }
250
+ ```
251
+
252
+ **Data yang Di-track:**
253
+ - Initial page load
254
+ - SPA navigation (React Router, etc)
255
+ - Browser back/forward navigation
256
+ - URL, pathname, search params, hash
257
+
258
+ **Melihat di SignOz:**
259
+ 1. Navigasi ke **Traces**
260
+ 2. Filter by span name: "Page Load" atau "Navigation"
261
+ 3. Lihat span attributes:
262
+ - `navigation.type`: Tipe navigasi (initial, pushState, replaceState, popstate)
263
+ - `navigation.from`: URL sebelumnya
264
+ - `navigation.to`: URL tujuan
265
+ - `navigation.pathname`: Pathname
266
+ - `navigation.search`: Query parameters
267
+ - `navigation.hash`: Hash fragment
268
+
269
+ **Menonaktifkan Navigation Tracking:**
270
+ ```typescript
271
+ initializeSignOzTracing({
272
+ // ... konfigurasi lainnya
273
+ enableNavigationTracking: false
274
+ });
275
+ ```
276
+
277
+ ### Document Load Performance
278
+
279
+ Library ini otomatis track page load performance metrics menggunakan Navigation Timing API.
280
+
281
+ **Metrics yang Di-track:**
282
+ - First Paint (FP)
283
+ - First Contentful Paint (FCP)
284
+ - DOM Content Loaded
285
+ - Load Complete
286
+ - Resource timing (CSS, JS, images, etc)
287
+
288
+ **Melihat di SignOz:**
289
+ 1. Navigasi ke **Traces**
290
+ 2. Filter by span name: "documentLoad" atau "documentFetch"
291
+ 3. Lihat metrics untuk page load performance
292
+
293
+ **Menonaktifkan Document Load Tracking:**
294
+ ```typescript
295
+ initializeSignOzTracing({
296
+ // ... konfigurasi lainnya
297
+ enableDocumentLoad: false
298
+ });
299
+ ```
300
+
93
301
  ### Error Boundary
94
302
 
95
303
  #### Penggunaan Dasar
@@ -110,9 +318,9 @@ function App() {
110
318
  import { ErrorBoundary, ErrorBoundaryProps } from '@echoteam/signoz-react';
111
319
 
112
320
  // Custom fallback component
113
- const CustomErrorFallback: React.FC<{ error: Error; resetErrorBoundary: () => void }> = ({
114
- error,
115
- resetErrorBoundary
321
+ const CustomErrorFallback: React.FC<{ error: Error; resetErrorBoundary: () => void }> = ({
322
+ error,
323
+ resetErrorBoundary
116
324
  }) => (
117
325
  <div className="custom-error">
118
326
  <h2>Terjadi Kesalahan!</h2>
@@ -239,7 +447,14 @@ Inisialisasi SignOz tracing untuk aplikasi React.
239
447
  - `maxQueueSize`: Ukuran maksimum antrian span
240
448
  - `scheduledDelayMillis`: Delay pengiriman batch dalam milidetik
241
449
  - `exportTimeoutMillis`: Timeout ekspor dalam milidetik
242
- - `allowedOrigins` (opsional): Array URL/RegExp yang diizinkan untuk CORS
450
+ - `allowedOrigins` (wajib): Array URL/RegExp yang diizinkan untuk CORS. Gunakan ['*'] untuk mengizinkan semua origin
451
+ - `enableRequestLogging` (opsional): Aktifkan logging request/response (default: true)
452
+ - `logRequestBody` (opsional): Log request body untuk POST/PUT/PATCH (default: true)
453
+ - `logResponseBody` (opsional): Log response body untuk semua request (default: true)
454
+ - `maxBodyLogSize` (opsional): Maksimal ukuran body yang di-log dalam bytes (default: 10000)
455
+ - `enableDocumentLoad` (opsional): Aktifkan document load instrumentation (default: true)
456
+ - `enableErrorTracking` (opsional): Aktifkan automatic error tracking (default: true)
457
+ - `enableNavigationTracking` (opsional): Aktifkan navigation/route tracking (default: true)
243
458
 
244
459
  ### `ErrorBoundary`
245
460
 
package/dist/index.d.ts CHANGED
@@ -13,6 +13,13 @@ interface SignOzConfig {
13
13
  exportTimeoutMillis?: number;
14
14
  };
15
15
  allowedOrigins?: (string | RegExp)[];
16
+ enableRequestLogging?: boolean;
17
+ logRequestBody?: boolean;
18
+ logResponseBody?: boolean;
19
+ maxBodyLogSize?: number;
20
+ enableDocumentLoad?: boolean;
21
+ enableErrorTracking?: boolean;
22
+ enableNavigationTracking?: boolean;
16
23
  }
17
24
  declare global {
18
25
  interface Window {
package/dist/index.esm.js CHANGED
@@ -15263,17 +15263,13 @@ function getConfigValue(key) {
15263
15263
  }
15264
15264
  // Fungsi untuk memvalidasi konfigurasi
15265
15265
  function validateConfig(config) {
15266
- const requiredFields = ['serviceName', 'serviceVersion', 'environment', 'serviceNamespace', 'url', 'allowedOrigins'];
15266
+ const requiredFields = ['serviceName', 'serviceVersion', 'environment', 'serviceNamespace', 'url'];
15267
15267
  const missingFields = [];
15268
15268
  for (const field of requiredFields) {
15269
15269
  if (!config[field]) {
15270
15270
  missingFields.push(field);
15271
15271
  }
15272
15272
  }
15273
- // Khusus validasi allowedOrigins: pastikan array tidak kosong
15274
- if (config.allowedOrigins && config.allowedOrigins.length === 0) {
15275
- missingFields.push('allowedOrigins tidak boleh kosong demi keamanan CORS');
15276
- }
15277
15273
  return {
15278
15274
  isValid: missingFields.length === 0,
15279
15275
  missingFields
@@ -15297,6 +15293,255 @@ function parseAllowedOrigins(originsStr) {
15297
15293
  return origin;
15298
15294
  });
15299
15295
  }
15296
+ // Fungsi helper untuk truncate body jika terlalu besar
15297
+ function truncateBody(body, maxSize) {
15298
+ try {
15299
+ const bodyStr = typeof body === 'string' ? body : JSON.stringify(body);
15300
+ if (bodyStr.length > maxSize) {
15301
+ return bodyStr.substring(0, maxSize) + '... [truncated]';
15302
+ }
15303
+ return bodyStr;
15304
+ }
15305
+ catch (e) {
15306
+ return '[Unable to serialize body]';
15307
+ }
15308
+ }
15309
+ // Fungsi untuk menambahkan logging ke fetch instrumentation
15310
+ function addFetchLogging(config) {
15311
+ if (!config.enableRequestLogging)
15312
+ return;
15313
+ const originalFetch = window.fetch;
15314
+ window.fetch = async function (...args) {
15315
+ const [resource, init] = args;
15316
+ const url = typeof resource === 'string' ? resource : (resource instanceof Request ? resource.url : resource.toString());
15317
+ const method = (init === null || init === void 0 ? void 0 : init.method) || 'GET';
15318
+ // Capture current page info
15319
+ const pageUrl = window.location.href;
15320
+ const pagePath = window.location.pathname;
15321
+ const tracer = trace.getTracer('fetch-logger');
15322
+ const span = tracer.startSpan(`HTTP ${method} ${url}`);
15323
+ try {
15324
+ // Log request data
15325
+ span.setAttribute('http.url', url);
15326
+ span.setAttribute('http.method', method);
15327
+ // Log page info (frontend URL)
15328
+ span.setAttribute('page.url', pageUrl);
15329
+ span.setAttribute('page.pathname', pagePath);
15330
+ span.setAttribute('page.search', window.location.search);
15331
+ span.setAttribute('page.hash', window.location.hash);
15332
+ if (config.logRequestBody && (init === null || init === void 0 ? void 0 : init.body) && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
15333
+ const bodyStr = truncateBody(init.body, config.maxBodyLogSize);
15334
+ span.setAttribute('http.request.body', bodyStr);
15335
+ console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath}:`, bodyStr);
15336
+ }
15337
+ const response = await originalFetch.apply(this, args);
15338
+ // Log response data
15339
+ span.setAttribute('http.status_code', response.status);
15340
+ if (config.logResponseBody && response.ok) {
15341
+ const clonedResponse = response.clone();
15342
+ try {
15343
+ const responseData = await clonedResponse.text();
15344
+ const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15345
+ span.setAttribute('http.response.body', truncatedData);
15346
+ console.log(`[SignOz] ${method} Response from ${url} (${response.status}) on page ${pagePath}:`, truncatedData);
15347
+ }
15348
+ catch (e) {
15349
+ console.warn('[SignOz] Failed to read response body:', e);
15350
+ }
15351
+ }
15352
+ else if (!response.ok) {
15353
+ console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${response.status}`);
15354
+ }
15355
+ span.setStatus({ code: SpanStatusCode.OK });
15356
+ return response;
15357
+ }
15358
+ catch (error) {
15359
+ span.recordException(error);
15360
+ span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
15361
+ console.error(`[SignOz] ${method} Error for ${url} on page ${pagePath}:`, error);
15362
+ throw error;
15363
+ }
15364
+ finally {
15365
+ span.end();
15366
+ }
15367
+ };
15368
+ }
15369
+ // Fungsi untuk menambahkan logging ke XMLHttpRequest instrumentation
15370
+ function addXHRLogging(config) {
15371
+ if (!config.enableRequestLogging)
15372
+ return;
15373
+ const OriginalXHR = window.XMLHttpRequest;
15374
+ window.XMLHttpRequest = function () {
15375
+ const xhr = new OriginalXHR();
15376
+ let method = '';
15377
+ let url = '';
15378
+ // Capture current page info when XHR is created
15379
+ const pageUrl = window.location.href;
15380
+ const pagePath = window.location.pathname;
15381
+ const originalOpen = xhr.open;
15382
+ xhr.open = function (...args) {
15383
+ method = args[0];
15384
+ url = args[1];
15385
+ return originalOpen.apply(this, args);
15386
+ };
15387
+ const originalSend = xhr.send;
15388
+ xhr.send = function (body) {
15389
+ const tracer = trace.getTracer('xhr-logger');
15390
+ const span = tracer.startSpan(`HTTP ${method} ${url}`);
15391
+ span.setAttribute('http.url', url);
15392
+ span.setAttribute('http.method', method);
15393
+ // Log page info (frontend URL)
15394
+ span.setAttribute('page.url', pageUrl);
15395
+ span.setAttribute('page.pathname', pagePath);
15396
+ span.setAttribute('page.search', window.location.search);
15397
+ span.setAttribute('page.hash', window.location.hash);
15398
+ // Log request body
15399
+ if (config.logRequestBody && body && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
15400
+ const bodyStr = truncateBody(body, config.maxBodyLogSize);
15401
+ span.setAttribute('http.request.body', bodyStr);
15402
+ console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath}:`, bodyStr);
15403
+ }
15404
+ this.addEventListener('load', function () {
15405
+ span.setAttribute('http.status_code', xhr.status);
15406
+ // Log response body
15407
+ if (config.logResponseBody && xhr.status >= 200 && xhr.status < 300) {
15408
+ const responseData = xhr.responseText;
15409
+ const truncatedData = truncateBody(responseData, config.maxBodyLogSize);
15410
+ span.setAttribute('http.response.body', truncatedData);
15411
+ console.log(`[SignOz] ${method} Response from ${url} (${xhr.status}) on page ${pagePath}:`, truncatedData);
15412
+ }
15413
+ else if (xhr.status >= 300) {
15414
+ console.log(`[SignOz] ${method} Request to ${url} from page ${pagePath} - Status: ${xhr.status}`);
15415
+ }
15416
+ span.setStatus({ code: SpanStatusCode.OK });
15417
+ span.end();
15418
+ });
15419
+ this.addEventListener('error', function () {
15420
+ span.recordException(new Error('XHR request failed'));
15421
+ span.setStatus({ code: SpanStatusCode.ERROR, message: 'XHR request failed' });
15422
+ console.error(`[SignOz] ${method} Error for ${url} on page ${pagePath}`);
15423
+ span.end();
15424
+ });
15425
+ return originalSend.call(this, body);
15426
+ };
15427
+ return xhr;
15428
+ };
15429
+ }
15430
+ // Fungsi untuk menambahkan error tracking
15431
+ function addErrorTracking() {
15432
+ // Track unhandled errors
15433
+ window.addEventListener('error', (event) => {
15434
+ var _a;
15435
+ const tracer = trace.getTracer('error-tracker');
15436
+ const span = tracer.startSpan('Unhandled Error');
15437
+ span.setAttribute('error.type', 'unhandled');
15438
+ span.setAttribute('error.message', event.message);
15439
+ span.setAttribute('error.filename', event.filename || 'unknown');
15440
+ span.setAttribute('error.lineno', event.lineno || 0);
15441
+ span.setAttribute('error.colno', event.colno || 0);
15442
+ if (event.error) {
15443
+ span.recordException(event.error);
15444
+ span.setAttribute('error.stack', event.error.stack || '');
15445
+ }
15446
+ span.setStatus({ code: SpanStatusCode.ERROR, message: event.message });
15447
+ console.error('[SignOz] Unhandled Error:', {
15448
+ message: event.message,
15449
+ filename: event.filename,
15450
+ lineno: event.lineno,
15451
+ colno: event.colno,
15452
+ stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack
15453
+ });
15454
+ span.end();
15455
+ });
15456
+ // Track unhandled promise rejections
15457
+ window.addEventListener('unhandledrejection', (event) => {
15458
+ const tracer = trace.getTracer('error-tracker');
15459
+ const span = tracer.startSpan('Unhandled Promise Rejection');
15460
+ span.setAttribute('error.type', 'unhandled_rejection');
15461
+ span.setAttribute('error.reason', String(event.reason));
15462
+ if (event.reason instanceof Error) {
15463
+ span.recordException(event.reason);
15464
+ span.setAttribute('error.message', event.reason.message);
15465
+ span.setAttribute('error.stack', event.reason.stack || '');
15466
+ }
15467
+ span.setStatus({ code: SpanStatusCode.ERROR, message: String(event.reason) });
15468
+ console.error('[SignOz] Unhandled Promise Rejection:', event.reason);
15469
+ span.end();
15470
+ });
15471
+ }
15472
+ // Fungsi untuk menambahkan navigation tracking
15473
+ function addNavigationTracking() {
15474
+ let previousUrl = window.location.href;
15475
+ // Track initial page load
15476
+ const tracer = trace.getTracer('navigation-tracker');
15477
+ const initialSpan = tracer.startSpan('Page Load');
15478
+ initialSpan.setAttribute('navigation.type', 'initial');
15479
+ initialSpan.setAttribute('navigation.url', window.location.href);
15480
+ initialSpan.setAttribute('navigation.pathname', window.location.pathname);
15481
+ initialSpan.setAttribute('navigation.search', window.location.search);
15482
+ initialSpan.setAttribute('navigation.hash', window.location.hash);
15483
+ console.log('[SignOz] Page Load:', {
15484
+ url: window.location.href,
15485
+ pathname: window.location.pathname
15486
+ });
15487
+ initialSpan.end();
15488
+ // Track popstate (browser back/forward)
15489
+ window.addEventListener('popstate', () => {
15490
+ const span = tracer.startSpan('Navigation');
15491
+ span.setAttribute('navigation.type', 'popstate');
15492
+ span.setAttribute('navigation.from', previousUrl);
15493
+ span.setAttribute('navigation.to', window.location.href);
15494
+ span.setAttribute('navigation.pathname', window.location.pathname);
15495
+ span.setAttribute('navigation.search', window.location.search);
15496
+ span.setAttribute('navigation.hash', window.location.hash);
15497
+ console.log('[SignOz] Navigation (popstate):', {
15498
+ from: previousUrl,
15499
+ to: window.location.href,
15500
+ pathname: window.location.pathname
15501
+ });
15502
+ previousUrl = window.location.href;
15503
+ span.end();
15504
+ });
15505
+ // Track pushState and replaceState (SPA navigation)
15506
+ const originalPushState = history.pushState;
15507
+ history.pushState = function (...args) {
15508
+ const span = tracer.startSpan('Navigation');
15509
+ span.setAttribute('navigation.type', 'pushState');
15510
+ span.setAttribute('navigation.from', previousUrl);
15511
+ const result = originalPushState.apply(this, args);
15512
+ span.setAttribute('navigation.to', window.location.href);
15513
+ span.setAttribute('navigation.pathname', window.location.pathname);
15514
+ span.setAttribute('navigation.search', window.location.search);
15515
+ span.setAttribute('navigation.hash', window.location.hash);
15516
+ console.log('[SignOz] Navigation (pushState):', {
15517
+ from: previousUrl,
15518
+ to: window.location.href,
15519
+ pathname: window.location.pathname
15520
+ });
15521
+ previousUrl = window.location.href;
15522
+ span.end();
15523
+ return result;
15524
+ };
15525
+ const originalReplaceState = history.replaceState;
15526
+ history.replaceState = function (...args) {
15527
+ const span = tracer.startSpan('Navigation');
15528
+ span.setAttribute('navigation.type', 'replaceState');
15529
+ span.setAttribute('navigation.from', previousUrl);
15530
+ const result = originalReplaceState.apply(this, args);
15531
+ span.setAttribute('navigation.to', window.location.href);
15532
+ span.setAttribute('navigation.pathname', window.location.pathname);
15533
+ span.setAttribute('navigation.search', window.location.search);
15534
+ span.setAttribute('navigation.hash', window.location.hash);
15535
+ console.log('[SignOz] Navigation (replaceState):', {
15536
+ from: previousUrl,
15537
+ to: window.location.href,
15538
+ pathname: window.location.pathname
15539
+ });
15540
+ previousUrl = window.location.href;
15541
+ span.end();
15542
+ return result;
15543
+ };
15544
+ }
15300
15545
  /**
15301
15546
  * Inisialisasi SignOz tracing untuk aplikasi React
15302
15547
  * @param config - Konfigurasi SignOz (opsional, akan menggunakan environment variables jika tidak disediakan)
@@ -15320,7 +15565,14 @@ function initializeSignOzTracing(config) {
15320
15565
  scheduledDelayMillis: 5000,
15321
15566
  exportTimeoutMillis: 30000
15322
15567
  },
15323
- allowedOrigins: (config === null || config === void 0 ? void 0 : config.allowedOrigins) || parseAllowedOrigins(getConfigValue('REACT_APP_SIGNOZ_ALLOWED_ORIGINS'))
15568
+ allowedOrigins: (config === null || config === void 0 ? void 0 : config.allowedOrigins) || parseAllowedOrigins(getConfigValue('REACT_APP_SIGNOZ_ALLOWED_ORIGINS')),
15569
+ enableRequestLogging: (config === null || config === void 0 ? void 0 : config.enableRequestLogging) !== undefined ? config.enableRequestLogging : (getConfigValue('REACT_APP_SIGNOZ_ENABLE_REQUEST_LOGGING') === 'true' || true),
15570
+ logRequestBody: (config === null || config === void 0 ? void 0 : config.logRequestBody) !== undefined ? config.logRequestBody : (getConfigValue('REACT_APP_SIGNOZ_LOG_REQUEST_BODY') === 'true' || true),
15571
+ logResponseBody: (config === null || config === void 0 ? void 0 : config.logResponseBody) !== undefined ? config.logResponseBody : (getConfigValue('REACT_APP_SIGNOZ_LOG_RESPONSE_BODY') === 'true' || true),
15572
+ 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') !== 'false'),
15574
+ 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') !== 'false')
15324
15576
  };
15325
15577
  // Validasi konfigurasi
15326
15578
  const { isValid, missingFields } = validateConfig(effectiveConfig);
@@ -15370,14 +15622,52 @@ function initializeSignOzTracing(config) {
15370
15622
  '@opentelemetry/instrumentation-fetch': {
15371
15623
  propagateTraceHeaderCorsUrls: effectiveConfig.allowedOrigins,
15372
15624
  },
15625
+ // Nonaktifkan user interaction instrumentation (click events)
15626
+ '@opentelemetry/instrumentation-user-interaction': {
15627
+ enabled: false,
15628
+ },
15629
+ // Document load instrumentation untuk page load performance
15630
+ '@opentelemetry/instrumentation-document-load': {
15631
+ enabled: effectiveConfig.enableDocumentLoad,
15632
+ },
15373
15633
  }),
15374
15634
  ],
15375
15635
  });
15636
+ // Tambahkan custom logging untuk request/response
15637
+ if (effectiveConfig.enableRequestLogging) {
15638
+ addFetchLogging({
15639
+ enableRequestLogging: effectiveConfig.enableRequestLogging,
15640
+ logRequestBody: effectiveConfig.logRequestBody,
15641
+ logResponseBody: effectiveConfig.logResponseBody,
15642
+ maxBodyLogSize: effectiveConfig.maxBodyLogSize
15643
+ });
15644
+ addXHRLogging({
15645
+ enableRequestLogging: effectiveConfig.enableRequestLogging,
15646
+ logRequestBody: effectiveConfig.logRequestBody,
15647
+ logResponseBody: effectiveConfig.logResponseBody,
15648
+ maxBodyLogSize: effectiveConfig.maxBodyLogSize
15649
+ });
15650
+ }
15651
+ // Tambahkan error tracking
15652
+ if (effectiveConfig.enableErrorTracking) {
15653
+ addErrorTracking();
15654
+ }
15655
+ // Tambahkan navigation tracking
15656
+ if (effectiveConfig.enableNavigationTracking) {
15657
+ addNavigationTracking();
15658
+ }
15376
15659
  console.log('SignOz: Konfigurasi tracing:', {
15377
15660
  serviceName: effectiveConfig.serviceName,
15378
15661
  environment: effectiveConfig.environment,
15379
15662
  allowedOrigins: effectiveConfig.allowedOrigins,
15380
- traceSampleRate: effectiveConfig.traceSampleRate
15663
+ traceSampleRate: effectiveConfig.traceSampleRate,
15664
+ enableRequestLogging: effectiveConfig.enableRequestLogging,
15665
+ logRequestBody: effectiveConfig.logRequestBody,
15666
+ logResponseBody: effectiveConfig.logResponseBody,
15667
+ maxBodyLogSize: effectiveConfig.maxBodyLogSize,
15668
+ enableDocumentLoad: effectiveConfig.enableDocumentLoad,
15669
+ enableErrorTracking: effectiveConfig.enableErrorTracking,
15670
+ enableNavigationTracking: effectiveConfig.enableNavigationTracking
15381
15671
  });
15382
15672
  console.log('SignOz: Tracing berhasil diinisialisasi');
15383
15673
  }