Fetch API adapter for Stainless X-ray request logging. Use this in edge runtimes, web workers, or any environment with the Fetch API.
pnpm add @stainlessdev/xray-emitterimport { createEmitter, wrapFetch } from '@stainlessdev/xray-emitter/fetch';
const xray = createEmitter({ serviceName: 'my-service' });
const handler = wrapFetch(async (_req) => {
return new Response('ok', { status: 200 });
}, xray);If you need to keep the original Request/Response objects (for framework compatibility), use wrapFetchPreserve:
import { wrapFetchPreserve } from '@stainlessdev/xray-emitter/fetch';
const handler = wrapFetchPreserve(async (req) => {
return new Response(await req.text());
}, xray);import { getXrayContext } from '@stainlessdev/xray-emitter/fetch';
const handler = wrapFetch(async (req) => {
const ctx = getXrayContext(req);
ctx?.setActor('tenant-123', 'user-123');
return new Response('ok');
}, xray);X-ray will auto-generate a request ID and inject it into your response headers under the configured name (requestId.header, default request-id, emitted as Request-Id) if the header is missing. If you set your own request ID first (via options.requestId or by setting the response header yourself), X-ray preserves it and does not overwrite the header.
createEmitter(config) accepts XrayRuntimeConfig:
serviceName(required)endpointUrl(required; falls back toSTAINLESS_XRAY_ENDPOINT_URLwhen omitted; explicitendpointUrlwins)environment,version,logger,logLevelexporter:endpointUrl,headers,timeoutMs,spanProcessor,instance(custom SpanExporter)capture: request/response headers and bodiesredaction: headers/query/body JSON-path redactionrequestId: header name to read/writeroute: normalization options
wrapFetch(handler, xray, options) and wrapFetchPreserve(handler, xray, options) share:
route: override the route name for the requestrequestId: explicit request ID to use (prevents auto-generation)capture: per-request capture overridesredaction: per-request redaction overridesonRequest(ctx),onResponse(ctx, log),onError(ctx, err)hooks
- Requires a global
fetchwhen using the default exporter. Iffetchis not available, provideexporter.instanceor use@stainlessdev/xray-emitter/node. - This package depends on OpenTelemetry packages as peer dependencies.