getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
7.76k stars 1.52k forks source link

Parsing Issue with moduleMetadataIntegration in Next.js Micro Frontend Setup Using Sentry #12704

Open ivank-s opened 6 days ago

ivank-s commented 6 days ago

Is there an existing issue for this?

How do you use Sentry?

Self-hosted/on-premise

Which SDK are you using?

@sentry/nextjs

SDK Version

8.13.0

Framework Version

Next 12.3.4 @module-federation/nextjs-mf 6.7.1

Link to Sentry event

No response

SDK Setup/Reproduction Example

in remote nextjs app next.config.js

const config =  {
webpack: config => {
    config.plugins.push(
      sentryWebpackPlugin({
        telemetry: false,
        moduleMetadata: ({ release }) => ({
          dsn: NEXT_PUBLIC_SENTRY_DSN,
          release
        })
      })
    )
}
}
const sentryWebpackPluginOptions = {
release: ''
}
module.exports = withSentryConfig(config, sentryWebpackPluginOptions )

in host nextjs app sentry.client.config.js

import {
  init,
  makeFetchTransport,
  moduleMetadataIntegration,
  makeMultiplexedTransport,
} from "@sentry/browser";

const EXTRA_KEY = "ROUTE_TO";

const transport = makeMultiplexedTransport(makeFetchTransport, (args) => {
  const event = args.getEvent();
  if (
    event &&
    event.extra &&
    EXTRA_KEY in event.extra &&
    Array.isArray(event.extra[EXTRA_KEY])
  ) {
    return event.extra[EXTRA_KEY];
  }
  return [];
});

init({
  dsn: "__DEFAULT_DSN__",
  integrations: [moduleMetadataIntegration()],
  transport,
  beforeSend: (event) => {
    if (event?.exception?.values?.[0].stacktrace.frames) {
      const frames = event.exception.values[0].stacktrace.frames;
      // Find the last frame with module metadata containing a DSN
      const routeTo = frames
        .filter(
          (frame) => frame.module_metadata && frame.module_metadata.dsn,
        )
        .map((v) => v.module_metadata)
        .slice(-1); // using top frame only - you may want to customize this according to your needs

      if (routeTo.length) {
        event.extra = {
          ...event.extra,
          [EXTRA_KEY]: routeTo,
        };
      }
    }

    return event;
  },
});

Steps to Reproduce

  1. Set a button in the remote package application to trigger an error
  2. build and serve remote app
  3. build and serve host app
  4. Clicking the remote package button in the host application triggers an error

Expected Result

The moduleMetadataIntegration plugin should successfully parse the metadata from the remote package files, allowing error data to be correctly forwarded and integrated within the Sentry dashboard. The filenames in the filenameMetadataMap should match those generated in the _sentryModuleMetadata object, ensuring consistent error tracking across the host and remote packages.

Actual Result

The error stacktrace frame filenames in the host application, including those from the remote package, start with app:/// (e.g., app:///_next/static/chunks/769.f60b4a7892c8be2e-f60b4a7892c8be2e-fed.js). This prefix causes the moduleMetadataIntegration plugin to fail in parsing the metadata, resulting in errors from the remote package not being properly forwarded or displayed in the Sentry dashboard.

Here is the generated _sentryModuleMetadata for reference:

{
  "Error↵ at http://xxx.com/_next/static/chunks/769.f60b4a7892c8be2e-f60b4a7892c8be2e-fed.js:1:971": {
    "dsn": "aaa",
    "release": "..."
  }
}
lforst commented 3 days ago

Thanks, I'll take a look!