1
1
import consola from 'consola'
2
2
import merge from 'lodash.mergewith'
3
- import { Handlers as SentryHandlers , captureException , withScope } from '@sentry/node'
3
+ import { captureException , withScope } from '@sentry/node'
4
4
import { buildHook , initializeServerSentry , shutdownServerSentry , webpackConfigHook } from './core/hooks'
5
- import { boolToText , canInitialize , clientSentryEnabled , envToBool , serverSentryEnabled } from './core/utils'
5
+ import { boolToText , callOnce , canInitialize , clientSentryEnabled , envToBool , serverSentryEnabled } from './core/utils'
6
6
7
7
const logger = consola . withScope ( 'nuxt:sentry' )
8
8
@@ -73,21 +73,6 @@ export default function SentryModule (moduleOptions) {
73
73
options . publishRelease = merged
74
74
}
75
75
76
- if ( serverSentryEnabled ( options ) ) {
77
- // @ts -ignore
78
- this . nuxt . hook ( 'render:setupMiddleware' , app => app . use ( SentryHandlers . requestHandler ( options . requestHandlerConfig ) ) )
79
- // @ts -ignore
80
- this . nuxt . hook ( 'render:errorMiddleware' , app => app . use ( SentryHandlers . errorHandler ( ) ) )
81
- // @ts -ignore
82
- this . nuxt . hook ( 'generate:routeFailed' , ( { route, errors } ) => {
83
- // @ts -ignore
84
- errors . forEach ( ( { error } ) => withScope ( ( scope ) => {
85
- scope . setExtra ( 'route' , route )
86
- captureException ( error )
87
- } ) )
88
- } )
89
- }
90
-
91
76
if ( canInitialize ( options ) && ( clientSentryEnabled ( options ) || serverSentryEnabled ( options ) ) ) {
92
77
const status = `(client side: ${ boolToText ( clientSentryEnabled ( options ) ) } , server side: ${ boolToText ( serverSentryEnabled ( options ) ) } )`
93
78
logger . success ( `Sentry reporting is enabled ${ status } ` )
@@ -105,21 +90,45 @@ export default function SentryModule (moduleOptions) {
105
90
logger . info ( `Sentry reporting is disabled (${ why } )` )
106
91
}
107
92
108
- this . nuxt . hook ( 'build:before' , ( ) => buildHook ( this , options , logger ) )
93
+ this . nuxt . hook ( 'build:before' , callOnce ( ( ) => buildHook ( this , options , logger ) ) )
109
94
110
- // This is messy but Nuxt provides many modes that it can be started with like:
111
- // - nuxt dev
112
- // - nuxt build
113
- // - nuxt start
114
- // - nuxt generate
115
- // but it doesn't really provide great way to differentiate those or enough hooks to
116
- // pick from. This should ensure that server Sentry will only be initialized **after**
117
- // the release version has been determined and the options template created but before
118
- // the build is started (if building).
119
- const initHook = this . options . _build ? 'build:compile' : 'ready'
120
95
if ( serverSentryEnabled ( options ) ) {
121
- this . nuxt . hook ( initHook , ( ) => initializeServerSentry ( this , options , logger ) )
122
- this . nuxt . hook ( 'generate:done' , ( ) => shutdownServerSentry ( ) )
96
+ /**
97
+ * Proxy that provides a dummy request handler before Sentry is initialized and gets replaced with Sentry's own
98
+ * handler after initialization. Otherwise server-side request tracing would not work as it depends on Sentry being
99
+ * initialized already during handler creation.
100
+ * @type {import('../types/sentry').SentryHandlerProxy }
101
+ */
102
+ const sentryHandlerProxy = {
103
+ errorHandler : ( error , req , res , next ) => { next ( error ) } ,
104
+ requestHandler : ( req , res , next ) => { next ( ) } ,
105
+ }
106
+ // @ts -ignore
107
+ this . nuxt . hook ( 'render:setupMiddleware' , app => app . use ( ( req , res , next ) => { sentryHandlerProxy . requestHandler ( req , res , next ) } ) )
108
+ // @ts -ignore
109
+ this . nuxt . hook ( 'render:errorMiddleware' , app => app . use ( ( error , req , res , next ) => { sentryHandlerProxy . errorHandler ( error , req , res , next ) } ) )
110
+ // @ts -ignore
111
+ this . nuxt . hook ( 'generate:routeFailed' , ( { route, errors } ) => {
112
+ // @ts -ignore
113
+ errors . forEach ( ( { error } ) => withScope ( ( scope ) => {
114
+ scope . setExtra ( 'route' , route )
115
+ captureException ( error )
116
+ } ) )
117
+ } )
118
+ // This is messy but Nuxt provides many modes that it can be started with like:
119
+ // - nuxt dev
120
+ // - nuxt build
121
+ // - nuxt start
122
+ // - nuxt generate
123
+ // but it doesn't really provide great way to differentiate those or enough hooks to
124
+ // pick from. This should ensure that server Sentry will only be initialized **after**
125
+ // the release version has been determined and the options template created but before
126
+ // the build is started (if building).
127
+ const initHook = this . options . _build ? 'build:compile' : 'ready'
128
+ this . nuxt . hook ( initHook , callOnce ( ( ) => initializeServerSentry ( this , options , sentryHandlerProxy , logger ) ) )
129
+ const shutdownServerSentryOnce = callOnce ( ( ) => shutdownServerSentry ( ) )
130
+ this . nuxt . hook ( 'generate:done' , shutdownServerSentryOnce )
131
+ this . nuxt . hook ( 'close' , shutdownServerSentryOnce )
123
132
}
124
133
125
134
// Enable publishing of sourcemaps
0 commit comments