1
1
import { registerInstrumentations } from '@opentelemetry/instrumentation' ;
2
- import type { FastifyRequestInfo } from '@opentelemetry/instrumentation-fastify' ;
3
2
import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify' ;
4
- import { captureException , defineIntegration , getIsolationScope , spanToJSON } from '@sentry/core' ;
3
+ import { captureException , defineIntegration , getCurrentScope , getIsolationScope } from '@sentry/core' ;
5
4
import type { IntegrationFn } from '@sentry/types' ;
6
5
7
- import type { Span } from '@opentelemetry/api' ;
8
6
import { addOriginToSpan } from '../../utils/addOriginToSpan' ;
9
7
10
8
const _fastifyIntegration = ( ( ) => {
@@ -14,9 +12,8 @@ const _fastifyIntegration = (() => {
14
12
registerInstrumentations ( {
15
13
instrumentations : [
16
14
new FastifyInstrumentation ( {
17
- requestHook ( span , info ) {
15
+ requestHook ( span ) {
18
16
addOriginToSpan ( span , 'auto.http.otel.fastify' ) ;
19
- updateScopeTransactionName ( span , info ) ;
20
17
} ,
21
18
} ) ,
22
19
] ,
@@ -25,22 +22,6 @@ const _fastifyIntegration = (() => {
25
22
} ;
26
23
} ) satisfies IntegrationFn ;
27
24
28
- function updateScopeTransactionName ( span : Span , info : FastifyRequestInfo ) : void {
29
- if ( ! span . isRecording ( ) ) {
30
- return ;
31
- }
32
-
33
- const attributes = spanToJSON ( span ) . data ;
34
- if ( ! attributes || ! attributes [ 'http.route' ] ) {
35
- return ;
36
- }
37
-
38
- const req = info . request as { method ?: string } ;
39
- const method = req . method ?. toUpperCase ( ) || 'GET' ;
40
- const route = String ( attributes [ 'http.route' ] ) ;
41
- getIsolationScope ( ) . setTransactionName ( `${ method } ${ route } ` ) ;
42
- }
43
-
44
25
/**
45
26
* Express integration
46
27
*
@@ -54,6 +35,19 @@ interface Fastify {
54
35
addHook : ( hook : string , handler : ( request : unknown , reply : unknown , error : Error ) => void ) => void ;
55
36
}
56
37
38
+ /**
39
+ * Minimal request type containing properties around route information.
40
+ * Works for Fastify 3, 4 and presumably 5.
41
+ */
42
+ interface FastifyRequestRouteInfo {
43
+
44
+ routeOptions ?: {
45
+ url ?: string ;
46
+ method ?: string ;
47
+ } ;
48
+ routerPath ?: string ;
49
+ }
50
+
57
51
/**
58
52
* Setup an error handler for Fastify.
59
53
*/
@@ -64,6 +58,20 @@ export function setupFastifyErrorHandler(fastify: Fastify): void {
64
58
captureException ( error ) ;
65
59
} ) ;
66
60
61
+ // registering `onRequest` hook here instead of using Otel `onRequest` callback b/c `onRequest` hook
62
+ // is ironically called in the fastify `preHandler` hook which is called later in the lifecycle:
63
+ // https://fastify.dev/docs/latest/Reference/Lifecycle/
64
+ fastify . addHook ( 'onRequest' , async ( request , _reply ) => {
65
+ const reqWithRouteInfo = request as FastifyRequestRouteInfo ;
66
+
67
+ // Taken from Otel Fastify instrumentation:
68
+ // https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/plugins/node/opentelemetry-instrumentation-fastify/src/instrumentation.ts#L94-L96
69
+ const routeName = reqWithRouteInfo . routeOptions ?. url || reqWithRouteInfo . routerPath ;
70
+ const method = reqWithRouteInfo . routeOptions ?. method || 'GET' ;
71
+
72
+ getIsolationScope ( ) . setTransactionName ( `${ method } ${ routeName } ` ) ;
73
+ } ) ;
74
+
67
75
done ( ) ;
68
76
} ,
69
77
{
0 commit comments