@heystack/otel 0.9.1 → 0.9.2
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 +1 -0
- package/dist/workers.js +16 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -364,6 +364,7 @@ As belt-and-suspenders the exporter also drops any span whose HTTP target points
|
|
|
364
364
|
|
|
365
365
|
## Migration / versioning
|
|
366
366
|
|
|
367
|
+
- **`0.9.2`** — **`/workers`: `instrument()` no longer breaks WebSocket / Durable Object upgrades.** The fetch wrapper rebuilt every response with `new Response(...)`, which **drops the `webSocket` property** on a `101 Switching Protocols` upgrade — so every WebSocket connection on an instrumented Worker failed *whenever tracing was active* (an API key set), while passing in dev/staging where `instrument()` is a passthrough. `instrument()` now detects an upgrade (`response.webSocket` present, or `status === 101`) and returns the **original response untouched** (span closed immediately; no `traceparent` header injected — headers on a 101 aren't delivered anyway). Fixes failed `wss://` connections behind `routeAgentRequest` / any `new WebSocketPair()` handler. No API change; upgrade and redeploy.
|
|
367
368
|
- **`0.9.1`** — **`/workers`: binding spans no longer orphan without `nodejs_compat`.** On a workerd runtime without `nodejs_compat` (no `globalThis.AsyncLocalStorage`), the synchronous fallback context manager cannot carry the active span across an `await` — so a D1/KV/R2/Vectorize/AI/Queue/Service span created *after* an `await` in your handler was emitted as the root of its own single-span trace instead of a child of the request. `instrument()` now captures the request's SERVER context per-request and uses it as an explicit parent fallback when no span is active, so binding operations are always children of the request trace. `nodejs_compat` is still recommended for cross-`await` parenting of outbound-fetch CLIENT spans and manual `withSpan` spans. No API change; upgrade and redeploy.
|
|
368
369
|
- **`0.9.0`** — **`/workers`: automatic LLM gen_ai enrichment for outbound API calls.** Outbound `fetch` calls to known LLM providers (OpenAI, Anthropic, Cloudflare AI Gateway, Google) automatically gain `gen_ai.*` OTel semantic-convention attributes on the CLIENT span — model, token counts, finish reason, response ID — with no extra code. New optional `WorkersConfig.ai` option: `captureContent: true` also captures prompt/completion text (off by default; **strongly recommended for AI-app RCA**), with `redact` for scrubbing and `maxContentChars` for length capping. The original request/response bodies are never consumed (request read only when already a string; response via `response.clone()`). Streaming responses skip response enrichment. No breaking changes.
|
|
369
370
|
- **`0.8.0`** — **`/workers`: Workers AI, Queue producer, and Service binding instrumentation.** `instrumentBindings: true` now auto-wraps three additional binding types: `env.AI.run()` emits CLIENT spans with `gen_ai.system`, `gen_ai.request.model`, and `gen_ai.usage.input_tokens`/`output_tokens` (streaming results are never consumed); Queue `.send`/`.sendBatch` emit PRODUCER spans with `messaging.*` attributes including batch size; Service binding `.fetch` emits a CLIENT span and injects a W3C `traceparent` header into the outgoing request so calls to other Workers appear in the same distributed trace. `startSpan` factory now accepts an optional `SpanKind` for correct CLIENT/PRODUCER categorisation. No breaking changes.
|
package/dist/workers.js
CHANGED
|
@@ -915,6 +915,22 @@ export function instrument(handler, config) {
|
|
|
915
915
|
}
|
|
916
916
|
try {
|
|
917
917
|
const response = await context.with(serverCtx, () => originalFetch(req, handlerEnv, ctx));
|
|
918
|
+
// WebSocket / connection upgrades: a 101 Switching Protocols response
|
|
919
|
+
// carries a live server-side `webSocket` that the Workers Runtime hands
|
|
920
|
+
// to the client ONLY if that exact Response object is returned. Rebuilding
|
|
921
|
+
// it (as the body branches below do) drops `.webSocket` — silently breaking
|
|
922
|
+
// every upgrade on an instrumented Worker whenever tracing is active. Pass
|
|
923
|
+
// the ORIGINAL response through untouched and close the span now (there is
|
|
924
|
+
// no body to time). We do NOT inject the `traceparent` header — headers on a
|
|
925
|
+
// 101 aren't delivered to the client anyway. `webSocket` is the reliable
|
|
926
|
+
// signal; `status === 101` is a belt-and-braces fallback.
|
|
927
|
+
if (response.webSocket || response.status === 101) {
|
|
928
|
+
span.setAttribute("http.response.status_code", response.status);
|
|
929
|
+
span.setStatus({ code: SpanStatusCode.UNSET });
|
|
930
|
+
span.end();
|
|
931
|
+
drain(provider, ctx);
|
|
932
|
+
return response;
|
|
933
|
+
}
|
|
918
934
|
const headers = new Headers(response.headers);
|
|
919
935
|
headers.set("traceparent", traceparent);
|
|
920
936
|
appendExposeHeader(headers, "traceparent");
|