Files
next.js/test/e2e/app-dir/cache-components-allow-otel-spans/app/page.tsx
Josh StoryandGitHub d5dc166f42 [Cache Components] Allow span creation while prerendering (#82350)
When creating spans with OTel random values must be created to follow
the OTel spec and is expected in practical implementations. While it is
a loose concession Next.js will allow spans to be created while
prerendering that have ids generated with random values. and by reading
the current time from the system clock.

This is pragmatic but potentially risky because if you are not careful
and for instance wrap a "use cache" function in a span it is possible
you will accidentally pass the span into the cache function causing it
to miss on every invocation due to the random nature of one of it's
arguments.

To defend against this we do check whether `startActiveSpan` is being
passed a Cache Function. However it is easy to circumvent by wrapping it
in an intermediate function or by using startSpan and context.with
yourself.

In the long run we should consider tainting the Span objects created in
these scopes so they cannot be sent through to a cache. I will consider
a follow up PR to land this if we determine taint is likely to be
stabilized in React.

The pratical implementation of this change is to patch the tracer
provider so that it always provides a patched tracer which exits the
workUnitStorage on span start/creation and re-enters the scope on inner
function exectuion.
2025-08-05 09:24:31 -07:00

42 lines
1.4 KiB
TypeScript

export default function Page() {
return (
<main>
<h1>OTel Cache Components Compat Test</h1>
<p>
Span generation causes random IDs to be created. There is a tradeoff
with this while prerendering since sync IO like Math.random() should be
excluded from static prerenders but spans are so widely used for
providing telemetry for rendering and they would ideally be side effect
free. Next.js now allows random id generation and current time reading
while OTel spans are constructed. However it is possible for the span
object to be passed to a Cache Component where the random ID will cause
cache misses while prerendering. It is important that Span objects not
be passed into Cache Functions for proper functioning of Cache
Components.
</p>
<ul>
<li>
<a href="/novel/cache">
"use cache" Page without build-time prerendering
</a>
</li>
<li>
<a href="/prerendered/cache">
"use cache" Page with build-time prerendering
</a>
</li>
<li>
<a href="/novel/server">
Server Page without build-time prerendering
</a>
</li>
<li>
<a href="/prerendered/server">
Server Page with build-time prerendering
</a>
</li>
</ul>
</main>
)
}