nuxt-community / sentry-module

Sentry module for Nuxt 2
https://sentry.nuxtjs.org
MIT License
500 stars 113 forks source link

In SSR side with Latest version (7.1.10) with tracing option is crashed #546

Closed buglavecz closed 1 year ago

buglavecz commented 1 year ago

Version

@nuxtjs/sentry: 7.1.10 nuxt: 2.16.3

Sentry configuration

not working:

sentry: {
        dsn: process.env.SENTRY_DSN_VUE,
        config: {
            debug: true,
            normalizeDepth: 6,
            release: `xy@${process.env.COMMIT_HASH || (process.env.NODE_ENV === 'development' ? 'local' : 'unknown')}`,
        },

        clientConfig: {
            allowUrls: ['xy.local','xy.com'],
        },
        clientIntegrations: {
            CaptureConsole: {
                levels: ['error']
            },
            ReportingObserver: {
                types: ['crash']
            }
        },
        serverIntegrations: {
            CaptureConsole: {
                levels: ['error']
            }
        },
        tracing: {
            tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.00001 : 1,
            vueOptions: {
                tracing: true,
                hooks: ['activate', 'mount', 'update'],
                timeout: 2000,
                trackComponents: true
            },
            browserTracing: {
                tracePropagationTargets: ['xy.local', 'xy.com', /^\//],
            }
        },
    },

working:

sentry: {
        dsn: process.env.SENTRY_DSN_VUE,
        config: {
            debug: true,
            normalizeDepth: 6,
            release: `xy@${process.env.COMMIT_HASH || (process.env.NODE_ENV === 'development' ? 'local' : 'unknown')}`,
        },

        clientConfig: {
            allowUrls: ['xy.local','xy.com'],
        },
        clientIntegrations: {
            CaptureConsole: {
                levels: ['error']
            },
            ReportingObserver: {
                types: ['crash']
            }
        },
        serverIntegrations: {
            CaptureConsole: {
                levels: ['error']
            }
        },
       /* tracing: {
            tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.00001 : 1,
            vueOptions: {
                tracing: true,
                hooks: ['activate', 'mount', 'update'],
                timeout: 2000,
                trackComponents: true
            },
            browserTracing: {
                tracePropagationTargets: ['xy.local', 'xy.com', /^\//],
            }
        },*/
    },

Reproduction Link

Steps to reproduce

What is Expected?

no error

What is actually happening?

image

rchl commented 1 year ago

Can you provide rest of your nuxt.config? You can filter out any sensitive info.

buglavecz commented 1 year ago

sentry tracing version: "@sentry/tracing": "^7.46.0",

buglavecz commented 1 year ago

plus info: this error come only in dev mode. in prod build working fine.

why? 🐛

rchl commented 1 year ago

Sorry, still can't reproduce.

Could you open the node_modules/@nuxtjs/sentry/dist/templates/plugin.server.js file in your editor and figure out where it crashes by editing it manually? You can either add console.log in various places or just null-check stuff and return early.

You could for example change it like so which should give some clue in the terminal when it crashes.

diff --git a/src/templates/plugin.server.js b/src/templates/plugin.server.js
index c24a705..03a2ec8 100644
--- a/src/templates/plugin.server.js
+++ b/src/templates/plugin.server.js
@@ -28,15 +28,18 @@ function connectBackendTraces (ctx) {
     return
   }
   const scope = ctx.$sentry.getCurrentHub().getScope()
+  console.info({scope})
   const span = scope.getSpan()
   const transaction = scope.getTransaction()
   if (!span || !transaction) {
     return
   }
   head.meta = head.meta || []
+  console.info({ 'head.meta': head.meta })
   head.meta.push({ hid: 'sentry-trace', name: 'sentry-trace', content: span.toTraceparent() })
   const dsc = transaction.getDynamicSamplingContext()
   if (dsc) {
+    console.info({dsc})
     head.meta.push({ hid: 'sentry-baggage', name: 'baggage', content: dynamicSamplingContextToSentryBaggageHeader(dsc) })
   }
 }
buglavecz commented 1 year ago

hi @rchl this is the output of your suggested console.logs:

i {                                                                                                                                                                                                                                                             08:59:00
  scope: Scope {
    _notifyingListeners: false,
    _scopeListeners: [],
    _eventProcessors: [],
    _breadcrumbs: [
      [Object]
    ],
    _attachments: [],
    _user: {},
    _tags: {},
    _extra: {},
    _contexts: {},
    _sdkProcessingMetadata: {
      request: [IncomingMessage],
      requestDataOptionsFromExpressHandler: undefined
    },
    _level: undefined,
    _span: <ref *1> Transaction {
      traceId: 'c09d07ec1e6c47af94d6d1da84a12a62',
      spanId: '8aeca7740bcc54f7',
      startTimestamp: 1680505138.5351233,
      tags: {},
      data: {},
      instrumenter: 'sentry',
      op: 'http.server',
      _measurements: {},
      _contexts: {},
      _frozenDynamicSamplingContext: undefined,
      _hub: [Hub],
      _name: 'GET /n/dashboard',
      metadata: [Object],
      _trimEnd: undefined,
      transaction: [Circular *1],
      sampled: true,
      spanRecorder: [SpanRecorder]
    },
    _session: undefined,
    _transactionName: undefined,
    _fingerprint: undefined,
    _requestSession: {
      status: 'ok'
    }
  }
}
i {                                                                                                                                                                                                                                                             08:59:00
  'head.meta': [
    {
      charset: 'utf-8'
    },
    {
      name: 'viewport',
      content: 'width=device-width, initial-scale=1'
    },
    {
      hid: 'description',
      name: 'description',
      content: ''
    },
    {
      name: 'format-detection',
      content: 'telephone=no'
    },
    {
      name: 'build-version',
      content: 'dev-local.0123456'
    }
  ]
}
i {                                                                                                                                                                                                                                                             08:59:00
  dsc: {
    environment: 'development',
    release: 'xxxx@dev-local.0123456',
    public_key: 'c2313c5e84074184aff89a0ebbe4637b',
    trace_id: 'c09d07ec1e6c47af94d6d1da84a12a62',
    sample_rate: '1'
  }
}
rchl commented 1 year ago

In that case I think it must be dynamicSamplingContextToSentryBaggageHeader that is not a function.

Could you also log console.info(dynamicSamplingContextToSentryBaggageHeader) below last console.info?

rchl commented 1 year ago

If that one is undefined or null then can you provide output of yarn why @sentry/utils (or npm why @sentry/utils if using npm)?

buglavecz commented 1 year ago

yes undefined.

the yarn why @sentry/utils output:

$ yarn why @sentry/utils
yarn why v1.22.19
[1/4] Why do we have the module "@sentry/utils"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
[4/4] Calculating file sizes...
=> Found "@sentry/utils@7.46.0"
info Reasons this module exists
   - "@nuxtjs#sentry" depends on it
   - Hoisted from "@nuxtjs#sentry#@sentry#utils"
   - Hoisted from "@sentry#tracing#@sentry-internal#tracing#@sentry#utils"
   - Hoisted from "@nuxtjs#sentry#@sentry#integrations#@sentry#utils"
   - Hoisted from "@nuxtjs#sentry#@sentry#node#@sentry#utils"
   - Hoisted from "@nuxtjs#sentry#@sentry#vue#@sentry#utils"
   - Hoisted from "@nuxtjs#sentry#@sentry#vue#@sentry#browser#@sentry#utils"
   - Hoisted from "@sentry#tracing#@sentry-internal#tracing#@sentry#core#@sentry#utils"
   - Hoisted from "@nuxtjs#sentry#@sentry#vue#@sentry#browser#@sentry#replay#@sentry#utils"
info Disk size without dependencies: "1.64MB"
info Disk size with unique dependencies: "2.11MB"
info Disk size with transitive dependencies: "2.11MB"
info Number of shared dependencies: 2
Done in 0.91s.
buglavecz commented 1 year ago

if this line disabled: //head.meta.push({ hid: 'sentry-baggage', name: 'baggage', content: dynamicSamplingContextToSentryBaggageHeader(dsc) })

working fine.

rchl commented 1 year ago

Shot in the dark: can you try yarn upgrade @nuxtjs/sentry? It might help if sentry SDK packages are at different versions now.

rchl commented 1 year ago

Can you also post the contents of .nuxt/sentry.client.js to make sure it doesn't miss anything?

buglavecz commented 1 year ago

Shot in the dark: can you try yarn upgrade @nuxtjs/sentry? It might help if sentry SDK packages are at different versions now.

this is not resolved the error.

buglavecz commented 1 year ago
/* eslint-disable import/order */
import Vue from 'vue'
import merge from '~lodash.mergewith'
import * as Sentry from '~@sentry/vue'
import { BrowserTracing } from '~@sentry/tracing'
import { vueRouterInstrumentation } from '~@sentry/vue'
import { CaptureConsole, ExtraErrorData, ReportingObserver, RewriteFrames } from '~@sentry/integrations'

export default async function (ctx, inject) {
  /* eslint-disable object-curly-spacing, quote-props, quotes, key-spacing, comma-spacing */
  const config = {
    Vue,
    dsn:"https:\u002F\u002Fc2313c5e84074184aff89a0ebbe4637b@o44978.ingest.sentry.io\u002F4504298700865536",
    environment:"development",
    normalizeDepth:6,
    release:"xxx@dev-local.0123456",
    allowUrls:["nuxt.xxx.local","app.xxx.hu"],
    tracesSampleRate:1,
  }

  config.integrations = [
    new ExtraErrorData(),
    new ReportingObserver({ types:["crash"] }),
    new RewriteFrames(),
    new CaptureConsole({ levels:["error"] }),
  ]

  // eslint-disable-next-line prefer-regex-literals
  const { browserTracing, vueOptions, ...tracingOptions } = {"tracesSampleRate":1,"browserTracing":{"tracePropagationTargets":["nuxt.xxx.local","app.xxx.hu",new RegExp("^\\\u002F", "")]},"vueOptions":{"trackComponents":true,"tracing":true,"hooks":["activate","mount","update"],"timeout":2000}}
  config.integrations.push(new BrowserTracing({
    ...(ctx.app.router ? { routingInstrumentation: vueRouterInstrumentation(ctx.app.router) } : {}),
    ...browserTracing,
  }))
  merge(config, vueOptions, tracingOptions)

  const runtimeConfigKey = "sentry"
  if (ctx.$config && runtimeConfigKey && ctx.$config[runtimeConfigKey]) {
    merge(config, ctx.$config[runtimeConfigKey].config, ctx.$config[runtimeConfigKey].clientConfig)
  }

  /* eslint-enable object-curly-spacing, quote-props, quotes, key-spacing, comma-spacing */
  Sentry.init(config)
  inject('sentry', Sentry)
  ctx.$sentry = Sentry
}
rchl commented 1 year ago

Ops, sorry, I meant .nuxt/sentry.server.js

buglavecz commented 1 year ago
import { dynamicSamplingContextToSentryBaggageHeader } from '~@sentry/utils'

/** @type {import('@nuxt/types').Module} */
export default function (ctx, inject) {
  const sentry = process.sentry || null
  if (!sentry) {
    return
  }
  inject('sentry', sentry)
  ctx.$sentry = sentry

  connectBackendTraces(ctx)
}

function connectBackendTraces (ctx) {
  const { head } = ctx.app
  if (!head || head instanceof Function) {
    console.warn('[@nuxtjs/sentry] can not connect backend and frontend traces because app.head is a function or missing!')
    return
  }
  const scope = ctx.$sentry.getCurrentHub().getScope()
  const span = scope.getSpan()
  const transaction = scope.getTransaction()
  if (!span || !transaction) {
    return
  }
  head.meta = head.meta || []
  head.meta.push({ hid: 'sentry-trace', name: 'sentry-trace', content: span.toTraceparent() })
  const dsc = transaction.getDynamicSamplingContext()
  if (dsc) {
    head.meta.push({ hid: 'sentry-baggage', name: 'baggage', content: dynamicSamplingContextToSentryBaggageHeader(dsc) })
  }
}
rchl commented 1 year ago

It's just bizzare. It shouldn't be possible that dynamicSamplingContextToSentryBaggageHeader is undefined since it's an export that is present in @sentry/utils.

I'm now thinking that it's some sort of a Nuxt/jiti caching issue so I would suggest that you try to remove and reinstall node_modules.

rm -rf node_modules && yarn
buglavecz commented 1 year ago

ok. I try. thanks

buglavecz commented 1 year ago

not workink. I don't understand... why? 😢

buglavecz commented 1 year ago

in this file: .nuxt/sentry.server.js I commented this line, working fine:

if (dsc) {
    // head.meta.push({ hid: 'sentry-baggage', name: 'baggage', content: dynamicSamplingContextToSentryBaggageHeader(dsc) })
  }
buglavecz commented 1 year ago

in this file: .nuxt/sentry.server.js when I remove ~ this alias from import: import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils'

working fine.

buglavecz commented 1 year ago

in dev mode import nuxt does'nt find this @sentry/utils dep. in root dir. i don't understand, but production mode find it? 🤔

rchl commented 1 year ago

in this file: .nuxt/sentry.server.js I commented this line, working fine:

Yes, but it's not a solution. It's just avoiding the problem by disabling functionality.

when I remove ~ this alias from import: import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils'

working fine.

Some things to try.

  1. In node_modules/@nuxtjs/sentry/lib/module.js add a log:
@@ -89,6 +89,7 @@ export default defineNuxtModule<ModuleConfiguration>({
     for (const dep of aliasedDependencies) {
       nuxt.options.alias[`~${dep}`] = (await resolvePath(dep)).replace(/\/cjs\//, '/esm/')
     }
+    console.info({ 'nuxt.options.alias': nuxt.options.alias })

     if (serverSentryEnabled(options)) {
       /**
  1. Provide output of this command:
tree node_modules/@sentry/utils/esm
buglavecz commented 1 year ago

yes I know. okay I do.

buglavecz commented 1 year ago

we have a monorepo in thi project. this is the folder structure:

projects 
     |- xxx
          |- ...
               |- client (nuxt folder)
                      |- node_modules      
               |- node_modules

the result of console info. i develop on windows.

i {                                                                                                                                                                                                                                    11:19:45
  'nuxt.options.alias': {
    '~~': 'C:\\projects\\xxx\\client',
    '@@': 'C:\\projects\\xxx\\client',
    '~': 'C:\\projects\\xxx\\client',
    '@': 'C:\\projects\\xxx\\client',
    assets: 'C:\\projects\\xxx\\client\\assets',
    static: 'C:\\projects\\xxx\\client\\static',
    '@nuxt-components': 'C:\\projects\\xxx\\client\\components',
    '@nuxt-mixins': 'C:\\projects\\xxx\\client\\mixins',
    '@nuxt-assets': 'C:\\projects\\xxx\\client\\assets',
    '@nuxt-helpers': 'C:\\projects\\xxx\\client\\helpers',
    '@nuxt-server-data': 'C:\\projects\\xxx\\client\\server-data',
    '@nuxt-store': 'C:\\projects\\xxx\\client\\store',
    '@nuxt-mock-data': 'C:\\projects\\xxx\\client\\mock-data',
    '@nuxt-configs': 'C:\\projects\\xxx\\client\\configs',
    '@nuxt-models': 'C:\\projects\\xxx\\client\\models',
    '~i18n-klona': 'C:\\projects\\xxx\\client\\node_modules\\klona\\full\\index.mjs',
    '~i18n-ufo': 'C:\\projects\\xxx\\client\\node_modules\\@nuxtjs\\i18n\\node_modules\\ufo\\dist\\index.cjs',
    '~lodash.mergewith': 'C:/projects/xxx/client/node_modules/lodash.mergewith/index.js',
    '~@sentry/integrations': 'C:/projects/xxx/client/node_modules/@sentry/integrations/esm/index.js',
    '~@sentry/utils': 'C:/projects/xxx/node_modules/@sentry/utils/dist/index.js',     <-------- THIS IS THE PROBLEM
    '~@sentry/vue': 'C:/projects/xxx/node_modules/@sentry/vue/dist/index.js',
    '~@sentry/tracing': 'C:/projects/xxx/node_modules/@sentry/tracing/dist/index.js'
  }
}
rchl commented 1 year ago

Oh, so @sentry/utils is not actually resolved properly and in that case it defaults to dist/index.js...? Seems weird. I will have to try to reproduce it somehow.

Or does your repo setup actually include some old versions of @sentry/utils (v6) that get picked up instead? I think this might be the case actually.

buglavecz commented 1 year ago

we have in root folder also a laravel-mix vue solution, in this project use this: node_modules/@sentry/utils (v6) nuxt why resolving these aliases to these paths?

'~@sentry/utils': 'C:/projects/xxx/node_modules/@sentry/utils/dist/index.js',
    '~@sentry/vue': 'C:/projects/xxx/node_modules/@sentry/vue/dist/index.js',
    '~@sentry/tracing': 'C:/projects/xxx/node_modules/@sentry/tracing/dist/index.js'

I don't understand. 🤔

rchl commented 1 year ago

I think that this should fix it: https://github.com/nuxt-community/sentry-module/pull/548

rchl commented 1 year ago

Are you able to apply those changes manually and do a quick test before I commit and release it?

buglavecz commented 1 year ago

In production the project run under docker container, there is no pick up, because there in upper level node_modules folder is "not exists". This is the reason, that in prod mode workink fine. I think...

buglavecz commented 1 year ago

Are you able to apply those changes manually and do a quick test before I commit and release it?

yes. one moment please.

buglavecz commented 1 year ago

yess. 🎉 working fine. the aliases is already good console.info result:

    '~@sentry/utils': 'C:/projects/xxx/client/node_modules/@sentry/utils/esm/index.js',
    '~@sentry/vue': 'C:/projects/xxx/client/node_modules/@sentry/vue/esm/index.js',
    '~@sentry/tracing': 'C:/projects/xxx/client/node_modules/@sentry/tracing/esm/index.js'
buglavecz commented 1 year ago

when do you do a release with this?

buglavecz commented 1 year ago

@rchl Thank you for your support! 🖖

rchl commented 1 year ago

Thanks for helping find out what the issue is.

Released in https://github.com/nuxt-community/sentry-module/releases/tag/v7.1.11