Skip to content

Implement trace propagation from SSR > Pageload in Next 14 App Router #16388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mydea opened this issue May 26, 2025 · 2 comments
Open

Implement trace propagation from SSR > Pageload in Next 14 App Router #16388

mydea opened this issue May 26, 2025 · 2 comments

Comments

@mydea
Copy link
Member

mydea commented May 26, 2025

Description

We today do not have connected traces between http.server (SSR) and pageload spans in Next.js 14, with App router.

vercel/next.js#64256 & #12157 have implemented this for Next 15+.

We should find some way to make this possible on Next 14, even if manual.

@Lms24
Copy link
Member

Lms24 commented May 27, 2025

UPDATE: see #16388 (comment)

As a first step, @RulaKhaled and I looked into finding a way to manually enable trace propagation via generateMetadata. In theory this sounds easy but in practise, it seems like NextJS is doing some pretty aggressive caching of metadata. So aggressive that although the function is run on each request, the rendered page still includes the metadata from the prerender at build time. We found a way to disable this caching behaviour but it seems a bit aggressive.

The idea is that users add the meta tag in their root layout so that the tags are applied to each page in their application. To disable the metadata caching, export const dynamic = 'force-dynamic'; needs to be set.

export const dynamic = 'force-dynamic';

export async function generateMetadata(
): Promise<Metadata> {
  
  const metaObject = {
    title: 'Create Next App',
    description: "Generated by create next app",
    other: {
      ...getTraceData()
    }
  };

  return metaObject
}

@Lms24
Copy link
Member

Lms24 commented May 27, 2025

Update:

After some more research, we concluded that letting users manually set generateMetadata to inject meta tags manually will be the one we take for Next 14 and older.

So what we'll tell users to do, is to add this code to their root layout:

// if they already have a metadata object, they'll need to delete it
- export const metadata = {
-  title: "my page",
- }

+ export async function generateMetadata(): Promise<Metadata> {
+  return {
+     // whatever else they have in here
+     title: "my page",
+     other: {
+      ...Sentry.getTraceData(),
+     },
+   };
+ }

Findings:

  • There's no need for us to worry about forcing dyanamic rendering via export const dynamic = 'force-dynamic:
    • We don't want to inject the tags on static pages anyway. getTraceData() already returns undefined values at build time, meaning this doesn't inject anything.
      • side-note: If we ever want to trace prerender cycles and link them to the pageloads, we can overwrite getTraceData in the NextJS SDK and simply return whatever information the client needs to pick up to establish a span link (cc @s1gr1d)
    • Users have to think about dynamic vs. static pages themselves to display the "correct" content. They will already define the behaviour on layout (e.g. peated) or page level (e.g. my test app).
    • generateMetadata is invoked in dynamic pages only, meaning, we get correct meta tags exactly in the pages we want them in.

Tasks:

  • Update docs (manual setup, set up tracing) and tell users to add this
  • Update wizard to inject generateMetadata in the root layout or if this already exists, show copy/paste instructions for users to also return the other: {...Sentry.getTraceData()} field
  • Add/Adjust a Next14 e2e test app with generateMetadata and assert on http.server and pageload transactions being connected by the same trace.

Why not add the headers in our patched generateMetadata?

We discussed this briefly but it seems like there's no need for this, assuming correct setup (i.e. users adding getTraceData values to their setup.

  • If users have nested generateMetadata calls, the final meta tags are merged by NextJS, so we don't need to patch all generateMetadata calls to always add our meta tags
  • Users still have to export generateMetadata in their root layout so that the Sentry meta tags are injected everywhere they should be. So if we tell them to export it there, we might as well tell them to add the three lines to get Sentry meta tags.
  • We can revisit this at any time if necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants