reroute-js 0.26.0 → 0.27.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.
Files changed (193) hide show
  1. package/README.md +12 -8
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +136 -40
  4. package/cli/bin.js.map +16 -13
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +4 -4
  7. package/cli/index.js.map +1 -1
  8. package/cli/src/cli.d.ts +1 -1
  9. package/cli/src/commands/analyze.d.ts +1 -1
  10. package/cli/src/commands/build.d.ts +1 -1
  11. package/cli/src/commands/build.d.ts.map +1 -1
  12. package/cli/src/commands/dev.d.ts +1 -1
  13. package/cli/src/commands/gen.d.ts +1 -1
  14. package/cli/src/commands/gen.d.ts.map +1 -1
  15. package/cli/src/commands/index.d.ts +1 -1
  16. package/cli/src/commands/init.d.ts +1 -1
  17. package/cli/src/commands/lib/assets.d.ts +1 -1
  18. package/cli/src/commands/lib/bundler.d.ts +1 -1
  19. package/cli/src/commands/lib/command.d.ts +1 -1
  20. package/cli/src/commands/lib/env.d.ts +1 -1
  21. package/cli/src/commands/lib/index.d.ts +1 -1
  22. package/cli/src/commands/lib/log.d.ts +1 -1
  23. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  24. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  25. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  26. package/cli/src/commands/lib/production.d.ts +1 -1
  27. package/cli/src/commands/lib/server.d.ts +1 -1
  28. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  29. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  30. package/cli/src/commands/lib/tailwind.d.ts +1 -1
  31. package/cli/src/commands/lib/terminal-ui.d.ts +1 -1
  32. package/cli/src/commands/lib/version.d.ts +1 -1
  33. package/cli/src/commands/og.d.ts +1 -1
  34. package/cli/src/commands/start.d.ts +1 -1
  35. package/cli/src/index.d.ts +1 -1
  36. package/core/index.d.ts +1 -1
  37. package/core/index.js +96 -9
  38. package/core/index.js.map +14 -11
  39. package/core/src/bundler/hash.d.ts +1 -1
  40. package/core/src/bundler/index.d.ts +1 -1
  41. package/core/src/config.d.ts +41 -13
  42. package/core/src/config.d.ts.map +1 -1
  43. package/core/src/content/discovery.d.ts +1 -1
  44. package/core/src/content/index.d.ts +1 -1
  45. package/core/src/content/metadata.d.ts +1 -1
  46. package/core/src/index.d.ts +1 -1
  47. package/core/src/llms/extractor.d.ts +1 -1
  48. package/core/src/llms/formatter.d.ts +1 -1
  49. package/core/src/llms/full-generator.d.ts +1 -1
  50. package/core/src/llms/index-generator.d.ts +1 -1
  51. package/core/src/llms/index.d.ts +1 -1
  52. package/core/src/og/discovery.d.ts +1 -1
  53. package/core/src/og/index.d.ts +1 -1
  54. package/core/src/og/meta.d.ts +1 -1
  55. package/core/src/og/render.d.ts +1 -1
  56. package/core/src/og/types.d.ts +1 -1
  57. package/core/src/robots/discovery.d.ts +1 -1
  58. package/core/src/robots/generator.d.ts +1 -1
  59. package/core/src/robots/index.d.ts +1 -1
  60. package/core/src/robots/policies.d.ts +1 -1
  61. package/core/src/rss/discovery.d.ts +1 -1
  62. package/core/src/rss/generator.d.ts +1 -1
  63. package/core/src/rss/index.d.ts +1 -1
  64. package/core/src/sitemap/discovery.d.ts +1 -1
  65. package/core/src/sitemap/generator.d.ts +1 -1
  66. package/core/src/sitemap/index.d.ts +1 -1
  67. package/core/src/ssr/index.d.ts +1 -1
  68. package/core/src/ssr/lib/cache.d.ts +1 -1
  69. package/core/src/ssr/lib/collections.d.ts +1 -1
  70. package/core/src/ssr/lib/compression.d.ts +1 -1
  71. package/core/src/ssr/lib/compute/content.d.ts +1 -1
  72. package/core/src/ssr/lib/compute/index.d.ts +1 -1
  73. package/core/src/ssr/lib/compute/layouts.d.ts +1 -1
  74. package/core/src/ssr/lib/compute/routes.d.ts +1 -1
  75. package/core/src/ssr/lib/data.d.ts +1 -1
  76. package/core/src/ssr/lib/html.d.ts +1 -1
  77. package/core/src/ssr/lib/imports.d.ts +1 -1
  78. package/core/src/ssr/lib/index.d.ts +1 -1
  79. package/core/src/ssr/lib/layouts.d.ts +1 -1
  80. package/core/src/ssr/lib/metadata.d.ts +1 -1
  81. package/core/src/ssr/lib/mime.d.ts +1 -1
  82. package/core/src/ssr/lib/modules.d.ts +1 -1
  83. package/core/src/ssr/lib/path.d.ts +1 -1
  84. package/core/src/ssr/lib/preload.d.ts +1 -1
  85. package/core/src/ssr/lib/scripts/collections.d.ts +1 -1
  86. package/core/src/ssr/lib/scripts/data.d.ts +5 -2
  87. package/core/src/ssr/lib/scripts/data.d.ts.map +1 -1
  88. package/core/src/ssr/lib/scripts/escape.d.ts +1 -1
  89. package/core/src/ssr/lib/scripts/feeds.d.ts +1 -1
  90. package/core/src/ssr/lib/scripts/index.d.ts +1 -1
  91. package/core/src/ssr/lib/seed.d.ts +1 -1
  92. package/core/src/ssr/lib/serialize.d.ts +17 -0
  93. package/core/src/ssr/lib/serialize.d.ts.map +1 -0
  94. package/core/src/ssr/lib/setup.d.ts +5 -2
  95. package/core/src/ssr/lib/setup.d.ts.map +1 -1
  96. package/core/src/ssr/lib/styles.d.ts +1 -1
  97. package/core/src/ssr/lib/template.d.ts +1 -1
  98. package/core/src/ssr/lib/types.d.ts +1 -1
  99. package/core/src/ssr/render.d.ts +1 -1
  100. package/core/src/ssr/render.d.ts.map +1 -1
  101. package/core/src/ssr/stream.d.ts +1 -1
  102. package/core/src/ssr/stream.d.ts.map +1 -1
  103. package/elysia/index.d.ts +1 -1
  104. package/elysia/index.js +96 -9
  105. package/elysia/index.js.map +14 -11
  106. package/elysia/src/index.d.ts +1 -1
  107. package/elysia/src/libs/assets.d.ts +1 -1
  108. package/elysia/src/libs/cache.d.ts +1 -1
  109. package/elysia/src/libs/caching.d.ts +1 -1
  110. package/elysia/src/libs/http.d.ts +1 -1
  111. package/elysia/src/libs/image.d.ts +1 -1
  112. package/elysia/src/libs/index.d.ts +1 -1
  113. package/elysia/src/libs/llms.d.ts +1 -1
  114. package/elysia/src/libs/response.d.ts +1 -1
  115. package/elysia/src/libs/serving.d.ts +1 -1
  116. package/elysia/src/plugin.d.ts +1 -1
  117. package/elysia/src/routes/artifacts.d.ts +1 -1
  118. package/elysia/src/routes/content.d.ts +1 -1
  119. package/elysia/src/routes/image.d.ts +1 -1
  120. package/elysia/src/routes/index.d.ts +1 -1
  121. package/elysia/src/routes/internal.d.ts +1 -1
  122. package/elysia/src/routes/llms.d.ts +1 -1
  123. package/elysia/src/routes/og.d.ts +1 -1
  124. package/elysia/src/routes/redirects.d.ts +1 -1
  125. package/elysia/src/routes/robots.d.ts +1 -1
  126. package/elysia/src/routes/rss.d.ts +1 -1
  127. package/elysia/src/routes/search.d.ts +1 -1
  128. package/elysia/src/routes/sitemap.d.ts +1 -1
  129. package/elysia/src/routes/ssr.d.ts +1 -1
  130. package/elysia/src/routes/static.d.ts +1 -1
  131. package/elysia/src/types.d.ts +1 -1
  132. package/package.json +9 -13
  133. package/react/index.d.ts +1 -1
  134. package/react/index.js +2 -2
  135. package/react/index.js.map +1 -1
  136. package/react/src/components/ClientOnly.d.ts +1 -1
  137. package/react/src/components/ContentRoute.d.ts +1 -1
  138. package/react/src/components/Image.d.ts +1 -1
  139. package/react/src/components/LazyRoute.d.ts +1 -1
  140. package/react/src/components/Link.d.ts +1 -1
  141. package/react/src/components/Markdown.d.ts +1 -1
  142. package/react/src/components/Outlet.d.ts +1 -1
  143. package/react/src/components/index.d.ts +1 -1
  144. package/react/src/hooks/index.d.ts +1 -1
  145. package/react/src/hooks/useContent.d.ts +1 -1
  146. package/react/src/hooks/useData.d.ts +1 -1
  147. package/react/src/hooks/useFeed.d.ts +1 -1
  148. package/react/src/hooks/useLayoutData.d.ts +1 -1
  149. package/react/src/hooks/useLlms.d.ts +1 -1
  150. package/react/src/hooks/useNavigate.d.ts +1 -1
  151. package/react/src/hooks/useParams.d.ts +1 -1
  152. package/react/src/hooks/useRouter.d.ts +1 -1
  153. package/react/src/hooks/useSearch.d.ts +1 -1
  154. package/react/src/hooks/useSearchParams.d.ts +1 -1
  155. package/react/src/hooks/useToc.d.ts +1 -1
  156. package/react/src/index.d.ts +1 -1
  157. package/react/src/lib/collection.d.ts +1 -1
  158. package/react/src/lib/content.d.ts +1 -1
  159. package/react/src/lib/head.d.ts +1 -1
  160. package/react/src/lib/index.d.ts +1 -1
  161. package/react/src/lib/lazy-route.d.ts +1 -1
  162. package/react/src/lib/route-loader.d.ts +1 -1
  163. package/react/src/providers/ContentProvider.d.ts +1 -1
  164. package/react/src/providers/RerouteProvider.d.ts +1 -1
  165. package/react/src/providers/RouterProvider.d.ts +1 -1
  166. package/react/src/providers/index.d.ts +1 -1
  167. package/react/src/types/any.d.ts +1 -1
  168. package/react/src/types/index.d.ts +1 -1
  169. package/react/src/types/router.d.ts +1 -1
  170. package/telemetry/react.d.ts +1 -1
  171. package/telemetry/react.js +539 -30
  172. package/telemetry/react.js.map +7 -6
  173. package/telemetry/server.d.ts +1 -1
  174. package/telemetry/server.js +304 -20
  175. package/telemetry/server.js.map +12 -10
  176. package/telemetry/src/react/api.d.ts +3 -2
  177. package/telemetry/src/react/api.d.ts.map +1 -1
  178. package/telemetry/src/react/context.d.ts +62 -0
  179. package/telemetry/src/react/context.d.ts.map +1 -0
  180. package/telemetry/src/react/index.d.ts +2 -1
  181. package/telemetry/src/react/index.d.ts.map +1 -1
  182. package/telemetry/src/react/telemetry.d.ts +4 -53
  183. package/telemetry/src/react/telemetry.d.ts.map +1 -1
  184. package/telemetry/src/server/context.d.ts +61 -0
  185. package/telemetry/src/server/context.d.ts.map +1 -0
  186. package/telemetry/src/server/index.d.ts +3 -1
  187. package/telemetry/src/server/index.d.ts.map +1 -1
  188. package/telemetry/src/server/instrumentation.d.ts +27 -2
  189. package/telemetry/src/server/instrumentation.d.ts.map +1 -1
  190. package/telemetry/src/server/plugin.d.ts +1 -1
  191. package/telemetry/src/server/plugin.d.ts.map +1 -1
  192. package/telemetry/src/server/sourcemap.d.ts +55 -0
  193. package/telemetry/src/server/sourcemap.d.ts.map +1 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v0.26.0
2
+ * reroute-js v0.27.0
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2025 stewones <hi@stewan.io>
@@ -51,10 +51,29 @@ import {
51
51
  useState
52
52
  } from "react";
53
53
  import { jsx } from "react/jsx-runtime";
54
+ function deserializeIgnoreRoutes(serialized) {
55
+ if (!(serialized && Array.isArray(serialized)))
56
+ return;
57
+ return serialized.map((pattern) => {
58
+ if (pattern?.type === "string") {
59
+ return pattern.value;
60
+ }
61
+ if (pattern?.type === "regex") {
62
+ return new RegExp(pattern.value, pattern.flags);
63
+ }
64
+ if (pattern?.type === "function") {
65
+ return new Function(`return ${pattern.value}`)();
66
+ }
67
+ return pattern;
68
+ });
69
+ }
54
70
  function getBrowserTelemetryConfig() {
55
71
  if (typeof window !== "undefined") {
56
72
  const globalConfig = window.__REROUTE_TELEMETRY_BROWSER__;
57
73
  if (globalConfig) {
74
+ if (globalConfig.ignoreRoutes) {
75
+ globalConfig.ignoreRoutes = deserializeIgnoreRoutes(globalConfig.ignoreRoutes);
76
+ }
58
77
  return globalConfig;
59
78
  }
60
79
  }
@@ -78,10 +97,11 @@ function TelemetryProvider({
78
97
  enabled: enabled ?? globalConfig.enabled ?? false,
79
98
  serviceName: serviceName ?? globalConfig.serviceName ?? "reroute-app-browser",
80
99
  serviceVersion: serviceVersion ?? globalConfig.serviceVersion ?? "1.0.0",
81
- otlpEndpoint: otlpEndpoint ?? globalConfig.otlpEndpoint ?? "/api/telemetry",
100
+ otlpEndpoint: otlpEndpoint ?? globalConfig.otlpEndpoint ?? "/__reroute/telemetry",
82
101
  apiKey: apiKey ?? globalConfig.apiKey,
83
102
  environment: environment ?? globalConfig.environment ?? "development",
84
- enableConsoleCapture: enableConsoleCapture ?? globalConfig.enableConsoleCapture ?? true
103
+ enableConsoleCapture: enableConsoleCapture ?? globalConfig.enableConsoleCapture ?? true,
104
+ ignoreRoutes: globalConfig.ignoreRoutes
85
105
  }), [
86
106
  enabled,
87
107
  serviceName,
@@ -167,12 +187,97 @@ var init_api = __esm(() => {
167
187
  TelemetryContext = createContext(null);
168
188
  });
169
189
 
190
+ // packages/telemetry/src/react/context.ts
191
+ function setContext(attributes) {
192
+ contextAttributes = { ...contextAttributes, ...attributes };
193
+ }
194
+ function clearContext() {
195
+ contextAttributes = {};
196
+ }
197
+ function getContextAttr() {
198
+ return contextAttributes;
199
+ }
200
+ function getContextAttributesForTelemetry() {
201
+ const prefixed = {};
202
+ for (const [key, value] of Object.entries(contextAttributes)) {
203
+ prefixed[`context.${key}`] = value;
204
+ }
205
+ return prefixed;
206
+ }
207
+ var contextAttributes;
208
+ var init_context = __esm(() => {
209
+ contextAttributes = {};
210
+ });
211
+
170
212
  // packages/telemetry/src/react/telemetry.ts
213
+ function addBreadcrumb(category, message, data) {
214
+ breadcrumbs.push({
215
+ timestamp: Date.now(),
216
+ category,
217
+ message,
218
+ data
219
+ });
220
+ if (breadcrumbs.length > MAX_BREADCRUMBS) {
221
+ breadcrumbs.shift();
222
+ }
223
+ }
224
+ function addNetworkRequest(request) {
225
+ networkRequests.push(request);
226
+ if (networkRequests.length > MAX_NETWORK_REQUESTS) {
227
+ networkRequests.shift();
228
+ }
229
+ }
230
+ async function setupTraceContextFromServer() {
231
+ try {
232
+ const injectedContext = window.__REROUTE_TRACE_CONTEXT__;
233
+ if (!injectedContext?.traceparent) {
234
+ console.log("[browser-telemetry] No server trace context found - spans will start new traces");
235
+ return;
236
+ }
237
+ const parts = injectedContext.traceparent.split("-");
238
+ if (parts.length >= 3) {
239
+ serverTraceContext = {
240
+ traceId: parts[1],
241
+ spanId: parts[2],
242
+ traceparent: injectedContext.traceparent,
243
+ tracestate: injectedContext.tracestate
244
+ };
245
+ console.log("[browser-telemetry] Server trace context stored for correlation:", injectedContext.traceparent);
246
+ }
247
+ } catch (error) {
248
+ console.error("[browser-telemetry] Failed to extract server trace context:", error);
249
+ }
250
+ }
251
+ function shouldIgnoreUrl(url, method = "GET") {
252
+ if (ignorePatterns.length === 0)
253
+ return false;
254
+ let pathname;
255
+ try {
256
+ pathname = new URL(url, window.location.origin).pathname;
257
+ } catch {
258
+ pathname = url;
259
+ }
260
+ return ignorePatterns.some((pattern) => {
261
+ if (typeof pattern === "string") {
262
+ return pathname.includes(pattern) || url.includes(pattern);
263
+ }
264
+ if (pattern instanceof RegExp) {
265
+ return pattern.test(pathname) || pattern.test(url);
266
+ }
267
+ if (typeof pattern === "function") {
268
+ return pattern(pathname, method);
269
+ }
270
+ return false;
271
+ });
272
+ }
171
273
  async function initBrowserTelemetry(options = {}) {
172
274
  if (IS_SERVER2 || isInitialized) {
173
275
  return;
174
276
  }
175
277
  isInitialized = true;
278
+ if (options.ignoreRoutes) {
279
+ ignorePatterns = options.ignoreRoutes;
280
+ }
176
281
  try {
177
282
  const [
178
283
  { getWebAutoInstrumentations },
@@ -196,7 +301,7 @@ async function initBrowserTelemetry(options = {}) {
196
301
  const env = typeof import.meta !== "undefined" ? import.meta.env : undefined;
197
302
  const SERVICE_NAME = options.serviceName || "reroute-app-browser";
198
303
  const SERVICE_VERSION = options.serviceVersion || "1.0.0";
199
- const OTLP_ENDPOINT = options.otlpEndpoint || "/api/telemetry";
304
+ const OTLP_ENDPOINT = options.otlpEndpoint || "/__reroute/telemetry";
200
305
  const ENVIRONMENT = options.environment || env?.MODE || "development";
201
306
  const ENABLE_CONSOLE_CAPTURE = options.enableConsoleCapture ?? true;
202
307
  console.log(`[browser-telemetry] Initializing with endpoint: ${OTLP_ENDPOINT}`);
@@ -213,7 +318,7 @@ async function initBrowserTelemetry(options = {}) {
213
318
  [ATTR_SERVICE_NAME]: SERVICE_NAME,
214
319
  [ATTR_SERVICE_VERSION]: SERVICE_VERSION,
215
320
  "deployment.environment": ENVIRONMENT,
216
- "browser.user_agent": navigator.userAgent,
321
+ "browser.agent": navigator.userAgent,
217
322
  "browser.language": navigator.language,
218
323
  "browser.platform": navigator.platform,
219
324
  "screen.width": window.screen.width,
@@ -231,6 +336,7 @@ async function initBrowserTelemetry(options = {}) {
231
336
  tracerProvider.register({
232
337
  contextManager: new ZoneContextManager
233
338
  });
339
+ await setupTraceContextFromServer();
234
340
  registerInstrumentations({
235
341
  instrumentations: [
236
342
  getWebAutoInstrumentations({
@@ -243,12 +349,54 @@ async function initBrowserTelemetry(options = {}) {
243
349
  "@opentelemetry/instrumentation-fetch": {
244
350
  enabled: true,
245
351
  propagateTraceHeaderCorsUrls: [/.*/],
246
- clearTimingResources: true
352
+ clearTimingResources: true,
353
+ ignoreUrls: ignorePatterns.map((pattern) => {
354
+ if (typeof pattern === "string") {
355
+ return new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
356
+ }
357
+ if (pattern instanceof RegExp) {
358
+ return pattern;
359
+ }
360
+ return /.^/;
361
+ }),
362
+ applyCustomAttributesOnSpan: (span, request) => {
363
+ const url = request.url || "";
364
+ const method = request.method || "GET";
365
+ for (const pattern of ignorePatterns) {
366
+ if (typeof pattern === "function") {
367
+ if (shouldIgnoreUrl(url, method)) {
368
+ span.end();
369
+ return;
370
+ }
371
+ }
372
+ }
373
+ }
247
374
  },
248
375
  "@opentelemetry/instrumentation-xml-http-request": {
249
376
  enabled: true,
250
377
  propagateTraceHeaderCorsUrls: [/.*/],
251
- clearTimingResources: true
378
+ clearTimingResources: true,
379
+ ignoreUrls: ignorePatterns.map((pattern) => {
380
+ if (typeof pattern === "string") {
381
+ return new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
382
+ }
383
+ if (pattern instanceof RegExp) {
384
+ return pattern;
385
+ }
386
+ return /.^/;
387
+ }),
388
+ applyCustomAttributesOnSpan: (span, request) => {
389
+ const url = request.url || "";
390
+ const method = request.method || "GET";
391
+ for (const pattern of ignorePatterns) {
392
+ if (typeof pattern === "function") {
393
+ if (shouldIgnoreUrl(url, method)) {
394
+ span.end();
395
+ return;
396
+ }
397
+ }
398
+ }
399
+ }
252
400
  }
253
401
  })
254
402
  ]
@@ -257,22 +405,246 @@ async function initBrowserTelemetry(options = {}) {
257
405
  if (ENABLE_CONSOLE_CAPTURE) {
258
406
  setupConsoleCapture().catch((err) => console.error("[browser-telemetry] Console capture setup failed:", err));
259
407
  }
408
+ setupBreadcrumbTracking();
409
+ setupNetworkTracking();
260
410
  console.log("[browser-telemetry] Initialized successfully");
261
411
  } catch (error) {
262
412
  console.error("[browser-telemetry] Failed to initialize:", error);
263
413
  isInitialized = false;
264
414
  }
265
415
  }
416
+ function setupBreadcrumbTracking() {
417
+ if (IS_SERVER2)
418
+ return;
419
+ document.addEventListener("click", (event) => {
420
+ const target = event.target;
421
+ const tagName = target.tagName.toLowerCase();
422
+ const id = target.id ? `#${target.id}` : "";
423
+ const classes = target.className ? `.${target.className.split(" ").join(".")}` : "";
424
+ const text = target.textContent?.substring(0, 50) || "";
425
+ addBreadcrumb("ui.click", `Clicked ${tagName}${id}${classes}`, {
426
+ tag: tagName,
427
+ id: target.id,
428
+ text,
429
+ x: event.clientX,
430
+ y: event.clientY
431
+ });
432
+ }, { capture: true, passive: true });
433
+ const originalPushState = history.pushState;
434
+ const originalReplaceState = history.replaceState;
435
+ history.pushState = function(...args) {
436
+ addBreadcrumb("navigation", `Navigated to ${args[2]}`, {
437
+ url: String(args[2]),
438
+ type: "pushState"
439
+ });
440
+ return originalPushState.apply(this, args);
441
+ };
442
+ history.replaceState = function(...args) {
443
+ addBreadcrumb("navigation", `Replaced state: ${args[2]}`, {
444
+ url: String(args[2]),
445
+ type: "replaceState"
446
+ });
447
+ return originalReplaceState.apply(this, args);
448
+ };
449
+ window.addEventListener("popstate", () => {
450
+ addBreadcrumb("navigation", `Navigated to ${window.location.pathname}`, {
451
+ url: window.location.href,
452
+ type: "popstate"
453
+ });
454
+ });
455
+ document.addEventListener("submit", (event) => {
456
+ const form = event.target;
457
+ addBreadcrumb("ui.submit", `Form submitted: ${form.action || "unknown"}`, {
458
+ action: form.action,
459
+ method: form.method,
460
+ id: form.id
461
+ });
462
+ }, { capture: true, passive: true });
463
+ document.addEventListener("focus", (event) => {
464
+ const target = event.target;
465
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT") {
466
+ const input = target;
467
+ addBreadcrumb("ui.focus", `Focused ${input.type || input.tagName.toLowerCase()}`, {
468
+ tag: input.tagName.toLowerCase(),
469
+ type: input.type,
470
+ name: input.name,
471
+ id: input.id
472
+ });
473
+ }
474
+ }, { capture: true, passive: true });
475
+ console.log("[browser-telemetry] Breadcrumb tracking enabled");
476
+ }
477
+ function setupNetworkTracking() {
478
+ if (IS_SERVER2)
479
+ return;
480
+ const originalFetch = window.fetch;
481
+ window.fetch = async function(input, init) {
482
+ const startTime = Date.now();
483
+ const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
484
+ const method = init?.method || "GET";
485
+ const requestInfo = {
486
+ timestamp: startTime,
487
+ url,
488
+ method
489
+ };
490
+ try {
491
+ const response = await originalFetch.call(globalThis, input, init);
492
+ requestInfo.status = response.status;
493
+ requestInfo.duration = Date.now() - startTime;
494
+ requestInfo.error = response.status >= 400;
495
+ if (!shouldIgnoreUrl(url, method)) {
496
+ addNetworkRequest(requestInfo);
497
+ addBreadcrumb("http", `${method} ${url} → ${response.status}`, {
498
+ method,
499
+ url,
500
+ status: response.status,
501
+ duration: requestInfo.duration
502
+ });
503
+ }
504
+ return response;
505
+ } catch (error) {
506
+ requestInfo.duration = Date.now() - startTime;
507
+ requestInfo.error = true;
508
+ if (!shouldIgnoreUrl(url, method)) {
509
+ addNetworkRequest(requestInfo);
510
+ addBreadcrumb("http", `${method} ${url} → error`, {
511
+ method,
512
+ url,
513
+ error: error instanceof Error ? error.message : String(error),
514
+ duration: requestInfo.duration
515
+ });
516
+ }
517
+ throw error;
518
+ }
519
+ };
520
+ const originalXHROpen = XMLHttpRequest.prototype.open;
521
+ const originalXHRSend = XMLHttpRequest.prototype.send;
522
+ XMLHttpRequest.prototype.open = function(method, url, _async, _username, _password) {
523
+ this._telemetry = {
524
+ method,
525
+ url: String(url),
526
+ startTime: Date.now()
527
+ };
528
+ return originalXHROpen.apply(this);
529
+ };
530
+ XMLHttpRequest.prototype.send = function(body) {
531
+ const telemetry = this._telemetry;
532
+ if (telemetry) {
533
+ this.addEventListener("loadend", () => {
534
+ const duration = Date.now() - telemetry.startTime;
535
+ const requestInfo = {
536
+ timestamp: telemetry.startTime,
537
+ url: telemetry.url,
538
+ method: telemetry.method,
539
+ status: this.status,
540
+ duration,
541
+ error: this.status >= 400 || this.status === 0
542
+ };
543
+ if (!shouldIgnoreUrl(telemetry.url, telemetry.method)) {
544
+ addNetworkRequest(requestInfo);
545
+ addBreadcrumb("http", `${telemetry.method} ${telemetry.url} → ${this.status}`, {
546
+ method: telemetry.method,
547
+ url: telemetry.url,
548
+ status: this.status,
549
+ duration
550
+ });
551
+ }
552
+ });
553
+ }
554
+ return originalXHRSend.call(this, body);
555
+ };
556
+ console.log("[browser-telemetry] Network tracking enabled");
557
+ }
558
+ function getPerformanceMetrics() {
559
+ if (IS_SERVER2)
560
+ return {};
561
+ const metrics = {};
562
+ const memory = performance.memory;
563
+ if (memory) {
564
+ metrics["perf.memory.heap"] = memory.usedJSHeapSize;
565
+ metrics["perf.memory.total"] = memory.totalJSHeapSize;
566
+ metrics["perf.memory.limit"] = memory.jsHeapSizeLimit;
567
+ metrics["perf.memory.usage"] = Math.round(memory.usedJSHeapSize / memory.jsHeapSizeLimit * 100);
568
+ }
569
+ const navTiming = performance.timing;
570
+ if (navTiming) {
571
+ metrics["perf.timing"] = Date.now() - navTiming.navigationStart;
572
+ }
573
+ const connection = navigator.connection;
574
+ if (connection) {
575
+ metrics["perf.connection.type"] = connection.effectiveType;
576
+ metrics["perf.connection.downlink"] = connection.downlink;
577
+ metrics["perf.connection.rtt"] = connection.rtt;
578
+ metrics["perf.connection.save.data"] = connection.saveData;
579
+ }
580
+ metrics["perf.hardware.concurrency"] = navigator.hardwareConcurrency;
581
+ metrics["perf.device.memory"] = navigator.deviceMemory;
582
+ metrics["perf.viewport.width"] = window.innerWidth;
583
+ metrics["perf.viewport.height"] = window.innerHeight;
584
+ return metrics;
585
+ }
586
+ function getErrorContext() {
587
+ const context = {};
588
+ if (breadcrumbs.length > 0) {
589
+ context["context.journey"] = JSON.stringify(breadcrumbs);
590
+ context["context.journey.count"] = breadcrumbs.length;
591
+ context["context.last.action"] = breadcrumbs[breadcrumbs.length - 1]?.message;
592
+ }
593
+ if (networkRequests.length > 0) {
594
+ context["context.network.requests"] = JSON.stringify(networkRequests);
595
+ context["context.network.requests.count"] = networkRequests.length;
596
+ const failedRequests = networkRequests.filter((r) => r.error);
597
+ if (failedRequests.length > 0) {
598
+ context["context.network.failed.count"] = failedRequests.length;
599
+ context["context.network.failed.last"] = failedRequests[failedRequests.length - 1]?.url;
600
+ }
601
+ }
602
+ const perfMetrics = getPerformanceMetrics();
603
+ Object.assign(context, perfMetrics);
604
+ const sessionAttrs = getContextAttributesForTelemetry();
605
+ Object.assign(context, sessionAttrs);
606
+ return context;
607
+ }
266
608
  async function setupErrorHandlers() {
267
609
  const { trace, SpanStatusCode } = await import("@opentelemetry/api");
268
610
  const tracer = trace.getTracer("error-handler");
269
- window.addEventListener("error", (event) => {
611
+ window.addEventListener("error", async (event) => {
270
612
  try {
613
+ const links = [];
614
+ if (serverTraceContext) {
615
+ links.push({
616
+ context: {
617
+ traceId: serverTraceContext.traceId,
618
+ spanId: serverTraceContext.spanId,
619
+ traceFlags: 1
620
+ },
621
+ attributes: {
622
+ "link.type": "server_request"
623
+ }
624
+ });
625
+ }
271
626
  const span = tracer.startSpan("browser.error.uncaught", {
272
- startTime: Date.now()
627
+ startTime: Date.now(),
628
+ links
273
629
  });
274
630
  const stackTrace = event.error?.stack || "";
275
631
  const errorMessage = event.message || event.error?.message || "Unknown error";
632
+ let mappedStack = stackTrace;
633
+ if (stackTrace) {
634
+ try {
635
+ const response = await fetch("/__reroute/telemetry/inspect", {
636
+ method: "POST",
637
+ headers: { "Content-Type": "application/json" },
638
+ body: JSON.stringify({ stack: stackTrace })
639
+ });
640
+ if (response.ok) {
641
+ const result = await response.json();
642
+ if (result.mapped) {
643
+ mappedStack = result.mapped;
644
+ }
645
+ }
646
+ } catch {}
647
+ }
276
648
  span.setStatus({
277
649
  code: SpanStatusCode.ERROR,
278
650
  message: errorMessage
@@ -282,20 +654,31 @@ async function setupErrorHandlers() {
282
654
  "error.type": event.error?.name || "UncaughtError",
283
655
  "error.message": errorMessage,
284
656
  "error.stack": stackTrace,
657
+ ...mappedStack !== stackTrace ? {
658
+ "error.stack.decoded": mappedStack
659
+ } : {},
285
660
  "error.filename": event.filename || "",
286
661
  "error.lineno": event.lineno || 0,
287
662
  "error.colno": event.colno || 0,
288
663
  "browser.url": window.location.href,
289
664
  "browser.pathname": window.location.pathname,
290
- "browser.user_agent": navigator.userAgent,
291
- "browser.timestamp": new Date().toISOString()
665
+ "browser.agent": navigator.userAgent,
666
+ "browser.timestamp": new Date().toISOString(),
667
+ ...serverTraceContext ? {
668
+ "server.trace_id": serverTraceContext.traceId,
669
+ "server.span_id": serverTraceContext.spanId
670
+ } : {},
671
+ ...getErrorContext()
292
672
  });
293
673
  if (event.error) {
294
- span.recordException(event.error);
674
+ const mappedError = new Error(event.error.message);
675
+ mappedError.name = event.error.name;
676
+ mappedError.stack = mappedStack;
677
+ span.recordException(mappedError);
295
678
  span.addEvent("exception", {
296
679
  "exception.type": event.error.name,
297
680
  "exception.message": event.error.message,
298
- "exception.stacktrace": stackTrace,
681
+ "exception.stacktrace": mappedStack,
299
682
  "exception.escaped": "false"
300
683
  });
301
684
  }
@@ -305,15 +688,45 @@ async function setupErrorHandlers() {
305
688
  console.error("[browser-telemetry] Error tracking failed:", telemetryError);
306
689
  }
307
690
  });
308
- window.addEventListener("unhandledrejection", (event) => {
691
+ window.addEventListener("unhandledrejection", async (event) => {
309
692
  try {
693
+ const links = [];
694
+ if (serverTraceContext) {
695
+ links.push({
696
+ context: {
697
+ traceId: serverTraceContext.traceId,
698
+ spanId: serverTraceContext.spanId,
699
+ traceFlags: 1
700
+ },
701
+ attributes: {
702
+ "link.type": "server_request"
703
+ }
704
+ });
705
+ }
310
706
  const span = tracer.startSpan("browser.error.unhandled_rejection", {
311
- startTime: Date.now()
707
+ startTime: Date.now(),
708
+ links
312
709
  });
313
710
  const isError = event.reason instanceof Error;
314
711
  const errorMessage = isError ? event.reason.message : String(event.reason);
315
712
  const errorStack = isError ? event.reason.stack || "" : "";
316
713
  const errorType = isError ? event.reason.name : "UnhandledRejection";
714
+ let mappedStack = errorStack;
715
+ if (errorStack) {
716
+ try {
717
+ const response = await fetch("/__reroute/telemetry/inspect", {
718
+ method: "POST",
719
+ headers: { "Content-Type": "application/json" },
720
+ body: JSON.stringify({ stack: errorStack })
721
+ });
722
+ if (response.ok) {
723
+ const result = await response.json();
724
+ if (result.mapped) {
725
+ mappedStack = result.mapped;
726
+ }
727
+ }
728
+ } catch {}
729
+ }
317
730
  span.setStatus({
318
731
  code: SpanStatusCode.ERROR,
319
732
  message: errorMessage
@@ -323,17 +736,28 @@ async function setupErrorHandlers() {
323
736
  "error.type": errorType,
324
737
  "error.message": errorMessage,
325
738
  "error.stack": errorStack,
739
+ ...mappedStack !== errorStack ? {
740
+ "error.stack.decoded": mappedStack
741
+ } : {},
326
742
  "browser.url": window.location.href,
327
743
  "browser.pathname": window.location.pathname,
328
- "browser.user_agent": navigator.userAgent,
329
- "browser.timestamp": new Date().toISOString()
744
+ "browser.agent": navigator.userAgent,
745
+ "browser.timestamp": new Date().toISOString(),
746
+ ...serverTraceContext ? {
747
+ "server.trace_id": serverTraceContext.traceId,
748
+ "server.span_id": serverTraceContext.spanId
749
+ } : {},
750
+ ...getErrorContext()
330
751
  });
331
752
  if (isError) {
332
- span.recordException(event.reason);
753
+ const mappedError = new Error(event.reason.message);
754
+ mappedError.name = event.reason.name;
755
+ mappedError.stack = mappedStack;
756
+ span.recordException(mappedError);
333
757
  span.addEvent("exception", {
334
758
  "exception.type": event.reason.name,
335
759
  "exception.message": event.reason.message,
336
- "exception.stacktrace": errorStack,
760
+ "exception.stacktrace": mappedStack,
337
761
  "exception.escaped": "false"
338
762
  });
339
763
  }
@@ -353,12 +777,29 @@ async function setupConsoleCapture() {
353
777
  }
354
778
  const wrappedError = (...args) => {
355
779
  try {
356
- const span = tracer.startSpan("browser.console.error");
780
+ const links = [];
781
+ if (serverTraceContext) {
782
+ links.push({
783
+ context: {
784
+ traceId: serverTraceContext.traceId,
785
+ spanId: serverTraceContext.spanId,
786
+ traceFlags: 1
787
+ },
788
+ attributes: {
789
+ "link.type": "server_request"
790
+ }
791
+ });
792
+ }
793
+ const span = tracer.startSpan("browser.console.error", { links });
357
794
  span.setAttributes({
358
795
  "log.level": "error",
359
796
  "log.message": args.map(String).join(" "),
360
797
  "browser.url": window.location.href,
361
- "browser.timestamp": new Date().toISOString()
798
+ "browser.timestamp": new Date().toISOString(),
799
+ ...serverTraceContext ? {
800
+ "server.trace_id": serverTraceContext.traceId,
801
+ "server.span_id": serverTraceContext.spanId
802
+ } : {}
362
803
  });
363
804
  span.end();
364
805
  } catch {}
@@ -382,11 +823,26 @@ function createSpan(name, attributes = {}) {
382
823
  globalThis.__OTEL_TRACE__ = trace;
383
824
  }
384
825
  const tracer = trace.getTracer("custom");
385
- const span = tracer.startSpan(name);
826
+ const links = [];
827
+ if (serverTraceContext) {
828
+ links.push({
829
+ context: {
830
+ traceId: serverTraceContext.traceId,
831
+ spanId: serverTraceContext.spanId,
832
+ traceFlags: 1
833
+ },
834
+ attributes: {
835
+ "link.type": "server_request",
836
+ "link.traceparent": serverTraceContext.traceparent
837
+ }
838
+ });
839
+ }
840
+ const span = tracer.startSpan(name, { links });
386
841
  span.setAttributes({
387
842
  ...attributes,
388
843
  "browser.url": window.location.href,
389
- "browser.pathname": window.location.pathname
844
+ "browser.pathname": window.location.pathname,
845
+ ...serverTraceContext ? { "server.trace_id": serverTraceContext.traceId } : {}
390
846
  });
391
847
  return span;
392
848
  } catch (error) {
@@ -410,15 +866,44 @@ function trackEvent(eventName, attributes = {}) {
410
866
  console.error("[browser-telemetry] Failed to track event:", error);
411
867
  }
412
868
  }
413
- function trackError(error, context = {}) {
869
+ async function trackError(error, context = {}) {
414
870
  if (IS_SERVER2 || !isInitialized) {
415
871
  return;
416
872
  }
417
873
  try {
418
874
  const { trace, SpanStatusCode } = __require("@opentelemetry/api");
419
875
  const tracer = trace.getTracer("error-handler");
420
- const span = tracer.startSpan("browser.error.tracked");
876
+ const links = [];
877
+ if (serverTraceContext) {
878
+ links.push({
879
+ context: {
880
+ traceId: serverTraceContext.traceId,
881
+ spanId: serverTraceContext.spanId,
882
+ traceFlags: 1
883
+ },
884
+ attributes: {
885
+ "link.type": "server_request"
886
+ }
887
+ });
888
+ }
889
+ const span = tracer.startSpan("browser.error.tracked", { links });
421
890
  const stackTrace = error.stack || "";
891
+ let mappedStack = stackTrace;
892
+ if (stackTrace) {
893
+ try {
894
+ const response = await fetch("/__reroute/telemetry/inspect", {
895
+ method: "POST",
896
+ headers: { "Content-Type": "application/json" },
897
+ body: JSON.stringify({ stack: stackTrace })
898
+ });
899
+ if (response.ok) {
900
+ const result = await response.json();
901
+ if (result.mapped) {
902
+ mappedStack = result.mapped;
903
+ }
904
+ }
905
+ } catch {}
906
+ }
422
907
  span.setStatus({
423
908
  code: SpanStatusCode.ERROR,
424
909
  message: error.message
@@ -428,16 +913,27 @@ function trackError(error, context = {}) {
428
913
  "error.type": error.name,
429
914
  "error.message": error.message,
430
915
  "error.stack": stackTrace,
916
+ ...mappedStack !== stackTrace ? {
917
+ "error.stack.decoded": mappedStack
918
+ } : {},
431
919
  ...context,
432
920
  "browser.url": window.location.href,
433
921
  "browser.pathname": window.location.pathname,
434
- "browser.timestamp": new Date().toISOString()
922
+ "browser.timestamp": new Date().toISOString(),
923
+ ...serverTraceContext ? {
924
+ "server.trace_id": serverTraceContext.traceId,
925
+ "server.span_id": serverTraceContext.spanId
926
+ } : {},
927
+ ...getErrorContext()
435
928
  });
436
- span.recordException(error);
929
+ const mappedError = new Error(error.message);
930
+ mappedError.name = error.name;
931
+ mappedError.stack = mappedStack;
932
+ span.recordException(mappedError);
437
933
  span.addEvent("exception", {
438
934
  "exception.type": error.name,
439
935
  "exception.message": error.message,
440
- "exception.stacktrace": stackTrace,
936
+ "exception.stacktrace": mappedStack,
441
937
  "exception.escaped": "false"
442
938
  });
443
939
  span.end();
@@ -452,14 +948,19 @@ async function shutdownTelemetry() {
452
948
  console.log("[browser-telemetry] Shut down successfully");
453
949
  }
454
950
  }
455
- var IS_SERVER2, isInitialized = false, tracerProvider = null;
951
+ var IS_SERVER2, isInitialized = false, tracerProvider = null, serverTraceContext = null, ignorePatterns, breadcrumbs, MAX_BREADCRUMBS = 20, networkRequests, MAX_NETWORK_REQUESTS = 15;
456
952
  var init_telemetry = __esm(() => {
953
+ init_context();
457
954
  IS_SERVER2 = typeof window === "undefined";
955
+ ignorePatterns = [];
956
+ breadcrumbs = [];
957
+ networkRequests = [];
458
958
  });
459
959
 
460
960
  // packages/telemetry/src/react/index.ts
461
961
  var init_react = __esm(() => {
462
962
  init_api();
963
+ init_context();
463
964
  init_telemetry();
464
965
  });
465
966
 
@@ -470,8 +971,12 @@ __export(exports_react, {
470
971
  trackEvent: () => trackEvent,
471
972
  trackError: () => trackError,
472
973
  shutdownTelemetry: () => shutdownTelemetry,
974
+ setContext: () => setContext,
473
975
  initBrowserTelemetry: () => initBrowserTelemetry,
976
+ getContextAttributesForTelemetry: () => getContextAttributesForTelemetry,
977
+ getContextAttr: () => getContextAttr,
474
978
  createSpan: () => createSpan,
979
+ clearContext: () => clearContext,
475
980
  TelemetryProvider: () => TelemetryProvider
476
981
  });
477
982
  var init_react2 = __esm(() => {
@@ -484,9 +989,13 @@ export {
484
989
  trackEvent,
485
990
  trackError,
486
991
  shutdownTelemetry,
992
+ setContext,
487
993
  initBrowserTelemetry,
994
+ getContextAttributesForTelemetry,
995
+ getContextAttr,
488
996
  createSpan,
997
+ clearContext,
489
998
  TelemetryProvider
490
999
  };
491
1000
 
492
- //# debugId=EF6D54D3079D2BAE64756E2164756E21
1001
+ //# debugId=523E68D56D72B13164756E2164756E21