mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
docs: update client-side tracing and Edge Function CORS guides (#48924)
Updates the client-side tracing and Edge Function CORS docs for changes shipping in `@supabase/supabase-js` v2.112.3 (supabase/supabase-js#2603, supabase/supabase-js#2604). The tracing guide gains a vendor compatibility table (plain OpenTelemetry works as is, Sentry needs `propagateTraceparent: true`, Datadog RUM needs `allowedTracingUrls`), the new `respectSamplingDecision` semantics (non-sampled requests now carry `traceparent` only, so logs stay correlatable), a troubleshooting entry for the SDK's new propagator warning, and a note that browser calls to Edge Functions need the trace headers in the function's CORS allow-list. The CORS guide now states explicitly that trace headers are sent only when trace propagation is opted in (never by default), adds a table of when each SDK header is actually sent, and the hardcoded `corsHeaders` examples are updated to the full header list. Should merge after the v2.112.3 release is published, since it documents that version's behavior. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Expanded CORS guidance with trace-propagation requirements and SDK version considerations. * Added browser and Edge Function setup guidance for client-side tracing. * Documented updated sampling behavior, advanced configuration, vendor setup examples, and troubleshooting. * **Bug Fixes** * Updated CORS configurations to allow retry and tracing headers required for supported requests. * Improved compatibility for browser requests that transmit distributed tracing context. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
4587d177c3
commit
fc5db9bb03
4 files changed
+53
-15
No files matched your search
@@ -55,16 +55,34 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
This approach ensures that when new headers are added to the Supabase SDK, your Edge Functions automatically include them, preventing CORS errors.
|
||||
Importing from the SDK keeps your allow-list aligned with the headers the client libraries send: when you upgrade the SDK version in your function and redeploy, newly added headers are picked up with it. As of `@supabase/supabase-js` v2.112.3 the list includes the trace context headers (`traceparent`, `tracestate`, `baggage`) used by [client-side tracing](/docs/guides/monitoring-and-debugging/client-side-tracing) — functions deployed with an older version need a redeploy before browsers can call them with trace propagation enabled.
|
||||
|
||||
<Admonition type="note">
|
||||
|
||||
The allow-list only states what a browser _may_ send — it doesn't change what the SDK sends. Trace context headers are sent exclusively by clients that explicitly opt in to trace propagation (`tracePropagation: true`, disabled by default). Clients that haven't opted in send exactly the same headers as before.
|
||||
|
||||
</Admonition>
|
||||
|
||||
The full list, and when each header is sent:
|
||||
|
||||
| Header | Sent |
|
||||
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `authorization` | Every request (session token or API key) |
|
||||
| `apikey` | Every request |
|
||||
| `x-client-info` | Every request (SDK name and version) |
|
||||
| `content-type` | Requests with a body |
|
||||
| `x-retry-count` | Only on automatic retry attempts (`postgrest-js` retries failed idempotent requests by default) |
|
||||
| `traceparent`, `tracestate`, `baggage` | **Only when [trace propagation](/docs/guides/monitoring-and-debugging/client-side-tracing) is explicitly enabled** — never by default |
|
||||
|
||||
### For versions before 2.95.0
|
||||
|
||||
If you're using `@supabase/supabase-js` before v2.95.0, you'll need to hardcode the CORS headers. Add a `cors.ts` file within a [`_shared` folder](/docs/guides/functions/development-environment#recommended-project-structure):
|
||||
If you're using `@supabase/supabase-js` before v2.95.0, you'll need to hardcode the CORS headers. Add a `cors.ts` file within a [`_shared` folder](/docs/guides/functions/development-environment#recommended-project-structure). The list must cover every header your calling clients send — include the trace context headers if any client enables `tracePropagation`:
|
||||
|
||||
```ts _shared/cors.ts
|
||||
export const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
'Access-Control-Allow-Headers':
|
||||
'authorization, x-client-info, apikey, content-type, x-retry-count, traceparent, tracestate, baggage',
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ description: 'Propagate W3C trace context from the Supabase JS, Swift, and Dart
|
||||
|
||||
The Supabase JS, Swift, and Dart SDKs can attach [W3C Trace Context](https://www.w3.org/TR/trace-context/) headers (`traceparent`, `tracestate`, `baggage`) to outgoing requests. The resulting `trace_id` flows through Supabase services and appears in API Gateway and Edge Function logs, so you can correlate client-side spans with the server-side logs they produced — end-to-end, across the network boundary.
|
||||
|
||||
Because the headers follow the W3C standard, any compliant tracing SDK (such as OpenTelemetry, Sentry, Datadog, or Honeycomb) can pick up the trace on the server side, including in self-hosted collectors.
|
||||
Because the headers follow the W3C standard, any compliant tracing SDK (such as OpenTelemetry, Sentry, Datadog, or Honeycomb) can pick up the trace on the server side, including in self-hosted collectors. On the client side, some vendor SDKs need a small configuration change before they emit the standard headers — see [Using a vendor tracing SDK](#using-a-vendor-tracing-sdk) in the JavaScript tab.
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
@@ -71,6 +71,12 @@ await tracer.startActiveSpan('fetch-users', async (span) => {
|
||||
|
||||
For security, trace headers are only attached to requests targeting Supabase domains (`*.supabase.co`, `*.supabase.in`, and `localhost` for local development). Third-party hosts called through a custom `fetch` are never tagged.
|
||||
|
||||
<Admonition type="note">
|
||||
|
||||
Calling Edge Functions from the browser with trace propagation enabled requires the function's CORS allow-list to include the trace headers. In the function, import `corsHeaders` from `npm:@supabase/supabase-js@^2.112.3/cors` or add `traceparent`, `tracestate`, and `baggage` to your own allow-list, then redeploy the function. See [CORS support for Edge Functions](/docs/guides/functions/cors).
|
||||
|
||||
</Admonition>
|
||||
|
||||
## Advanced configuration
|
||||
|
||||
Pass an object instead of `true` for fine-grained control:
|
||||
@@ -81,22 +87,33 @@ import '@supabase/supabase-js/tracing'
|
||||
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY, {
|
||||
tracePropagation: {
|
||||
enabled: true,
|
||||
// Default: true. When false, headers are attached even if the
|
||||
// upstream trace is not sampled — useful when you want every
|
||||
// Supabase request tagged with a trace_id for log correlation.
|
||||
// Default: true. Non-sampled requests carry only `traceparent` (with the
|
||||
// sampled flag preserved, so nothing is recorded downstream) — log
|
||||
// correlation keeps working while `tracestate` and `baggage` are withheld.
|
||||
// Set to false to always send the full trace context regardless of sampling.
|
||||
respectSamplingDecision: false,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ------------------------- | --------- | ------- | ------------------------------------------------------------------- |
|
||||
| `enabled` | `boolean` | `false` | Enable trace propagation. |
|
||||
| `respectSamplingDecision` | `boolean` | `true` | If `true`, skip propagation when the upstream trace is not sampled. |
|
||||
| Option | Type | Default | Description |
|
||||
| ------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `enabled` | `boolean` | `false` | Enable trace propagation. |
|
||||
| `respectSamplingDecision` | `boolean` | `true` | When `true`, non-sampled requests send only `traceparent` (sampled flag preserved) and omit `tracestate` and `baggage`; `false` always sends the full trace context. On versions before `2.112.3`, `true` skipped all trace headers for non-sampled requests. |
|
||||
|
||||
## Using a vendor tracing SDK
|
||||
|
||||
Many tracing SDKs are built on top of OpenTelemetry. They work with this guide as long as a W3C-compliant propagator is registered. Some vendor SDKs inject only their proprietary headers by default and need extra configuration to also emit the standard `traceparent` header. Check your vendor's OTel integration docs for the exact setup.
|
||||
Many tracing SDKs are built on top of OpenTelemetry, but they differ in whether their propagator emits the standard `traceparent` header by default:
|
||||
|
||||
| Vendor setup | Works with `tracePropagation`? | Required configuration |
|
||||
| --------------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| OpenTelemetry SDK (also Honeycomb, Grafana, New Relic via OTLP) | Yes | None — the W3C propagator is the default |
|
||||
| Sentry (Node.js, including Next.js server-side) | Yes, with one flag | Set `propagateTraceparent: true` in `Sentry.init()` — Sentry's propagator omits `traceparent` by default |
|
||||
| Sentry (browser) | Via Sentry's own instrumentation | Set `propagateTraceparent: true` and add your project URL (`https://<ref>.supabase.co`) to `tracePropagationTargets` — Sentry's browser SDK only attaches headers cross-origin for listed targets. For Edge Functions, also add `sentry-trace` to the function's CORS allow-list: Sentry always sends its own header, and it isn't part of `corsHeaders` |
|
||||
| Datadog `dd-trace` (Node.js) | Out of the box | None — `dd-trace` injects W3C headers at the HTTP layer itself, even without `tracePropagation` |
|
||||
| Datadog Browser RUM | Yes, with configuration | Add your project URL to `allowedTracingUrls` with the `tracecontext` propagator type |
|
||||
|
||||
If a propagator is active but doesn't emit `traceparent`, the SDK logs a one-time console warning naming the headers the propagator wrote (version `2.112.3` and later).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -106,7 +123,8 @@ The SDK never throws when it can't propagate, which keeps it safe to enable but
|
||||
- **No active span at request time.** The SDK reads the _current_ context. If `supabase.from(...)` is called outside `tracer.startActiveSpan(...)` (or equivalent), there's nothing to propagate. Wrap the call in a span or use OpenTelemetry's automatic instrumentation.
|
||||
- **`@opentelemetry/api` is not installed** in the app making the request. On `2.112.0` and later the tracing subpath imports it directly, so a missing package surfaces as a module resolution error. On `2.106.0`–`2.111.x` it's loaded dynamically and the SDK silently no-ops.
|
||||
- **No `TracerProvider` registered.** `@opentelemetry/api` defaults to a noop provider that produces non-recorded spans. Ensure your app calls `provider.register()` (or your vendor SDK's equivalent) before making requests.
|
||||
- **The upstream trace is not sampled.** By default the SDK respects upstream sampling decisions. Set `respectSamplingDecision: false` to propagate every request regardless of sampling.
|
||||
- **Your tracing SDK's propagator doesn't emit W3C `traceparent`.** Sentry's propagator, for example, only emits it when `propagateTraceparent: true` is set. From version `2.112.3` the SDK logs a one-time warning naming the headers the propagator wrote — see [Using a vendor tracing SDK](#using-a-vendor-tracing-sdk).
|
||||
- **The upstream trace is not sampled** (versions before `2.112.3`). Older versions skip all trace headers when the upstream trace is not sampled. From `2.112.3`, non-sampled requests still carry `traceparent`, so log correlation keeps working by default. Set `respectSamplingDecision: false` to always send the full trace context.
|
||||
- **You're calling a non-Supabase host through a custom `fetch`.** Trace headers are only attached to Supabase domains (`*.supabase.co`, `*.supabase.in`, `localhost`).
|
||||
- **You're using the CDN (UMD) build.** Trace propagation isn't available there — the tracing runtime can't be loaded from a script tag.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
'Access-Control-Allow-Headers':
|
||||
'authorization, x-client-info, apikey, content-type, x-retry-count, traceparent, tracestate, baggage',
|
||||
}
|
||||
@@ -8,5 +8,6 @@
|
||||
|
||||
export const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
'Access-Control-Allow-Headers':
|
||||
'authorization, x-client-info, apikey, content-type, x-retry-count, traceparent, tracestate, baggage',
|
||||
}
|
||||
Reference in new issue
Block a user