sentry-module icon indicating copy to clipboard operation
sentry-module copied to clipboard

Nuxt 3 compatibility

Open nandi95 opened this issue 2 years ago • 22 comments

With nuxt 3 out in beta, it would be nice if this module can be updated so it also supports v3.

It should be possible to support both by using @nuxt/kit. The version 3 has said it's compatible with v2 modules but I'm seem to be experiencing issues. Is it might be because this module not using the lastest dependencies?

If this in fact meant to be working with v3, are there any way to ensure that fact with tests?

nandi95 avatar Oct 19 '21 14:10 nandi95

Thanks for reporting. This is discussed in https://github.com/nuxt/framework/discussions/751#discussioncomment-1468163 a bit. I would still like some answers from the team and better documentation since it's not clear how things should look going forward.

And related to that, I'm not in a rush to fix it since Nuxt 3 appears to need quite a bit of work before it stabilizes.

Open to any suggestions and help though.

rchl avatar Oct 19 '21 14:10 rchl

Missed that! Still this issue could be useful so others can find this too and for tracking support down the line.

nandi95 avatar Oct 19 '21 14:10 nandi95

I have written the following Nuxt 3 plugin which seems to be working fairly well for me. Note that Sentry's SDK doesn't seem to play well with the native Vue error event handler when logErrors: true is set during Sentry init; however i've added a simple console.error in the beforeSend hook so I can still see my errors in dev.

For anyone else using Nuxt 3 that this may be useful for..

  1. Add your Sentry DSN to publicRuntimeConfig.SENTRY_DSN in nuxt.config.ts, or define it manually. See other options i've sourced from runtime config below, too. Setting DSN is required; other options will fall back to defaults.
  2. Add the following in plugins/sentry.client.ts
// plugins/sentry.client.ts

import { defineNuxtPlugin, useRuntimeConfig } from '#app'
import * as Sentry from "@sentry/vue";
import { Integrations } from "@sentry/tracing";

export default defineNuxtPlugin((nuxtApp) => {
    const config = useRuntimeConfig()
    const { vueApp } = nuxtApp;
    console.log(`vueApp: `, vueApp)
    Sentry.init({
        app: [vueApp],
        dsn: config.SENTRY_DSN,
        integrations: [
            new Integrations.BrowserTracing({
                routingInstrumentation: Sentry.vueRouterInstrumentation(nuxtApp.$router),
                tracingOrigins: ["localhost", "yourdomain.com", /^\//],
            }),
        ],
        logErrors: false, // Note that this doesn't seem to work with nuxt 3
        tracesSampleRate: config.SENTRY_TRACES_SAMPLE_RATE || 1.0, // Sentry recommends adjusting this value in production
        debug: config.SENTRY_ENABLE_DEBUG || false, // Enable debug mode
        environment: config.ENVIRONMENT || 'dev', // Set environment
        // The following enables exeptions to be logged to console despite logErrors being set to false (preventing them from being passed to the default Vue err handler)
        beforeSend(event, hint) {
            // Check if it is an exception, and if so, log it.
            if (event.exception) {
                console.error(`[Exeption handled by Sentry]: (${hint.originalException})`, { event, hint })
            }
            // Continue sending to Sentry
            return event;
        },
    });

    vueApp.mixin(Sentry.createTracingMixins({ trackComponents: true, timeout: 2000, hooks: ['activate', 'mount', 'update'] }))
    Sentry.attachErrorHandler(vueApp, { logErrors: false, attachProps: true, trackComponents: true, timeout: 2000, hooks: ['activate', 'mount', 'update'] });

    return {
        provide: {
            sentrySetContext: (n, context) => Sentry.setContext(n, context),
            sentrySetUser: (user) => Sentry.setUser(user),
            sentrySetTag: (tagName, value) => Sentry.setTag(tagName, value),
            sentryAddBreadcrumb: (breadcrumb) => Sentry.addBreadcrumb(breadcrumb),
        }
    }
})
  1. Use the provided helpers in your components etc, eg:
<script setup lang="ts">
const { $sentrySetContext, $sentrySetUser } = useNuxtApp()

const throwTestError = () => {
    throw new Error('Test Error')
}

const setContext = () => {
    $sentrySetContext("character", {
        name: "Mighty Fighter",
        age: 19,
        attack_type: "melee",
    });
}

const setUser = () => {
    $sentrySetUser({ email: '[email protected]' });
}
</script>

jontybrook avatar Jan 20 '22 00:01 jontybrook

With Nuxt 3 RC1 being released in the coming days, has there been any movement on this?

oyed avatar Apr 20 '22 02:04 oyed

Not really. If anyone knows how everything can be made to work in Nuxt 3 then feel free to contribute.

The biggest problem might be with getting it to work on the server-side (in server middleware specifically) as Nuxt 3 doesn't want modules to run at runtime and I haven't seen an equivalent to current solution for Nuxt 3.

rchl avatar Apr 20 '22 07:04 rchl

@rchl http://v3.nuxtjs.org/api/advanced/kit

As far as I can understand, you can call addPlugin, addServerMiddleware, and Webpack/Vite methods in module, and those settings will be applied when project start.

Is this something that will allow module to run on runtime and allow migration to Nuxt 3?

daniluk4000 avatar Apr 21 '22 09:04 daniluk4000

One thing that would need to be figured out is publishing of releases which relies on a webpack plugin provided by Sentry right now. It won't work with Vite.

As for using addServerMiddleware, that would have to be tested but it would be a bit awkward as we'd need to generate the file with the user options included and then add it using addServerMiddleware. Typical thing for plugins but feels a bit weird for server middleware maybe...

rchl avatar Apr 21 '22 10:04 rchl

It won't work with Vite

Damn. That would be hard then.

daniluk4000 avatar Apr 21 '22 10:04 daniluk4000

I found https://github.com/ikenfin/vite-plugin-sentry, but its unofficial. I'm not using that plugin myself so I don't know if it would fit here.

darthf1 avatar Apr 21 '22 10:04 darthf1

One thing that would need to be figured out is publishing of releases which relies on a webpack plugin provided by Sentry right now. It won't work with Vite.

As for using addServerMiddleware, that would have to be tested but it would be a bit awkward as we'd need to generate the file with the user options included and then add it using addServerMiddleware. Typical thing for plugins but feels a bit weird for server middleware maybe...

About that, I am looking into making a unplugin for sentry which would support, webpack, vite, rollup and esbuild. unplugin-sentry and also have made a Dev repo where I might work on the sentry module. nuxt-sentry

asonnleitner avatar Apr 26 '22 05:04 asonnleitner

@asonnleitner appreciate the work and hope that we could use and/or merge those changes at some point.

Though it's still not fully clear to me how the situation looks like right now when it comes to module supporting both Nuxt 2 and Nuxt 3.

While @nuxt/bridge is supposedly bridging that gap and allowing for exactly that, it itself introduces breaking changes to Nuxt 2, as far as my experience goes. And since Nuxt 2 has and will have a big market share for a while longer, it would be non-ideal to either:

  • have to maintain two separate versions of the module
  • migrate to Nuxt 3 and not care about Nuxt 2 anymore

rchl avatar May 07 '22 21:05 rchl

How is this going?

Trying to migrate to nuxt-edge and this plugin doesns't seem to work. Should we ask for help or something, because I'm not sure how you can migrate any meaningful app without error reporting.

Especially at a time where you are expecting the error rate to skyrocket due to breaking changes of packages

klausXR avatar May 20 '22 11:05 klausXR

@danielroe can we get some insights here on the problems that are troubling the maintainers of this library?

We really need to get this module working, Sentry is the premier package for error reporting and is probably used across most of Vue/Nuxt projects.

I'm not sure any people working on production-ready apps would be willing to migrate if they don't have error reporting abilities.

klausXR avatar May 25 '22 05:05 klausXR

@asonnleitner appreciate the work and hope that we could use and/or merge those changes at some point.

Though it's still not fully clear to me how the situation looks like right now when it comes to module supporting both Nuxt 2 and Nuxt 3.

While @nuxt/bridge is supposedly bridging that gap and allowing for exactly that, it itself introduces breaking changes to Nuxt 2, as far as my experience goes. And since Nuxt 2 has and will have a big market share for a while longer, it would be non-ideal to either:

  • have to maintain two separate versions of the module

  • migrate to Nuxt 3 and not care about Nuxt 2 anymore

@rchl I think to make the plugin compatible with all nuxt2/bridge and 3 should not be an issue, but I am currently a bit tight with time so will take a while until I'll have a look at it in-depth.

asonnleitner avatar May 26 '22 04:05 asonnleitner

beforeSend

I have written the following Nuxt 3 plugin which seems to be working fairly well for me. Note that Sentry's SDK doesn't seem to play well with the native Vue error event handler when logErrors: true is set during Sentry init; however i've added a simple console.error in the beforeSend hook so I can still see my errors in dev.

For anyone else using Nuxt 3 that this may be useful for..

1. Add your Sentry DSN to `publicRuntimeConfig.SENTRY_DSN` in `nuxt.config.ts`, or define it manually. See other options i've sourced from runtime config below, too. Setting DSN is required; other options will fall back to defaults.

2. Add the following in plugins/sentry.client.ts
// plugins/sentry.client.ts

import { defineNuxtPlugin, useRuntimeConfig } from '#app'
import * as Sentry from "@sentry/vue";
import { Integrations } from "@sentry/tracing";

export default defineNuxtPlugin((nuxtApp) => {
    const config = useRuntimeConfig()
    const { vueApp } = nuxtApp;
    console.log(`vueApp: `, vueApp)
    Sentry.init({
        app: [vueApp],
        dsn: config.SENTRY_DSN,
        integrations: [
            new Integrations.BrowserTracing({
                routingInstrumentation: Sentry.vueRouterInstrumentation(nuxtApp.$router),
                tracingOrigins: ["localhost", "yourdomain.com", /^\//],
            }),
        ],
        logErrors: false, // Note that this doesn't seem to work with nuxt 3
        tracesSampleRate: config.SENTRY_TRACES_SAMPLE_RATE || 1.0, // Sentry recommends adjusting this value in production
        debug: config.SENTRY_ENABLE_DEBUG || false, // Enable debug mode
        environment: config.ENVIRONMENT || 'dev', // Set environment
        // The following enables exeptions to be logged to console despite logErrors being set to false (preventing them from being passed to the default Vue err handler)
        beforeSend(event, hint) {
            // Check if it is an exception, and if so, log it.
            if (event.exception) {
                console.error(`[Exeption handled by Sentry]: (${hint.originalException})`, { event, hint })
            }
            // Continue sending to Sentry
            return event;
        },
    });

    vueApp.mixin(Sentry.createTracingMixins({ trackComponents: true, timeout: 2000, hooks: ['activate', 'mount', 'update'] }))
    Sentry.attachErrorHandler(vueApp, { logErrors: false, attachProps: true, trackComponents: true, timeout: 2000, hooks: ['activate', 'mount', 'update'] });

    return {
        provide: {
            sentrySetContext: (n, context) => Sentry.setContext(n, context),
            sentrySetUser: (user) => Sentry.setUser(user),
            sentrySetTag: (tagName, value) => Sentry.setTag(tagName, value),
            sentryAddBreadcrumb: (breadcrumb) => Sentry.addBreadcrumb(breadcrumb),
        }
    }
})
3. Use the provided helpers in your components etc, eg:
<script setup lang="ts">
const { $sentrySetContext, $sentrySetUser } = useNuxtApp()

const throwTestError = () => {
    throw new Error('Test Error')
}

const setContext = () => {
    $sentrySetContext("character", {
        name: "Mighty Fighter",
        age: 19,
        attack_type: "melee",
    });
}

const setUser = () => {
    $sentrySetUser({ email: '[email protected]' });
}
</script>

I do not really care about the message, so it will be fine, but I am getting the following error when I use this code: [Exeption handled by Sentry]: (TypeError: proxy set handler returned false for property '"$_sentrySpans"')

Again, it does not really make sense, but also I am not depended on it, so it will be fine for me. Just curious.. I found that it has to do with the trackComponents aprt of the tracing mixin

Harm-Nullix avatar May 26 '22 09:05 Harm-Nullix

@rchl I think to make the plugin compatible with all nuxt2/bridge and 3 should not be an issue, but I am currently a bit tight with time so will take a while until I'll have a look at it in-depth.

Just installing the @nuxt/bridge creates incompatibilities as it switches to the new h3 server-side rendering engine. I guess it's probably possible to disable h3 but then it should probably not be enabled by default IMO.

rchl avatar May 31 '22 13:05 rchl

For server side, I kinda manage to run Sentry node at bare minimum (still not working great tho, I think)

// plugins/sentry.server.ts
import * as Sentry from '@sentry/node';
import '@sentry/tracing'; // Side-effect the tracing init

export default defineNuxtPlugin(app => {
  Sentry.init({ ... });

  return {
    provide: {
      sentry: Sentry,
    }
  };
});

Combined with the sentry.client.ts above, the TS will generate the distinct type between sentry node & vue. Though, it needs a bit hack and transpilation on nuxt config

build: {
  transpile: ['@sentry/node'],
},
alias: {
  '@sentry/utils/esm/buildPolyfills.js': '@sentry/utils/esm/buildPolyfills/index.js',
},

akasection avatar Sep 02 '22 13:09 akasection

@akasection Stupid question: how did you realize you had to include @sentry/node in the build.transpile option?

ffxsam avatar Sep 02 '22 14:09 ffxsam

@akasection Stupid question: how did you realize you had to include @sentry/node in the build.transpile option?

When I tried import @sentry/node in sentry.server.ts and run nuxt build, I noticed the .output/server referenced the library, but somehow in the node_modules, the one that imported into server build is the CJS one, while the index file is .mjs (resulting runtime error).

It's still wasteful approach tho, because instead of importing the correct ESM one, it re-transpiles the CJS dist into ESM.

akasection avatar Sep 02 '22 17:09 akasection

For me, it is working in the client but not in the server. I created a plugin in sentry.server.ts with this content:

import { defineNuxtPlugin } from '#app';
// eslint-disable-next-line no-restricted-imports
import * as Sentry from '@sentry/node';
import { NODE_ENV, SENTRY_DSN } from '@/constants';

export default defineNuxtPlugin(() => {
  Sentry.init({
    logErrors: true,
    dsn: SENTRY_DSN,
    environment: NODE_ENV,
    normalizeDepth: 5,
  });
});

Does anyone know what I'm doing wrong?

andresespinosapc avatar Sep 23 '22 22:09 andresespinosapc

@andresespinosapc I have to manually pull it in from useNuxtApp(), e.g.:

import * as Sentry from '@sentry/serverless';

export default defineNuxtPlugin(() => {
  return {
    provide: { sentryServer: Sentry },
  };
});

And then in the code:

const { $sentryServer } = useNuxtApp();

ffxsam avatar Sep 26 '22 18:09 ffxsam

@andresespinosapc try transpile the @sentry/node under nuxt.config > build so it will transform into ESM one.

akasection avatar Oct 04 '22 12:10 akasection

@rchl hello there.

https://github.com/getsentry/sentry-webpack-plugin/issues/375#issuecomment-1294925936 https://github.com/getsentry/sentry-javascript-bundler-plugins

Once this new plugin is finished, will you be able to add support for Vite in this plugin?

Also, do you have any status for your Nuxt 3 migration plans? It will be out of RC pretty soon now.

daniluk4000 avatar Oct 28 '22 12:10 daniluk4000

Once this new plugin is finished, will you be able to add support for Vite in this plugin?

Same answer as in https://github.com/nuxt-community/sentry-module/issues/433#issuecomment-1263270237 but I'm sure someone could contribute to this project and it wouldn't have to be me.

Also, do you have any status for your Nuxt 3 migration plans? It will be out of RC pretty soon now.

I suppose this goes hand in hand with supporting Vite.

As far as going out of RC soon, what is your source? Nuxt 3 was supposed to be released early this year or something and yet new RC versions are coming out with breaking changes and new features (quite unusual for "RC").

Also, it's still unclear whether we can make a version that will be compatible with Nuxt Bridge and Nuxt 3 at the same time or are there still blocking issues that would required two separate versions of the module.

rchl avatar Oct 28 '22 18:10 rchl

As far as going out of RC soon, what is your source?

They said in last RC 12 that they plan to make 1-2 more RCs. That can change though, but I think this Autumn it will finally release.

breaking changes and new features

Can't argue with that.

Also, it's still unclear whether we can make a version that will be compatible with Nuxt Bridge and Nuxt 3 at the same time

Nuxt team says it is possible. Do you plan to wait until Bridge becomes stable as well and then decide?

daniluk4000 avatar Oct 28 '22 18:10 daniluk4000

Nuxt team says it is possible. Do you plan to wait until Bridge becomes stable as well and then decide?

Yes, I personally would wait for things to stabilise and for final Nuxt 3 to be released. I don't have time to deal with breaking changes and keep updating things for each RC. If someone else wants to deal with that then there is an option of contributing.

Also, last time I've tried to attempt the migration the functionality needed for this module didn't exist in bridge/Nuxt 3. At least if we want to have parity with the Nuxt 2 version we need to be able to expose Sentry instance on the server-side (server middleware specificially) and this seemed impossible before or required some weird hacks. It's possible that the situation has changed now but I haven't been keeping up with all the changes.

rchl avatar Oct 28 '22 18:10 rchl

I don't have time to deal with breaking changes and keep updating things for each RC

Fair enough.

if we want to have parity with the Nuxt 2 version

I guess if supporting both versions will stay impossible one day Nuxt 3-only version will become a needed thing. Long after stable release for the guys to have time to update.

daniluk4000 avatar Oct 28 '22 19:10 daniluk4000

https://twitter.com/nuxt_js/status/1590312836412379137

Nuxt has been mentioned as nearly-stable, and will be released as stable in the coming weeks.

+1 For nuxt 3 Support on Sentry

unr avatar Nov 09 '22 16:11 unr

FYI Nuxt 3 stable is out now

bmulholland avatar Nov 17 '22 10:11 bmulholland

https://github.com/getsentry/sentry-javascript-bundler-plugins have reached 0.1.0 version

May I suggest this solution to @rchl problem:

  • Active support Nuxt 3 with Webpack and Vite using this new plugin above (if it's usable already ofc)
  • Move Nuxt 2 branch to maintenance mode and only fix critical errors from now on and don't update to major versions of Sentry etc
  • Add Nuxt Bridge support for Nuxt 2, at least when it and 2.16 becomes stable and releases

This:

  • Will allow us to move to Nuxt 3
  • Allow you to upgrade to Nuxt 3, Sentry v7 and this new bundler plugin (w/ Vite) with any breaking changes you want
  • Will allow you to stop active support for Nuxt 2 repo but keep it working with critical-only bug fixes (which are rare I guess in current state)
  • Will allow those who stays on Nuxt 2 update to Nuxt Bridge and 2.16, as it does not supported yet

Possible version branches I see:

  • 6.0: dead branch for <= Nuxt 2.15
  • 7.0: LTS branch for Nuxt 2.16 and Bridge. IMO LTS period of 6 months will be quite enough, but you can do 12 if you can handle this
  • 8.0: major breaking changes for Nuxt 3.0, Sentry v7 and bundler plugin support with Vite/Webpack

I'm not sure if 7.0 really needed, as I can't quite understand if upgrading this module to Bridge will inproduce breaking changes. As I could see from other libs, their Bridge version could even be minor one with no breaking changes.

Possible variants I see now:

  • If Nuxt Bridge requires breaking changes, upgrade to unstable version in 7.0 and to Nuxt 3 in 8.0
  • If Nuxt Bridge does not require breaking changes, skip it for now and wait for stable version, and upgrade to Nuxt 3 in 7.0
  • If you are not sure yet about Nuxt Bridge at all, wait until it becomes full stable and then choose from those two options above. But this'll leave all Nuxt 3 users without one very cool Sentry plugin

I hope I did help in any way with most of your concerns about this lib.

daniluk4000 avatar Nov 17 '22 10:11 daniluk4000