@obtrace/browser 2.4.1 → 2.5.1

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.
@@ -13,7 +13,6 @@ import { installResourceTiming } from "./resources";
13
13
  import { installLongTaskDetection } from "./longtasks";
14
14
  import { installMemoryTracking } from "./memory";
15
15
  import { installOfflineSupport } from "./offline";
16
- import { installSupabaseFetchInterceptor } from "./supabase-intercept";
17
16
  const instances = new Set();
18
17
  const replayBuffers = new Set();
19
18
  let currentUser = null;
@@ -216,7 +215,9 @@ export function initBrowserSDK(config) {
216
215
  cleanups.push(installResourceTiming(meter));
217
216
  cleanups.push(installLongTaskDetection(tracer));
218
217
  cleanups.push(installMemoryTracking(meter));
219
- cleanups.push(installSupabaseFetchInterceptor(tracer, replay.sessionId));
218
+ // supabase-intercept removed: child spans are now created inside
219
+ // FetchInstrumentation's applyCustomAttributesOnSpan callback so all
220
+ // spans share the same traceId (single connected trace per request).
220
221
  if (config.captureConsole !== false) {
221
222
  cleanups.push(installConsoleCapture(tracer, logger, replay.sessionId));
222
223
  }
@@ -29722,13 +29722,59 @@ function setupOtelWeb(config) {
29722
29722
  });
29723
29723
  const ingestPattern = new RegExp(`^${baseUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`);
29724
29724
  const instrumentations = [];
29725
- const applySupabaseAttrs = (span, req, _result) => {
29725
+ const sessionId = config.sessionId || "";
29726
+ const applySupabaseAttrs = (parentSpan, req, result2) => {
29726
29727
  try {
29727
29728
  const url = typeof req === "string" ? req : req instanceof URL ? req.href : req?.url || "";
29728
29729
  const method = req?.method || "GET";
29729
- if (url && isSupabaseURL(url)) {
29730
- enrichSupabaseSpan(span, url, method);
29731
- }
29730
+ if (!url || !isSupabaseURL(url)) return;
29731
+ enrichSupabaseSpan(parentSpan, url, method);
29732
+ if (sessionId) parentSpan.setAttribute("session.id", sessionId);
29733
+ const parsed = parseSupabaseURL(url, method);
29734
+ if (!parsed) return;
29735
+ const status = typeof result2?.status === "number" ? result2.status : 0;
29736
+ const t = trace.getTracer("@obtrace/sdk-browser", "2.5.1");
29737
+ const synth = { "session.id": sessionId, "supabase.ref": parsed.ref, "span.synthetic": "true" };
29738
+ const parentCtx = trace.setSpan(ROOT_CONTEXT, parentSpan);
29739
+ context.with(parentCtx, () => {
29740
+ const gw = t.startSpan("supabase.gateway", {
29741
+ attributes: { ...synth, "http.method": method.toUpperCase(), "http.status_code": status, "peer.service": "supabase.kong" }
29742
+ });
29743
+ const gwCtx = trace.setSpan(ROOT_CONTEXT, gw);
29744
+ context.with(gwCtx, () => {
29745
+ if (parsed.service === "postgrest") {
29746
+ const db2 = t.startSpan("supabase.db.query", {
29747
+ attributes: { ...synth, "db.system": "postgresql", "db.operation": parsed.operation, "db.sql.table": parsed.table, "db.statement": parsed.detail, "peer.service": "supabase.postgresql" }
29748
+ });
29749
+ db2.setStatus({ code: status >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK });
29750
+ db2.end();
29751
+ }
29752
+ if (parsed.service === "auth") {
29753
+ const auth = t.startSpan("supabase.auth." + parsed.operation, {
29754
+ attributes: { ...synth, "auth.operation": parsed.operation, "peer.service": "supabase.gotrue" }
29755
+ });
29756
+ auth.setStatus({ code: status >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK });
29757
+ auth.end();
29758
+ }
29759
+ if (parsed.service === "storage") {
29760
+ const stor = t.startSpan("supabase.storage." + parsed.operation, {
29761
+ attributes: { ...synth, "storage.operation": parsed.operation, "peer.service": "supabase.storage" }
29762
+ });
29763
+ stor.setStatus({ code: status >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK });
29764
+ stor.end();
29765
+ }
29766
+ if (parsed.service === "edge-function") {
29767
+ const fnName = parsed.operation.replace("invoke:", "");
29768
+ const fn = t.startSpan("supabase.function." + fnName, {
29769
+ attributes: { ...synth, "faas.name": fnName, "faas.trigger": "http", "peer.service": "supabase.edge-runtime" }
29770
+ });
29771
+ fn.setStatus({ code: status >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK });
29772
+ fn.end();
29773
+ }
29774
+ });
29775
+ gw.setStatus({ code: status >= 400 ? SpanStatusCode.ERROR : SpanStatusCode.OK });
29776
+ gw.end();
29777
+ });
29732
29778
  } catch {
29733
29779
  }
29734
29780
  };
@@ -30429,127 +30475,6 @@ function installMemoryTracking(meter) {
30429
30475
  return () => clearInterval(timer);
30430
30476
  }
30431
30477
 
30432
- // src/browser/supabase-intercept.ts
30433
- function installSupabaseFetchInterceptor(tracer, sessionId) {
30434
- if (typeof window === "undefined" || typeof window.fetch === "undefined") return () => {
30435
- };
30436
- const originalFetch = window.fetch;
30437
- window.fetch = async function(input2, init) {
30438
- const url = typeof input2 === "string" ? input2 : input2 instanceof URL ? input2.href : input2 instanceof Request ? input2.url : "";
30439
- if (!url || !isSupabaseURL(url)) {
30440
- return originalFetch.call(this, input2, init);
30441
- }
30442
- const method = init?.method || (input2 instanceof Request ? input2.method : "GET") || "GET";
30443
- const parsed = parseSupabaseURL(url, method);
30444
- if (!parsed) {
30445
- return originalFetch.call(this, input2, init);
30446
- }
30447
- const rootSpan = tracer.startSpan(`supabase.${parsed.service} ${parsed.detail}`, {
30448
- attributes: {
30449
- "supabase.ref": parsed.ref,
30450
- "supabase.service": parsed.service,
30451
- "supabase.operation": parsed.operation,
30452
- "supabase.detail": parsed.detail,
30453
- "http.method": method.toUpperCase(),
30454
- "http.url": url.split("?")[0],
30455
- "peer.service": `supabase.${parsed.service}`,
30456
- "session.id": sessionId,
30457
- ...parsed.service === "postgrest" ? {
30458
- "db.system": "postgresql",
30459
- "db.operation": parsed.operation,
30460
- "db.sql.table": parsed.table
30461
- } : {}
30462
- }
30463
- });
30464
- const rootCtx = trace.setSpan(context.active(), rootSpan);
30465
- const startMs = performance.now();
30466
- try {
30467
- const response = await originalFetch.call(this, input2, init);
30468
- const durationMs = performance.now() - startMs;
30469
- rootSpan.setAttribute("http.status_code", response.status);
30470
- rootSpan.setAttribute("supabase.duration_ms", Math.round(durationMs));
30471
- context.with(rootCtx, () => {
30472
- createChildSpans(tracer, parsed, method, response.status, durationMs, sessionId);
30473
- });
30474
- if (response.status >= 400) {
30475
- rootSpan.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${response.status}` });
30476
- addBreadcrumb({ timestamp: Date.now(), category: "supabase", message: `${parsed.detail} \u2192 ${response.status}`, level: "error" });
30477
- } else {
30478
- rootSpan.setStatus({ code: SpanStatusCode.OK });
30479
- addBreadcrumb({ timestamp: Date.now(), category: "supabase", message: `${parsed.detail} \u2192 ${response.status} (${Math.round(durationMs)}ms)`, level: "info" });
30480
- }
30481
- rootSpan.end();
30482
- return response;
30483
- } catch (err) {
30484
- rootSpan.setStatus({ code: SpanStatusCode.ERROR, message: err instanceof Error ? err.message : "fetch failed" });
30485
- if (err instanceof Error) rootSpan.recordException(err);
30486
- rootSpan.end();
30487
- addBreadcrumb({ timestamp: Date.now(), category: "supabase", message: `${parsed.detail} \u2192 FAILED`, level: "error" });
30488
- throw err;
30489
- }
30490
- };
30491
- return () => {
30492
- window.fetch = originalFetch;
30493
- };
30494
- }
30495
- function createChildSpans(tracer, parsed, method, status, _durationMs, sessionId) {
30496
- const synth = { "session.id": sessionId, "supabase.ref": parsed.ref, "span.synthetic": "true" };
30497
- const gatewaySpan = tracer.startSpan("supabase.gateway", {
30498
- attributes: {
30499
- ...synth,
30500
- "http.method": method.toUpperCase(),
30501
- "http.status_code": status,
30502
- "peer.service": "supabase.kong"
30503
- }
30504
- });
30505
- const gatewayCtx = trace.setSpan(context.active(), gatewaySpan);
30506
- context.with(gatewayCtx, () => {
30507
- if (parsed.service === "postgrest") {
30508
- const dbSpan = tracer.startSpan("supabase.db.query", {
30509
- attributes: {
30510
- ...synth,
30511
- "db.system": "postgresql",
30512
- "db.operation": parsed.operation,
30513
- "db.sql.table": parsed.table,
30514
- "db.statement": parsed.detail,
30515
- "peer.service": "supabase.postgresql"
30516
- }
30517
- });
30518
- if (status >= 400) dbSpan.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${status}` });
30519
- else dbSpan.setStatus({ code: SpanStatusCode.OK });
30520
- dbSpan.end();
30521
- }
30522
- if (parsed.service === "auth") {
30523
- const authSpan = tracer.startSpan("supabase.auth." + parsed.operation, {
30524
- attributes: { ...synth, "auth.operation": parsed.operation, "peer.service": "supabase.gotrue" }
30525
- });
30526
- if (status >= 400) authSpan.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${status}` });
30527
- else authSpan.setStatus({ code: SpanStatusCode.OK });
30528
- authSpan.end();
30529
- }
30530
- if (parsed.service === "storage") {
30531
- const storageSpan = tracer.startSpan("supabase.storage." + parsed.operation, {
30532
- attributes: { ...synth, "storage.operation": parsed.operation, "peer.service": "supabase.storage" }
30533
- });
30534
- if (status >= 400) storageSpan.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${status}` });
30535
- else storageSpan.setStatus({ code: SpanStatusCode.OK });
30536
- storageSpan.end();
30537
- }
30538
- if (parsed.service === "edge-function") {
30539
- const fnName = parsed.operation.replace("invoke:", "");
30540
- const fnSpan = tracer.startSpan("supabase.function." + fnName, {
30541
- attributes: { ...synth, "faas.name": fnName, "faas.trigger": "http", "peer.service": "supabase.edge-runtime" }
30542
- });
30543
- if (status >= 400) fnSpan.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${status}` });
30544
- else fnSpan.setStatus({ code: SpanStatusCode.OK });
30545
- fnSpan.end();
30546
- }
30547
- });
30548
- if (status >= 400) gatewaySpan.setStatus({ code: SpanStatusCode.ERROR, message: `HTTP ${status}` });
30549
- else gatewaySpan.setStatus({ code: SpanStatusCode.OK });
30550
- gatewaySpan.end();
30551
- }
30552
-
30553
30478
  // src/browser/index.ts
30554
30479
  var instances = /* @__PURE__ */ new Set();
30555
30480
  var replayBuffers = /* @__PURE__ */ new Set();
@@ -30727,7 +30652,6 @@ function initBrowserSDK(config) {
30727
30652
  cleanups.push(installResourceTiming(meter));
30728
30653
  cleanups.push(installLongTaskDetection(tracer));
30729
30654
  cleanups.push(installMemoryTracking(meter));
30730
- cleanups.push(installSupabaseFetchInterceptor(tracer, replay.sessionId));
30731
30655
  if (config.captureConsole !== false) {
30732
30656
  cleanups.push(installConsoleCapture(tracer, logger, replay.sessionId));
30733
30657
  }