Skip to content

feat: inject traceparent meta tag when OpenTelemetry is active#3729

Merged
bartlomieju merged 9 commits into
mainfrom
feat/otel-traceparent-meta
Mar 29, 2026
Merged

feat: inject traceparent meta tag when OpenTelemetry is active#3729
bartlomieju merged 9 commits into
mainfrom
feat/otel-traceparent-meta

Conversation

@bartlomieju

Copy link
Copy Markdown
Contributor

Summary

When an OpenTelemetry exporter is configured, Fresh now automatically injects a <meta name="traceparent"> tag into the <head> of rendered HTML pages. This enables client-side OTel instrumentation (e.g., @opentelemetry/instrumentation-document-load) to connect browser performance traces to the server-side span that rendered the page.

Output example

<head>
  <meta name="traceparent" content="00-ab42124a3c573678d4d8b21ba52df3bf-d21f7bc17caa5aba-01">
  <!-- ... other head elements ... -->
</head>

How it works

  • During <head> rendering in preact_hooks.ts, checks for an active OTel span via trace.getActiveSpan()
  • Validates the span context with isSpanContextValid() to ensure a real exporter is configured (not the no-op default)
  • Injects a <meta name="traceparent"> tag in W3C Trace Context format: 00-{traceId}-{spanId}-{traceFlags}
  • Zero overhead when OTel is not configured — getActiveSpan() returns undefined with the no-op provider

Test plan

  • deno test -A packages/fresh/src/app_test.tsx — 46 passed
  • deno test -A packages/fresh/src/fs_routes_test.tsx — 55 passed

Closes #2830

🤖 Generated with Claude Code

bartlomieju and others added 5 commits March 28, 2026 10:43
When an OTel exporter is configured, Fresh now automatically adds a
<meta name="traceparent"> tag to the <head> of rendered HTML pages.
This enables client-side OTel instrumentation (e.g.,
@opentelemetry/instrumentation-document-load) to connect browser
traces to the server-side span that rendered the page.

The tag follows the W3C Trace Context format:
  <meta name="traceparent" content="00-{traceId}-{spanId}-{flags}">

Only injected when a valid span context exists (real OTel exporter
configured), so there is zero overhead when OTel is not in use.

Closes #2830

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move `as any` cast to a single line so the deno-lint-ignore directive
covers it, fixing ban-unused-ignore and no-explicit-any errors on CI.

Also document the new traceparent meta tag injection in the
OpenTelemetry docs page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju enabled auto-merge (squash) March 29, 2026 18:28
bartlomieju and others added 4 commits March 29, 2026 20:34
The ignore directive only applies to the immediately following line.
After formatting, `items.push(` was on its own line, so the directive
covered that instead of the `as any` cast. Move the comment inside
the push() call, directly above the line that needs it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
npmjs.com returns 403 to automated link checkers. Link to the
OpenTelemetry GitHub repo instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The package is under packages/, not plugins/web/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju merged commit 075dfb7 into main Mar 29, 2026
8 of 9 checks passed
@bartlomieju bartlomieju deleted the feat/otel-traceparent-meta branch March 29, 2026 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generate traceparent in app wrapper when OTEL is enabled

1 participant