Skip to content

Commit 075dfb7

Browse files
bartlomiejuclaude
andauthored
feat: inject traceparent meta tag when OpenTelemetry is active (#3729)
Closes #2830 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 92e07f0 commit 075dfb7

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

docs/latest/advanced/opentelemetry.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,25 @@ deno task start
127127

128128
Open `http://localhost:16686` to browse traces. You'll see each request broken
129129
down into its middleware, handler, and rendering spans.
130+
131+
## Client-side trace correlation
132+
133+
When an OpenTelemetry exporter is active, Fresh automatically injects a
134+
[W3C Trace Context](https://www.w3.org/TR/trace-context/) `<meta>` tag into the
135+
`<head>` of every rendered page:
136+
137+
```html
138+
<head>
139+
<meta
140+
name="traceparent"
141+
content="00-ab42124a3c573678d4d8b21ba52df3bf-d21f7bc17caa5aba-01"
142+
>
143+
<!-- ... -->
144+
</head>
145+
```
146+
147+
This allows client-side OpenTelemetry instrumentation (such as
148+
[`@opentelemetry/instrumentation-document-load`](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/c9d62be989802534c01373e8ab41e13747d7ee3e/packages/instrumentation-document-load))
149+
to link browser performance traces back to the server-side span that rendered
150+
the page, giving you end-to-end visibility from server rendering through page
151+
load.

packages/fresh/src/runtime/server/preact_hooks.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { getCodeFrame } from "../../dev/middlewares/error_overlay/code_frame.ts"
3535
import { escapeScript } from "../../utils.ts";
3636
import { HeadContext } from "../head.ts";
3737
import { useContext } from "preact/hooks";
38+
import { isSpanContextValid, trace } from "@opentelemetry/api";
3839

3940
interface InternalPreactOptions extends PreactOptions {
4041
[OptionsType.ATTR](name: string, value: unknown): string | void;
@@ -295,6 +296,22 @@ options[OptionsType.DIFF] = (vnode) => {
295296
}
296297
}
297298

299+
// Inject W3C traceparent meta tag when OpenTelemetry is active,
300+
// enabling client-side tracing to connect to the server span.
301+
const activeSpan = trace.getActiveSpan();
302+
if (activeSpan) {
303+
const spanCtx = activeSpan.spanContext();
304+
if (isSpanContextValid(spanCtx)) {
305+
const flags = (spanCtx.traceFlags & 1) ? "01" : "00";
306+
const traceparent =
307+
`00-${spanCtx.traceId}-${spanCtx.spanId}-${flags}`;
308+
items.push(
309+
// deno-lint-ignore no-explicit-any
310+
h("meta", { name: "traceparent", content: traceparent }) as any,
311+
);
312+
}
313+
}
314+
298315
// deno-lint-ignore no-explicit-any
299316
items.push(h(RemainingHead, null) as VNode<any>);
300317

0 commit comments

Comments
 (0)