getsentry / sentry-javascript

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

Microfrontends with module federation doesn't have frame.module_metadata.dsn when transport error with beforeSend #14156

Open tweety18 opened 4 weeks ago

tweety18 commented 4 weeks ago

Is there an existing issue for this?

How do you use Sentry?

Sentry self-hosted

Which SDK are you using?

@sentry/angular

SDK Version

"@sentry/angular": "8.35.0" and "@angular-architects/module-federation": "^17.0.8"

Framework Version

"@sentry/angular": "8.35.0"

Link to Sentry event

can't provide, there is private repo

Reproduction Example/SDK Setup

As you mention in documentation, Sentry inits only once in core application.

Sentry.init({
    dsn: environment.dsn,
    tracesSampleRate: 1.0,
    sampleRate: 1.0,
    environment: environment.name,
    sendDefaultPii: false,
    integrations: [
        Sentry.browserTracingIntegration({}),
        Sentry.captureConsoleIntegration({levels: ['error']}),
        Sentry.extraErrorDataIntegration(),
        Sentry.httpClientIntegration({
            failedRequestStatusCodes: [400, 599],
        }),
        Sentry.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);

            if (routeTo.length || window.history.state.dsn) {
                event.extra = {
                    ...event.extra,
                    [EXTRA_KEY]: routeTo.length ? routeTo :
                    [{
                        dsn: window.history.state.dsn,
                        release: event.release
                    }],
                };
            }
        }
        return event;
    }
})

In microfrontend with module federation I use this configs:

module.exports = merge(baseConfig, {
    devtool: "source-map",
    plugins: [
        SentryWebpackPlugin({
            moduleMetadata: ({ release }) => ({
                dsn: "dsn_path",
                release,

            }),
            org: process.env.SENTRY_ORG,
            project: process.env.SENTRY_PROJECT,
            authToken: process.env.SENTRY_AUTH_TOKEN,
        })
    ],
});

Also, sentry dependency doesn't share in core app for other microfrontends. When http error occurs interceptor in core app call Sentry.captureException(new Error(errorResponse.message))

Steps to Reproduce

  1. init sentry in core app with mentioned below config
  2. in microfrontend with module federation add config to webpack config as mentioned below
  3. reproduce http error with status code 400-599
  4. such error type get caught by common project because for some reason this condition "frame.module_metadata && frame.module_metadata.dsn" isn't true. However, when another error occurs (for example, method with throw error) it transport error to specific project as expected

Expected Result

transport http errors, which appoint in microfrontend with module federation, from core app by beforeSend to specific project

Actual Result

only http errors which appoint in microfrontend with module federation get caught by common project and can't transport by beforeSend because of false value of this condition "frame.module_metadata && frame.module_metadata.dsn"

AbhiPrasad commented 3 weeks ago

Hi @tweety18. Because of the varied nature of microfrontend setups, could you help us dig deeper into this by sharing an example reproduction? That will allow us to debug this faster. Thanks!

tweety18 commented 3 weeks ago

Hi! Could you explain what exactly should I share? This is package.json dependencies in microfrontend:

"dependencies": { @./animations": "^17.3.7", @./cdk": "^17.3.7", @./common": "^17.3.7", @./compiler": "^17.3.7", @./core": "^17.3.7", @./elements": "^17.3.7", @./forms": "^17.3.7", @./material": "^17.3.3", @./platform-browser": "^17.3.7", @./platform-browser-dynamic": "^17.3.7", @./router": "^17.3.7", @./angular": "8.35.0", @./ui-kit": "0.2.0-next.3", "ngx-mask": "^17.0.7", "rxjs": "7.8.1", "tslib": "^2.3.0", "zone.js": "~0.14.5" }, "devDependencies": { @./module-federation": "^17.0.8", @./jest": "^17.0.3", @./build-angular": "^17.3.6", @./cli": "^17.3.6", @./compiler-cli": "^17.3.7", @./webpack-plugin": "2.22.6", @./tracing": "7.114.0", @./jest": "^27.4.0", @./node": "^20.14.15", "cors": "^2.8.5", "express": "^4.21.1", "jest": "^29.7.0", "jest-html-reporters": "^3.1.7", "jest-preset-angular": "^14.2.4", "ngx-build-plus": "^17.0.0", "typescript": "~5.4.5", "webpack-merge": "^6.0.1" }

also, sentry is using via sentry webpack plugin in webpack.congfig like this

const { merge } = require('webpack-merge'); const baseConfig = require('./webpack.config.js'); const {sentryWebpackPlugin: SentryWebpackPlugin} = @.***/webpack-plugin');

module.exports = merge(baseConfig, { devtool: "source-map", plugins: [ SentryWebpackPlugin({ moduleMetadata: ({ release }) => ({ dsn: "dsn data", release,

        }),
        org: process.env.SENTRY_ORG,
        project: process.env.SENTRY_PROJECT,
        authToken: process.env.SENTRY_AUTH_TOKEN,
    })
],

});

чт, 31 окт. 2024 г. в 21:43, Abhijeet Prasad @.***>:

Hi @tweety18 https://github.com/tweety18. Because of the varied nature of microfrontend setups, could you help us dig deeper into this by sharing an example reproduction? That will allow us to debug this faster. Thanks!

— Reply to this email directly, view it on GitHub https://github.com/getsentry/sentry-javascript/issues/14156#issuecomment-2450781968, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOSUUXCB4ER54RVKXVYBMH3Z6KI7TAVCNFSM6AAAAABQ62PPQWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINJQG44DCOJWHA . You are receiving this because you were mentioned.Message ID: @.***>

AbhiPrasad commented 3 weeks ago

@tweety18 it would be great to get a github repo that shows your setup. It can be a minimal reproduction, so doesn't need all the details, just enough to show this problem with sentry.

tweety18 commented 3 weeks ago

As I mentioned about problem with microfrontend should I provide only 1 repo or 2 repos with core app and 1 microfrontend?Wysłane z iPhone'aWiadomość napisana przez Abhijeet Prasad @.***> w dniu 1 lis 2024, o godz. 17:16: @tweety18 it would be great to get a github repo that shows your setup. It can be a minimal reproduction, so doesn't need all the details, just enough to show this problem with sentry.

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>

andreiborza commented 3 weeks ago

@tweety18 please provide a way for us to see the problem by running your reproduction. Whether that's 1 repo or 2 depends on the way you reproduce this issue. We just need a way to run something that shows the issue you are describing so we can investigate it.

tweety18 commented 3 weeks ago

@tweety18 please provide a way for us to see the problem by running your reproduction. Whether that's 1 repo or 2 depends on the way you reproduce this issue. We just need a way to run something that shows the issue you are describing so we can investigate it.

I have self-hosted sentry version (not saas, I edit issue's description) and try to provide repo, but how do you reproduce bug without sentry's projects?

andreiborza commented 3 weeks ago

@tweety18 you can reproduce the issue in a new github repo using the dsn to your self hosted sentry version and when you confirmed it still happens, you can remove the dsn and publish the repo. We will supply our own dns. The issue isn't related to what sentry backend you're using.

tweety18 commented 3 weeks ago

@tweety18 you can reproduce the issue in a new github repo using the dsn to your self hosted sentry version and when you confirmed it still happens, you can remove the dsn and publish the repo. We will supply our own dns. The issue isn't related to what sentry backend you're using.

Hello! Can you provide an interface to error event, which appear in beforeSend construction? 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,

                };
            }
        }
        return event;
    },
});
andreiborza commented 3 weeks ago

@tweety18 do you mean types for the exception? We have https://github.com/getsentry/sentry-javascript/blob/develop/packages/types/src/exception.ts in @sentry/types.

tweety18 commented 3 weeks ago

@tweety18 do you mean types for the exception? We have https://github.com/getsentry/sentry-javascript/blob/develop/packages/types/src/exception.ts in @sentry/types.

No, in beforeSend we got an event and than condition event?.exception?.values?.[0].stacktrace?.frames the question is where can I see the interface for such event? because, when I try console.log(frames) I didn't see module_metadata and module_metadata.dsn properties, but when I try console.log(frame.module_metadata.dsn) i got a string with dsn

andreiborza commented 3 weeks ago

@tweety18 I'm not sure I understand the question entirely. Are you looking for the type of a stack frame?

tweety18 commented 3 weeks ago

@tweety18 I'm not sure I understand the question entirely. Are you looking for the type of a stack frame?

In your documentation there is a solution for automatically route errors https://docs.sentry.io/platforms/javascript/guides/angular/best-practices/micro-frontends/ there is such code:

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;
  },
}

So, the question is what exact interface has event (i mean this event: beforeSend: (event) => {)? As I see, below there is a condition of event?.exception?.values?.[0].stacktrace.frames I want such interface from you:

interface Event {
 exception: {
     values: [
         stacktrace: [
                   frames.....
               ] 
        ]  
  }
}
andreiborza commented 3 weeks ago

@tweety18 you can find this here: https://github.com/getsentry/sentry-javascript/blob/develop/packages/types/src/event.ts

You can explore all types related to the Event from there.