getsentry / sentry-javascript

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

[NUXT] Can't get the sourcemaps to work. #13847

Open z0lo13 opened 3 weeks ago

z0lo13 commented 3 weeks ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nuxt

SDK Version

8.32.0

Framework Version

Nuxt 3.13.2

Link to Sentry event

https://market-wiz.sentry.io/issues/5937402524/?project=4507160564858880&query=is%3Aunresolved%20issue.priority%3A%5Bhigh%2C%20medium%5D&referrer=issue-stream&statsPeriod=24h&stream_index=1

Reproduction Example/SDK Setup

in nuxt.config.ts

sentry: {
    sourceMapsUploadOptions: {
      authToken: "",
      org: "market-wiz",
      project: "hmc-crm-nuxt",
    },
  },
....
sourcemap: {
    server: true,
    client: true,
  },
modules: [
    ....,
    '@sentry/nuxt/module'
  ],
....

sentry.client.config.ts

import * as Sentry from '@sentry/nuxt';
const router = useRouter()
const { public: { sentry } } = useRuntimeConfig()
Sentry.init({
    // If set up, you can use your runtime config here
    dsn: sentry.dsn,
    environment: sentry.environment,
    enabled: process.env.enviroment !== 'development',
    integrations: [
        Sentry.browserTracingIntegration({ router }),
        Sentry.replayIntegration({
            maskAllInputs: false,
            maskAllText: false,
        })
    ],
    tracesSampleRate: 0.2,
    replaysSessionSampleRate: 0,
    replaysOnErrorSampleRate: 1.0,
});

Also during the build the following warnings outputed:

[info] Building client...
[info] vite v5.4.8 building for production...
[sentry-vite-plugin] Info: Sending telemetry data on issues and performance to Sentry. To disable telemetry, set `options.telemetry` to `false`.
[info] ✓ 3269 modules transformed.
[info] rendering chunks...
[sentry-vite-plugin] Warning: Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option.
[info] ✓ built in 1m 12s
[success] Client built in 71526ms
[info] Building server...
[info] vite v5.4.8 building SSR bundle for production...
[sentry-vite-plugin] Info: Sending telemetry data on issues and performance to Sentry. To disable telemetry, set `options.telemetry` to `false`.
[info] transforming...
...
[sentry-vite-plugin] Warning: Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option.
[info] ✓ built in 1m 12s
[success] Server built in 72312ms
[success] [nitro] Generated public .output/public
[info] [nitro] Building Nuxt Nitro server (preset: `node-server`)
[sentry-rollup-plugin] Info: Sending telemetry data on issues and performance to Sentry. To disable telemetry, set `options.telemetry` to `false`.
> Found 1072 files
> Analyzing 1072 sources
> Adding source map references
> Bundled 1072 files for upload
> Bundle ID: 544229cf-c1a2-58d3-80f4-df4de27ff355
> Uploaded files to Sentry
> File upload complete (processing pending on server)
> Organization: market-wiz
> Project: ***-nuxt
> Release: 357334fc5e7d729e8f2a12e5d7642f06c94d9a23
> Dist: None
> Upload type: artifact bundle
Source Map Upload Report
.....

Steps to Reproduce

<script setup>
  const triggerError = () => {
    throw new Error("Nuxt Button Error");
  };
</script>

<template>
  <button id="errorBtn" @click="triggerError">Trigger Error</button>
</template>

Expected Result

Have sourcemaps linked

Actual Result

Seems to me that only server-side sourcemaps are uploaded.

z0lo13 commented 3 weeks ago

I have found the woraround.

Instead of initializing the plugin inside the nuxt.config.ts, i created a client plugin with the following:

import * as Sentry from '@sentry/vue'

export default defineNuxtPlugin((nuxtApp) => {
    const router = useRouter()
    const { public: { sentry } } = useRuntimeConfig()

    if (!sentry.dsn) {
        return
    }
    Sentry.init({
        app: nuxtApp.vueApp,
        dsn: sentry.dsn,
        environment: sentry.environment,
        integrations: [
            Sentry.browserTracingIntegration({ router }),
            Sentry.replayIntegration({
                maskAllInputs: false,
                maskAllText: false,
            })
        ],

        tracesSampleRate: 0.2, // Change in prod
        replaysSessionSampleRate: 0, // Change in prod
        replaysOnErrorSampleRate: 1.0, // Change in prod if necessary
    })
})

server plugin:

import * as Sentry from '@sentry/node'
import {
    nodeProfilingIntegration,
} from '@sentry/profiling-node'
import { H3Error } from 'h3'

export default defineNitroPlugin((nitroApp) => {
    const { public: { sentry } } = useRuntimeConfig()

    if (!sentry.dsn) {
        console.warn('Sentry DSN not set, skipping Sentry initialization')
        return
    }

    Sentry.init({
        dsn: sentry.dsn,
        environment: sentry.environment,
        integrations: [
            nodeProfilingIntegration(),
        ],
        // Performance Monitoring
        tracesSampleRate: 0.2,
        // Set sampling rate for profiling - this is relative to tracesSampleRate
        profilesSampleRate: 0.2,
    })

    nitroApp.hooks.hook('error', (error) => {
        // Do not handle 404s and 422s
        if (error instanceof H3Error) {
            if (error.statusCode === 404 || error.statusCode === 422) {
                return
            }
        }
        // checkf if error is not about missing .map file
        if (error.message && error.message.includes('.map')) {
            return
        }

        Sentry.captureException(error)
    })

    nitroApp.hooks.hook('request', (event) => {
        event.context.$sentry = Sentry
    })

    nitroApp.hooks.hookOnce('close', async () => {
        await Sentry.close(2000)
    })
})

Inside my nuxt.config.ts

do not add anything under modules, but:

vite: {
    plugins: [
      // Put the Sentry vite plugin after all other plugins
      sentryVitePlugin({
        disable: process.env.NODE_ENV === 'development',
        authToken: "",
        org: "market-wiz",
        project: "hmc-crm-nuxt",
        telemetry: false,
      }),
    ],
}

However, the @sentry/vue does throw a 500 full page error, which is not the wanted behaviour, and the @sentry/nuxt have it fixed. Therefore as for now it is impossible to fully use sentry with nuxt

s1gr1d commented 3 weeks ago

Hello, thanks for reaching out! I looked at your linked Sentry event and the error message contains 'toISOString', which is not in your provided reproduction snippet. To be able to look at this, a larger reproduction example would be awesome! :)

In general, the Sentry Nuxt SDK uploads source maps for both client and server. That is done in multiple uploads as we have to use the Vite and the Rollup plugin to upload all of them. By just using the Vite plugin you wouldn't get the source maps for the Nitro-part of your application.

z0lo13 commented 1 week ago

@s1gr1d that the function that throws an error. The error is only an example, as the sourcemaps does not work, it does not matter what sentry event it is, they are just not being linked properly.

toISOString('xya')

s1gr1d commented 1 week ago

Sadly, I cannot reproduce this issue. I guess you already checked that, but the source maps upload needs org, project and authToken to be set. Just to make sure it's not missing :) Another thing you could try is upgrading to at least v8.33.0 as I changed the source maps upload a bit in this release.