Last 12 weeks · 6 commits
1 of 6 standards met
Problem Application spans require framework-specific inbound extraction to join Vercel platform traces. Solution Decorate Node context managers to lazily expose the span as parent. Preserve active spans, custom managers, explicit extraction, sampling, and async isolation. Validate with 51 tests, type-check, lint, bundle limits, and a live Node 24 trace. Trace: https://vercel.com/uncurated-tests/node-context-propagation-probe/logs/traces/12e024b6b40e74cb0bef39bb0a74c81d?view=waterfall Related PR(s) https://github.com/vercel/functions/pull/3496 https://github.com/vercel/otel/pull/163
What this is Variation of #214 that structures the exporter for streaming spans during the invocation, while keeping the reliable end-of-trace delivery as the default. Same foundation (per-trace context capture, in-context queue drain, retain-instead-of-drop), plus strict per-trace payload discipline and an opt-in streaming mode. Behavior Default (accumulate): spans of registered traces buffer per trace and ship in one payload at the trace's final flush, through the context captured at root-span start. Untracked traces ship immediately via the ambient context. Unattributable spans are retained and retried instead of silently acked. Streaming (): every flush ships each trace's spans as their own single-trace payload immediately, bounding client memory on long runs. Opt-in and not recommended yet: parts of the platform-side delivery pipeline currently only reliably persist batches delivered near the end of the request, so streamed spans of long traces can still be lost. Once that is addressed, flipping the flag gives streaming without loss; the client side is ready. Both modes: traces never share a payload, so one stale span can no longer poison other traces' delivery (this mixing is what made earlier mid-run shipping attempts non-deterministic). Verification Long-running workflow reproduction, default env: Default (accumulate) mode: all step spans consistently survive across repeated runs (previously only the last few seconds' spans did). Streaming mode on today's platform loses early spans (expected, see above), which is why it is flag-gated. Relationship to #213 / #214 #214: same foundation; this PR supersedes it if we want the streaming option and the strict per-trace payload hardening (or #214 lands first and this rebases to a small delta). #213: kept its in-context flush driver and retain-instead-of-drop ideas. Testing 12 unit tests: default-mode accumulate + finalize semantics, streaming-mode per-flush shipping, strict no-mixing, ambient shipping for untracked traces, no-channel buffering + retry, failing-channel retention, in-context drain triggers, registration lifecycle. , , full unit suite pass. Bundle size limits bumped slightly (main was within ~2KB / ~100 bytes of them).
Problem Traces from long-running invocations (e.g. Vercel Workflows) are missing most spans from the first part of the run: the trace looks blank early on, with all step spans bunched into the last few seconds. The work happens the whole time; the spans are genuinely lost. Root cause (client side) 1. The schedules flushes with a bare , which runs outside the request's . The runtime exporter then resolves no request context and silently acked + dropped every mid-run batch. Only the final flush, triggered via (in-context), survived. 2. The queue is shared by all concurrent requests on an instance, so a flush ships other invocations' spans through the wrong request's telemetry channel, where they are not reliably persisted. Fix Capture the owning request context per trace id at root-span start (always in-request), bounded against never-ending traces. The exporter accumulates spans of registered traces per trace and ships the whole buffer in a single report when the trace is finalized from its own request's . Untracked traces keep shipping immediately through the ambient context. Spans that cannot be attributed are retained and re-attempted instead of silently acked. The processor drains the queue in-context on span end (debounced on / ) so long runs cannot overflow . Off-Vercel behavior is unchanged. Verified on a long-running workflow reproduction: with this change all step spans consistently survive across repeated runs (previously only the last few seconds' spans did). Relationship to #213 Same problem; this PR keeps its in-context flush and retain-instead-of-drop ideas, and adds per-trace attribution + single-report delivery, which testing showed is required for reliability on warm instances. Testing Unit tests for accumulation/finalize semantics, per-trace separation, retain/re-ship paths, in-context drain triggers, and registration lifecycle. , , full unit suite pass. Bundle size limits bumped slightly (main was within ~2KB / ~100 bytes of them).
Problem The v1.x workflow fails at publish with: is npm's masked response for an unauthenticated publish. ( was never published — is still at .) Root cause Releases use OIDC trusted publishing (no ). detects OIDC but defers the actual OIDC→registry-token exchange to the npm CLI, which requires npm ≥ 11.5.1. v1.x pinned , and every Node 22 release bundles npm 10.9.x (< 11.5.1) → npm can't perform the OIDC exchange → publishes anonymously → E404. The release workflow is identical (same , same OIDC path, same ) and publishes fine — because it runs Node 24 (npm 11.6.2+). That passing run isolates the Node/npm version as the only material difference. The pin likely came from misreading npm's "requires Node.js ≥ 22.14.0" (npm 11.5.1 runs on Node ≥22.14; Node 22.14 does not ship npm 11.5.1). Fix Bump both release jobs to (npm 11.6.2+). Can't use here — that's (Node 18, the v1 SDK's runtime target); the publish job's Node is just tooling and is independent of the package's supported runtimes.
Repository: vercel/otel. Description: OTEL tracing for Vercel Stars: 97, Forks: 22. Primary language: TypeScript. Languages: TypeScript (96.5%), JavaScript (3%), CSS (0.4%), HTML (0.1%). Homepage: https://vercel.com/docs/observability/otel-overview Latest release: @vercel/otel@1.14.2 (1mo ago). Open PRs: 15, open issues: 36. Last activity: 10h ago. Community health: 37%. Top contributors: jankaifer, dvoytenko, github-actions[bot], kakadiadarpan, gaspar09, agadzik, bripkens, bengigone, ethshea, huozhi and others.