@sentry/react-router 9.17.0 → 9.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/build/cjs/server/instrumentation/reactRouter.js +103 -0
  2. package/build/cjs/server/instrumentation/reactRouter.js.map +1 -0
  3. package/build/cjs/server/instrumentation/util.js +63 -0
  4. package/build/cjs/server/instrumentation/util.js.map +1 -0
  5. package/build/cjs/server/integration/reactRouterServer.js +34 -0
  6. package/build/cjs/server/integration/reactRouterServer.js.map +1 -0
  7. package/build/cjs/server/lowQualityTransactionsFilterIntegration.js +40 -0
  8. package/build/cjs/server/lowQualityTransactionsFilterIntegration.js.map +1 -0
  9. package/build/cjs/server/sdk.js +44 -0
  10. package/build/cjs/server/sdk.js.map +1 -1
  11. package/build/cjs/server/wrapSentryHandleRequest.js +3 -0
  12. package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
  13. package/build/esm/package.json +1 -1
  14. package/build/esm/server/instrumentation/reactRouter.js +101 -0
  15. package/build/esm/server/instrumentation/reactRouter.js.map +1 -0
  16. package/build/esm/server/instrumentation/util.js +56 -0
  17. package/build/esm/server/instrumentation/util.js.map +1 -0
  18. package/build/esm/server/integration/reactRouterServer.js +31 -0
  19. package/build/esm/server/integration/reactRouterServer.js.map +1 -0
  20. package/build/esm/server/lowQualityTransactionsFilterIntegration.js +38 -0
  21. package/build/esm/server/lowQualityTransactionsFilterIntegration.js.map +1 -0
  22. package/build/esm/server/sdk.js +46 -3
  23. package/build/esm/server/sdk.js.map +1 -1
  24. package/build/esm/server/wrapSentryHandleRequest.js +4 -1
  25. package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
  26. package/build/types/server/instrumentation/reactRouter.d.ts +19 -0
  27. package/build/types/server/instrumentation/reactRouter.d.ts.map +1 -0
  28. package/build/types/server/instrumentation/util.d.ts +31 -0
  29. package/build/types/server/instrumentation/util.d.ts.map +1 -0
  30. package/build/types/server/integration/reactRouterServer.d.ts +8 -0
  31. package/build/types/server/integration/reactRouterServer.d.ts.map +1 -0
  32. package/build/types/server/lowQualityTransactionsFilterIntegration.d.ts +3 -0
  33. package/build/types/server/lowQualityTransactionsFilterIntegration.d.ts.map +1 -0
  34. package/build/types/server/sdk.d.ts +6 -0
  35. package/build/types/server/sdk.d.ts.map +1 -1
  36. package/build/types/server/wrapSentryHandleRequest.d.ts.map +1 -1
  37. package/package.json +5 -4
@@ -0,0 +1,103 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const instrumentation = require('@opentelemetry/instrumentation');
4
+ const core = require('@sentry/core');
5
+ const debugBuild = require('../../common/debug-build.js');
6
+ const util = require('./util.js');
7
+
8
+ const supportedVersions = ['>=7.0.0'];
9
+ const COMPONENT = 'react-router';
10
+
11
+ /**
12
+ * Instrumentation for React Router's server request handler.
13
+ * This patches the requestHandler function to add Sentry performance monitoring for data loaders.
14
+ */
15
+ class ReactRouterInstrumentation extends instrumentation.InstrumentationBase {
16
+ constructor(config = {}) {
17
+ super('ReactRouterInstrumentation', core.SDK_VERSION, config);
18
+ }
19
+
20
+ /**
21
+ * Initializes the instrumentation by defining the React Router server modules to be patched.
22
+ */
23
+ // eslint-disable-next-line @typescript-eslint/naming-convention
24
+ init() {
25
+ const reactRouterServerModule = new instrumentation.InstrumentationNodeModuleDefinition(
26
+ COMPONENT,
27
+ supportedVersions,
28
+ (moduleExports) => {
29
+ return this._createPatchedModuleProxy(moduleExports);
30
+ },
31
+ (_moduleExports) => {
32
+ // nothing to unwrap here
33
+ return _moduleExports;
34
+ },
35
+ );
36
+
37
+ return reactRouterServerModule;
38
+ }
39
+
40
+ /**
41
+ * Creates a proxy around the React Router module exports that patches the createRequestHandler function.
42
+ * This allows us to wrap the request handler to add performance monitoring for data loaders and actions.
43
+ */
44
+ _createPatchedModuleProxy(moduleExports) {
45
+ return new Proxy(moduleExports, {
46
+ get(target, prop, receiver) {
47
+ if (prop === 'createRequestHandler') {
48
+ const original = target[prop];
49
+ return function sentryWrappedCreateRequestHandler( ...args) {
50
+ const originalRequestHandler = original.apply(this, args);
51
+
52
+ return async function sentryWrappedRequestHandler(request, initialContext) {
53
+ let url;
54
+ try {
55
+ url = new URL(request.url);
56
+ } catch (error) {
57
+ return originalRequestHandler(request, initialContext);
58
+ }
59
+
60
+ // We currently just want to trace loaders and actions
61
+ if (!util.isDataRequest(url.pathname)) {
62
+ return originalRequestHandler(request, initialContext);
63
+ }
64
+
65
+ const activeSpan = core.getActiveSpan();
66
+ const rootSpan = activeSpan && core.getRootSpan(activeSpan);
67
+
68
+ if (!rootSpan) {
69
+ debugBuild.DEBUG_BUILD && core.logger.debug('No active root span found, skipping tracing for data request');
70
+ return originalRequestHandler(request, initialContext);
71
+ }
72
+
73
+ // Set the source and overwrite attributes on the root span to ensure the transaction name
74
+ // is derived from the raw URL pathname rather than any parameterized route that may be set later
75
+ // TODO: try to set derived parameterized route from build here (args[0])
76
+ rootSpan.setAttributes({
77
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
78
+ [util.SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]: `${request.method} ${url.pathname}`,
79
+ });
80
+
81
+ return core.startSpan(
82
+ {
83
+ name: util.getSpanName(url.pathname, request.method),
84
+ attributes: {
85
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router',
86
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: util.getOpName(url.pathname, request.method),
87
+ },
88
+ },
89
+ () => {
90
+ return originalRequestHandler(request, initialContext);
91
+ },
92
+ );
93
+ };
94
+ };
95
+ }
96
+ return Reflect.get(target, prop, receiver);
97
+ },
98
+ });
99
+ }
100
+ }
101
+
102
+ exports.ReactRouterInstrumentation = ReactRouterInstrumentation;
103
+ //# sourceMappingURL=reactRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactRouter.js","sources":["../../../../src/server/instrumentation/reactRouter.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport {\n getActiveSpan,\n getRootSpan,\n logger,\n SDK_VERSION,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n} from '@sentry/core';\nimport type * as reactRouter from 'react-router';\nimport { DEBUG_BUILD } from '../../common/debug-build';\nimport { getOpName, getSpanName, isDataRequest, SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE } from './util';\n\ntype ReactRouterModuleExports = typeof reactRouter;\n\nconst supportedVersions = ['>=7.0.0'];\nconst COMPONENT = 'react-router';\n\n/**\n * Instrumentation for React Router's server request handler.\n * This patches the requestHandler function to add Sentry performance monitoring for data loaders.\n */\nexport class ReactRouterInstrumentation extends InstrumentationBase<InstrumentationConfig> {\n public constructor(config: InstrumentationConfig = {}) {\n super('ReactRouterInstrumentation', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the React Router server modules to be patched.\n */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n protected init(): InstrumentationNodeModuleDefinition {\n const reactRouterServerModule = new InstrumentationNodeModuleDefinition(\n COMPONENT,\n supportedVersions,\n (moduleExports: ReactRouterModuleExports) => {\n return this._createPatchedModuleProxy(moduleExports);\n },\n (_moduleExports: unknown) => {\n // nothing to unwrap here\n return _moduleExports;\n },\n );\n\n return reactRouterServerModule;\n }\n\n /**\n * Creates a proxy around the React Router module exports that patches the createRequestHandler function.\n * This allows us to wrap the request handler to add performance monitoring for data loaders and actions.\n */\n private _createPatchedModuleProxy(moduleExports: ReactRouterModuleExports): ReactRouterModuleExports {\n return new Proxy(moduleExports, {\n get(target, prop, receiver) {\n if (prop === 'createRequestHandler') {\n const original = target[prop];\n return function sentryWrappedCreateRequestHandler(this: unknown, ...args: unknown[]) {\n const originalRequestHandler = original.apply(this, args);\n\n return async function sentryWrappedRequestHandler(request: Request, initialContext?: unknown) {\n let url: URL;\n try {\n url = new URL(request.url);\n } catch (error) {\n return originalRequestHandler(request, initialContext);\n }\n\n // We currently just want to trace loaders and actions\n if (!isDataRequest(url.pathname)) {\n return originalRequestHandler(request, initialContext);\n }\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan && getRootSpan(activeSpan);\n\n if (!rootSpan) {\n DEBUG_BUILD && logger.debug('No active root span found, skipping tracing for data request');\n return originalRequestHandler(request, initialContext);\n }\n\n // Set the source and overwrite attributes on the root span to ensure the transaction name\n // is derived from the raw URL pathname rather than any parameterized route that may be set later\n // TODO: try to set derived parameterized route from build here (args[0])\n rootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]: `${request.method} ${url.pathname}`,\n });\n\n return startSpan(\n {\n name: getSpanName(url.pathname, request.method),\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: getOpName(url.pathname, request.method),\n },\n },\n () => {\n return originalRequestHandler(request, initialContext);\n },\n );\n };\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n }\n}\n"],"names":["InstrumentationBase","SDK_VERSION","InstrumentationNodeModuleDefinition","isDataRequest","getActiveSpan","getRootSpan","DEBUG_BUILD","logger","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE","startSpan","getSpanName","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","getOpName"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ /**
4
+ * Gets the op name for a request based on whether it's a loader or action request.
5
+ * @param pathName The URL pathname to check
6
+ * @param requestMethod The HTTP request method
7
+ */
8
+ function getOpName(pathName, requestMethod) {
9
+ return isLoaderRequest(pathName, requestMethod)
10
+ ? 'function.react-router.loader'
11
+ : isActionRequest(pathName, requestMethod)
12
+ ? 'function.react-router.action'
13
+ : 'function.react-router';
14
+ }
15
+
16
+ /**
17
+ * Gets the span name for a request based on whether it's a loader or action request.
18
+ * @param pathName The URL pathname to check
19
+ * @param requestMethod The HTTP request method
20
+ */
21
+ function getSpanName(pathName, requestMethod) {
22
+ return isLoaderRequest(pathName, requestMethod)
23
+ ? 'Executing Server Loader'
24
+ : isActionRequest(pathName, requestMethod)
25
+ ? 'Executing Server Action'
26
+ : 'Unknown Data Request';
27
+ }
28
+
29
+ /**
30
+ * Checks if the request is a server loader request
31
+ * @param pathname The URL pathname to check
32
+ * @param requestMethod The HTTP request method
33
+ */
34
+ function isLoaderRequest(pathname, requestMethod) {
35
+ return isDataRequest(pathname) && requestMethod === 'GET';
36
+ }
37
+
38
+ /**
39
+ * Checks if the request is a server action request
40
+ * @param pathname The URL pathname to check
41
+ * @param requestMethod The HTTP request method
42
+ */
43
+ function isActionRequest(pathname, requestMethod) {
44
+ return isDataRequest(pathname) && requestMethod === 'POST';
45
+ }
46
+
47
+ /**
48
+ * Checks if the request is a react-router data request
49
+ * @param pathname The URL pathname to check
50
+ */
51
+ function isDataRequest(pathname) {
52
+ return pathname.endsWith('.data');
53
+ }
54
+
55
+ const SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE = 'sentry.overwrite-route';
56
+
57
+ exports.SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE = SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE;
58
+ exports.getOpName = getOpName;
59
+ exports.getSpanName = getSpanName;
60
+ exports.isActionRequest = isActionRequest;
61
+ exports.isDataRequest = isDataRequest;
62
+ exports.isLoaderRequest = isLoaderRequest;
63
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sources":["../../../../src/server/instrumentation/util.ts"],"sourcesContent":["/**\n * Gets the op name for a request based on whether it's a loader or action request.\n * @param pathName The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function getOpName(pathName: string, requestMethod: string): string {\n return isLoaderRequest(pathName, requestMethod)\n ? 'function.react-router.loader'\n : isActionRequest(pathName, requestMethod)\n ? 'function.react-router.action'\n : 'function.react-router';\n}\n\n/**\n * Gets the span name for a request based on whether it's a loader or action request.\n * @param pathName The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function getSpanName(pathName: string, requestMethod: string): string {\n return isLoaderRequest(pathName, requestMethod)\n ? 'Executing Server Loader'\n : isActionRequest(pathName, requestMethod)\n ? 'Executing Server Action'\n : 'Unknown Data Request';\n}\n\n/**\n * Checks if the request is a server loader request\n * @param pathname The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function isLoaderRequest(pathname: string, requestMethod: string): boolean {\n return isDataRequest(pathname) && requestMethod === 'GET';\n}\n\n/**\n * Checks if the request is a server action request\n * @param pathname The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function isActionRequest(pathname: string, requestMethod: string): boolean {\n return isDataRequest(pathname) && requestMethod === 'POST';\n}\n\n/**\n * Checks if the request is a react-router data request\n * @param pathname The URL pathname to check\n */\nexport function isDataRequest(pathname: string): boolean {\n return pathname.endsWith('.data');\n}\n\nexport const SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE = 'sentry.overwrite-route';\n"],"names":[],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACO,SAAS,SAAS,CAAC,QAAQ,EAAU,aAAa,EAAkB;AAC3E,EAAE,OAAO,eAAe,CAAC,QAAQ,EAAE,aAAa;AAChD,MAAM;AACN,MAAM,eAAe,CAAC,QAAQ,EAAE,aAAa;AAC7C,QAAQ;AACR,QAAQ,uBAAuB;AAC/B;;AAEA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW,CAAC,QAAQ,EAAU,aAAa,EAAkB;AAC7E,EAAE,OAAO,eAAe,CAAC,QAAQ,EAAE,aAAa;AAChD,MAAM;AACN,MAAM,eAAe,CAAC,QAAQ,EAAE,aAAa;AAC7C,QAAQ;AACR,QAAQ,sBAAsB;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACO,SAAS,eAAe,CAAC,QAAQ,EAAU,aAAa,EAAmB;AAClF,EAAE,OAAO,aAAa,CAAC,QAAQ,KAAK,aAAA,KAAkB,KAAK;AAC3D;;AAEA;AACA;AACA;AACA;AACA;AACO,SAAS,eAAe,CAAC,QAAQ,EAAU,aAAa,EAAmB;AAClF,EAAE,OAAO,aAAa,CAAC,QAAQ,KAAK,aAAA,KAAkB,MAAM;AAC5D;;AAEA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,QAAQ,EAAmB;AACzD,EAAE,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;AACnC;;AAEO,MAAM,mCAAoC,GAAE;;;;;;;;;"}
@@ -0,0 +1,34 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const node = require('@sentry/node');
5
+ const reactRouter = require('../instrumentation/reactRouter.js');
6
+
7
+ const INTEGRATION_NAME = 'ReactRouterServer';
8
+
9
+ const instrumentReactRouter = node.generateInstrumentOnce('React-Router-Server', () => {
10
+ return new reactRouter.ReactRouterInstrumentation();
11
+ });
12
+
13
+ const instrumentReactRouterServer = Object.assign(
14
+ () => {
15
+ instrumentReactRouter();
16
+ },
17
+ { id: INTEGRATION_NAME },
18
+ );
19
+
20
+ /**
21
+ * Integration capturing tracing data for React Router server functions.
22
+ */
23
+ const reactRouterServerIntegration = core.defineIntegration(() => {
24
+ return {
25
+ name: INTEGRATION_NAME,
26
+ setupOnce() {
27
+ instrumentReactRouterServer();
28
+ },
29
+ };
30
+ });
31
+
32
+ exports.instrumentReactRouterServer = instrumentReactRouterServer;
33
+ exports.reactRouterServerIntegration = reactRouterServerIntegration;
34
+ //# sourceMappingURL=reactRouterServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactRouterServer.js","sources":["../../../../src/server/integration/reactRouterServer.ts"],"sourcesContent":["import { defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node';\nimport { ReactRouterInstrumentation } from '../instrumentation/reactRouter';\n\nconst INTEGRATION_NAME = 'ReactRouterServer';\n\nconst instrumentReactRouter = generateInstrumentOnce('React-Router-Server', () => {\n return new ReactRouterInstrumentation();\n});\n\nexport const instrumentReactRouterServer = Object.assign(\n (): void => {\n instrumentReactRouter();\n },\n { id: INTEGRATION_NAME },\n);\n\n/**\n * Integration capturing tracing data for React Router server functions.\n */\nexport const reactRouterServerIntegration = defineIntegration(() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentReactRouterServer();\n },\n };\n});\n"],"names":["generateInstrumentOnce","ReactRouterInstrumentation","defineIntegration"],"mappings":";;;;;;AAIA,MAAM,gBAAA,GAAmB,mBAAmB;;AAE5C,MAAM,qBAAA,GAAwBA,2BAAsB,CAAC,qBAAqB,EAAE,MAAM;AAClF,EAAE,OAAO,IAAIC,sCAA0B,EAAE;AACzC,CAAC,CAAC;;AAEW,MAAA,2BAAA,GAA8B,MAAM,CAAC,MAAM;AACxD,EAAE,MAAY;AACd,IAAI,qBAAqB,EAAE;AAC3B,GAAG;AACH,EAAE,EAAE,EAAE,EAAE,gBAAA,EAAkB;AAC1B;;AAEA;AACA;AACA;MACa,4BAA6B,GAAEC,sBAAiB,CAAC,MAAM;AACpE,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB,MAAM,2BAA2B,EAAE;AACnC,KAAK;AACL,GAAG;AACH,CAAC;;;;;"}
@@ -0,0 +1,40 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+
5
+ /**
6
+ * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/
7
+ *
8
+ */
9
+
10
+ function _lowQualityTransactionsFilterIntegration(options)
11
+
12
+ {
13
+ const matchedRegexes = [/GET \/node_modules\//, /GET \/favicon\.ico/, /GET \/@id\//];
14
+
15
+ return {
16
+ name: 'LowQualityTransactionsFilter',
17
+
18
+ processEvent(event, _hint, _client) {
19
+ if (event.type !== 'transaction' || !event.transaction) {
20
+ return event;
21
+ }
22
+
23
+ const transaction = event.transaction;
24
+
25
+ if (matchedRegexes.some(regex => transaction.match(regex))) {
26
+ options.debug && core.logger.log('[ReactRouter] Filtered node_modules transaction:', event.transaction);
27
+ return null;
28
+ }
29
+
30
+ return event;
31
+ },
32
+ };
33
+ }
34
+
35
+ const lowQualityTransactionsFilterIntegration = core.defineIntegration((options) =>
36
+ _lowQualityTransactionsFilterIntegration(options),
37
+ );
38
+
39
+ exports.lowQualityTransactionsFilterIntegration = lowQualityTransactionsFilterIntegration;
40
+ //# sourceMappingURL=lowQualityTransactionsFilterIntegration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../src/server/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import { type Client, type Event, type EventHint, defineIntegration, logger } from '@sentry/core';\nimport type { NodeOptions } from '@sentry/node';\n\n/**\n * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/\n *\n */\n\nfunction _lowQualityTransactionsFilterIntegration(options: NodeOptions): {\n name: string;\n processEvent: (event: Event, hint: EventHint, client: Client) => Event | null;\n} {\n const matchedRegexes = [/GET \\/node_modules\\//, /GET \\/favicon\\.ico/, /GET \\/@id\\//];\n\n return {\n name: 'LowQualityTransactionsFilter',\n\n processEvent(event: Event, _hint: EventHint, _client: Client): Event | null {\n if (event.type !== 'transaction' || !event.transaction) {\n return event;\n }\n\n const transaction = event.transaction;\n\n if (matchedRegexes.some(regex => transaction.match(regex))) {\n options.debug && logger.log('[ReactRouter] Filtered node_modules transaction:', event.transaction);\n return null;\n }\n\n return event;\n },\n };\n}\n\nexport const lowQualityTransactionsFilterIntegration = defineIntegration((options: NodeOptions) =>\n _lowQualityTransactionsFilterIntegration(options),\n);\n"],"names":["logger","defineIntegration"],"mappings":";;;;AAGA;AACA;AACA;AACA;;AAEA,SAAS,wCAAwC,CAAC,OAAO;;AAGzD,CAAE;AACF,EAAE,MAAM,iBAAiB,CAAC,sBAAsB,EAAE,oBAAoB,EAAE,aAAa,CAAC;;AAEtF,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,8BAA8B;;AAExC,IAAI,YAAY,CAAC,KAAK,EAAS,KAAK,EAAa,OAAO,EAAwB;AAChF,MAAM,IAAI,KAAK,CAAC,IAAK,KAAI,aAAc,IAAG,CAAC,KAAK,CAAC,WAAW,EAAE;AAC9D,QAAQ,OAAO,KAAK;AACpB;;AAEA,MAAM,MAAM,WAAA,GAAc,KAAK,CAAC,WAAW;;AAE3C,MAAM,IAAI,cAAc,CAAC,IAAI,CAAC,KAAA,IAAS,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE;AAClE,QAAQ,OAAO,CAAC,KAAM,IAAGA,WAAM,CAAC,GAAG,CAAC,kDAAkD,EAAE,KAAK,CAAC,WAAW,CAAC;AAC1G,QAAQ,OAAO,IAAI;AACnB;;AAEA,MAAM,OAAO,KAAK;AAClB,KAAK;AACL,GAAG;AACH;;MAEa,uCAAwC,GAAEC,sBAAiB,CAAC,CAAC,OAAO;AACjF,EAAE,wCAAwC,CAAC,OAAO,CAAC;AACnD;;;;"}
@@ -1,8 +1,24 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const semanticConventions = require('@opentelemetry/semantic-conventions');
3
4
  const core = require('@sentry/core');
4
5
  const node = require('@sentry/node');
5
6
  const debugBuild = require('../common/debug-build.js');
7
+ const util = require('./instrumentation/util.js');
8
+ const reactRouterServer = require('./integration/reactRouterServer.js');
9
+ const lowQualityTransactionsFilterIntegration = require('./lowQualityTransactionsFilterIntegration.js');
10
+
11
+ /**
12
+ * Returns the default integrations for the React Router SDK.
13
+ * @param options The options for the SDK.
14
+ */
15
+ function getDefaultReactRouterServerIntegrations(options) {
16
+ return [
17
+ ...node.getDefaultIntegrations(options),
18
+ lowQualityTransactionsFilterIntegration.lowQualityTransactionsFilterIntegration(options),
19
+ reactRouterServer.reactRouterServerIntegration(),
20
+ ];
21
+ }
6
22
 
7
23
  /**
8
24
  * Initializes the server side of the React Router SDK
@@ -10,6 +26,7 @@ const debugBuild = require('../common/debug-build.js');
10
26
  function init(options) {
11
27
  const opts = {
12
28
  ...options,
29
+ defaultIntegrations: getDefaultReactRouterServerIntegrations(options),
13
30
  };
14
31
 
15
32
  debugBuild.DEBUG_BUILD && core.logger.log('Initializing SDK...');
@@ -20,9 +37,36 @@ function init(options) {
20
37
 
21
38
  core.setTag('runtime', 'node');
22
39
 
40
+ // Overwrite the transaction name for instrumented data loaders because the trace data gets overwritten at a later point.
41
+ // We only update the tx in case SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE got set in our instrumentation before.
42
+ core.getGlobalScope().addEventProcessor(
43
+ Object.assign(
44
+ (event => {
45
+ const overwrite = event.contexts?.trace?.data?.[util.SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];
46
+ if (
47
+ event.type === 'transaction' &&
48
+ event.transaction === 'GET *' &&
49
+ event.contexts?.trace?.data?.[semanticConventions.ATTR_HTTP_ROUTE] === '*' &&
50
+ overwrite
51
+ ) {
52
+ event.transaction = overwrite;
53
+ event.contexts.trace.data[semanticConventions.ATTR_HTTP_ROUTE] = 'url';
54
+ }
55
+
56
+ // always yeet this attribute into the void, as this should not reach the server
57
+ delete event.contexts?.trace?.data?.[util.SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];
58
+
59
+ return event;
60
+ }) ,
61
+ { id: 'ReactRouterTransactionEnhancer' },
62
+ ),
63
+ );
64
+
23
65
  debugBuild.DEBUG_BUILD && core.logger.log('SDK successfully initialized');
66
+
24
67
  return client;
25
68
  }
26
69
 
70
+ exports.getDefaultReactRouterServerIntegrations = getDefaultReactRouterServerIntegrations;
27
71
  exports.init = init;
28
72
  //# sourceMappingURL=sdk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import { applySdkMetadata, logger, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts = {\n ...options,\n };\n\n DEBUG_BUILD && logger.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n DEBUG_BUILD && logger.log('SDK successfully initialized');\n return client;\n}\n"],"names":["DEBUG_BUILD","logger","applySdkMetadata","initNodeSdk","setTag"],"mappings":";;;;;;AAKA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuC;AACnE,EAAE,MAAM,OAAO;AACf,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAEA,0BAAeC,WAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC;;AAElD,EAAEC,qBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;;AAElE,EAAE,MAAM,MAAO,GAAEC,SAAW,CAAC,IAAI,CAAC;;AAElC,EAAEC,WAAM,CAAC,SAAS,EAAE,MAAM,CAAC;;AAE3B,EAAEJ,0BAAeC,WAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC;AAC3D,EAAE,OAAO,MAAM;AACf;;;;"}
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport type { EventProcessor, Integration } from '@sentry/core';\nimport { applySdkMetadata, getGlobalScope, logger, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getNodeDefaultIntegrations, init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE } from './instrumentation/util';\nimport { reactRouterServerIntegration } from './integration/reactRouterServer';\nimport { lowQualityTransactionsFilterIntegration } from './lowQualityTransactionsFilterIntegration';\n\n/**\n * Returns the default integrations for the React Router SDK.\n * @param options The options for the SDK.\n */\nexport function getDefaultReactRouterServerIntegrations(options: NodeOptions): Integration[] {\n return [\n ...getNodeDefaultIntegrations(options),\n lowQualityTransactionsFilterIntegration(options),\n reactRouterServerIntegration(),\n ];\n}\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts: NodeOptions = {\n ...options,\n defaultIntegrations: getDefaultReactRouterServerIntegrations(options),\n };\n\n DEBUG_BUILD && logger.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n // Overwrite the transaction name for instrumented data loaders because the trace data gets overwritten at a later point.\n // We only update the tx in case SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE got set in our instrumentation before.\n getGlobalScope().addEventProcessor(\n Object.assign(\n (event => {\n const overwrite = event.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];\n if (\n event.type === 'transaction' &&\n event.transaction === 'GET *' &&\n event.contexts?.trace?.data?.[ATTR_HTTP_ROUTE] === '*' &&\n overwrite\n ) {\n event.transaction = overwrite;\n event.contexts.trace.data[ATTR_HTTP_ROUTE] = 'url';\n }\n\n // always yeet this attribute into the void, as this should not reach the server\n delete event.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];\n\n return event;\n }) satisfies EventProcessor,\n { id: 'ReactRouterTransactionEnhancer' },\n ),\n );\n\n DEBUG_BUILD && logger.log('SDK successfully initialized');\n\n return client;\n}\n"],"names":["getNodeDefaultIntegrations","lowQualityTransactionsFilterIntegration","reactRouterServerIntegration","DEBUG_BUILD","logger","applySdkMetadata","initNodeSdk","setTag","getGlobalScope","SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE","ATTR_HTTP_ROUTE"],"mappings":";;;;;;;;;;AAUA;AACA;AACA;AACA;AACO,SAAS,uCAAuC,CAAC,OAAO,EAA8B;AAC7F,EAAE,OAAO;AACT,IAAI,GAAGA,2BAA0B,CAAC,OAAO,CAAC;AAC1C,IAAIC,+EAAuC,CAAC,OAAO,CAAC;AACpD,IAAIC,8CAA4B,EAAE;AAClC,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuC;AACnE,EAAE,MAAM,IAAI,GAAgB;AAC5B,IAAI,GAAG,OAAO;AACd,IAAI,mBAAmB,EAAE,uCAAuC,CAAC,OAAO,CAAC;AACzE,GAAG;;AAEH,EAAEC,0BAAeC,WAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC;;AAElD,EAAEC,qBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;;AAElE,EAAE,MAAM,MAAO,GAAEC,SAAW,CAAC,IAAI,CAAC;;AAElC,EAAEC,WAAM,CAAC,SAAS,EAAE,MAAM,CAAC;;AAE3B;AACA;AACA,EAAEC,mBAAc,EAAE,CAAC,iBAAiB;AACpC,IAAI,MAAM,CAAC,MAAM;AACjB,OAAO,SAAS;AAChB,QAAQ,MAAM,SAAA,GAAY,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAGC,wCAAmC,CAAC;AAC5F,QAAQ;AACR,UAAU,KAAK,CAAC,IAAK,KAAI,aAAc;AACvC,UAAU,KAAK,CAAC,WAAY,KAAI,OAAQ;AACxC,UAAU,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAGC,mCAAe,CAAE,KAAI,GAAI;AACjE,UAAU;AACV,UAAU;AACV,UAAU,KAAK,CAAC,WAAY,GAAE,SAAS;AACvC,UAAU,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAACA,mCAAe,CAAE,GAAE,KAAK;AAC5D;;AAEA;AACA,QAAQ,OAAO,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAGD,wCAAmC,CAAC;;AAEjF,QAAQ,OAAO,KAAK;AACpB,OAAO;AACP,MAAM,EAAE,EAAE,EAAE,gCAAA,EAAkC;AAC9C,KAAK;AACL,GAAG;;AAEH,EAAEN,0BAAeC,WAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC;;AAE3D,EAAE,OAAO,MAAM;AACf;;;;;"}
@@ -22,6 +22,7 @@ function wrapSentryHandleRequest(originalHandle) {
22
22
  ) {
23
23
  const parameterizedPath =
24
24
  routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;
25
+
25
26
  if (parameterizedPath) {
26
27
  const activeSpan = core.getActiveSpan();
27
28
  if (activeSpan) {
@@ -30,6 +31,7 @@ function wrapSentryHandleRequest(originalHandle) {
30
31
 
31
32
  // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.
32
33
  const rpcMetadata = core$1.getRPCMetadata(api.context.active());
34
+
33
35
  if (rpcMetadata?.type === core$1.RPCType.HTTP) {
34
36
  rpcMetadata.route = routeName;
35
37
  }
@@ -38,6 +40,7 @@ function wrapSentryHandleRequest(originalHandle) {
38
40
  rootSpan.setAttributes({
39
41
  [semanticConventions.ATTR_HTTP_ROUTE]: routeName,
40
42
  [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
43
+ [core.SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: `${request.method} ${routeName}`,
41
44
  });
42
45
  }
43
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport { getActiveSpan, getRootSpan, getTraceMetaTags, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\nimport type { PassThrough } from 'stream';\nimport { Transform } from 'stream';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n ) {\n const parameterizedPath =\n routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;\n if (parameterizedPath) {\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n const rootSpan = getRootSpan(activeSpan);\n const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n });\n }\n }\n\n return originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n };\n}\n\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\n\n/**\n * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n *\n * @param body - PassThrough stream containing the HTML response body to modify\n */\nexport function getMetaTagTransformer(body: PassThrough): Transform {\n const headClosingTag = '</head>';\n const htmlMetaTagTransformer = new Transform({\n transform(chunk, _encoding, callback) {\n const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n callback(null, modifiedHtml);\n return;\n }\n callback(null, chunk);\n },\n });\n htmlMetaTagTransformer.pipe(body);\n return htmlMetaTagTransformer;\n}\n"],"names":["getActiveSpan","getRootSpan","getRPCMetadata","context","RPCType","ATTR_HTTP_ROUTE","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","Transform","getTraceMetaTags"],"mappings":";;;;;;;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAkB;AAC5B,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;AACvH,IAAI,IAAI,iBAAiB,EAAE;AAC3B,MAAM,MAAM,UAAA,GAAaA,kBAAa,EAAE;AACxC,MAAM,IAAI,UAAU,EAAE;AACtB,QAAQ,MAAM,QAAS,GAAEC,gBAAW,CAAC,UAAU,CAAC;AAChD,QAAQ,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,QAAA,MAAA,WAAA,GAAAC,qBAAA,CAAAC,WAAA,CAAA,MAAA,EAAA,CAAA;AACA,QAAA,IAAA,WAAA,EAAA,IAAA,KAAAC,cAAA,CAAA,IAAA,EAAA;AACA,UAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,QAAA,QAAA,CAAA,aAAA,CAAA;AACA,UAAA,CAAAC,mCAAA,GAAA,SAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,OAAA;AACA,SAAA,CAAA;AACA;AACA;;AAEA,IAAA,OAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,GAAA;AACA;;AAEA;AACA,MAAA,mBAAA,GAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,IAAA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,SAAA;AACA,EAAA,MAAA,sBAAA,GAAA,IAAAC,gBAAA,CAAA;AACA,IAAA,SAAA,CAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA;AACA,MAAA,MAAA,IAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,GAAA,KAAA,CAAA,QAAA,EAAA,GAAA,MAAA,CAAA,KAAA,CAAA;AACA,MAAA,IAAA,IAAA,CAAA,QAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,YAAA,GAAA,IAAA,CAAA,OAAA,CAAA,cAAA,EAAA,CAAA,EAAAC,qBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;;;"}
1
+ {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport {\n getActiveSpan,\n getRootSpan,\n getTraceMetaTags,\n SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\nimport type { PassThrough } from 'stream';\nimport { Transform } from 'stream';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n ) {\n const parameterizedPath =\n routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;\n\n if (parameterizedPath) {\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n const rootSpan = getRootSpan(activeSpan);\n const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: `${request.method} ${routeName}`,\n });\n }\n }\n\n return originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n };\n}\n\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\n\n/**\n * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n *\n * @param body - PassThrough stream containing the HTML response body to modify\n */\nexport function getMetaTagTransformer(body: PassThrough): Transform {\n const headClosingTag = '</head>';\n const htmlMetaTagTransformer = new Transform({\n transform(chunk, _encoding, callback) {\n const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n callback(null, modifiedHtml);\n return;\n }\n callback(null, chunk);\n },\n });\n htmlMetaTagTransformer.pipe(body);\n return htmlMetaTagTransformer;\n}\n"],"names":["getActiveSpan","getRootSpan","getRPCMetadata","context","RPCType","ATTR_HTTP_ROUTE","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME","Transform","getTraceMetaTags"],"mappings":";;;;;;;;AAsBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAkB;AAC5B,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;;AAEvH,IAAI,IAAI,iBAAiB,EAAE;AAC3B,MAAM,MAAM,UAAA,GAAaA,kBAAa,EAAE;AACxC,MAAM,IAAI,UAAU,EAAE;AACtB,QAAQ,MAAM,QAAS,GAAEC,gBAAW,CAAC,UAAU,CAAC;AAChD,QAAQ,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,QAAA,MAAA,WAAA,GAAAC,qBAAA,CAAAC,WAAA,CAAA,MAAA,EAAA,CAAA;;AAEA,QAAA,IAAA,WAAA,EAAA,IAAA,KAAAC,cAAA,CAAA,IAAA,EAAA;AACA,UAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,QAAA,QAAA,CAAA,aAAA,CAAA;AACA,UAAA,CAAAC,mCAAA,GAAA,SAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,OAAA;AACA,UAAA,CAAAC,+CAAA,GAAA,CAAA,EAAA,OAAA,CAAA,MAAA,CAAA,CAAA,EAAA,SAAA,CAAA,CAAA;AACA,SAAA,CAAA;AACA;AACA;;AAEA,IAAA,OAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,GAAA;AACA;;AAEA;AACA,MAAA,mBAAA,GAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,IAAA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,SAAA;AACA,EAAA,MAAA,sBAAA,GAAA,IAAAC,gBAAA,CAAA;AACA,IAAA,SAAA,CAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA;AACA,MAAA,MAAA,IAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,GAAA,KAAA,CAAA,QAAA,EAAA,GAAA,MAAA,CAAA,KAAA,CAAA;AACA,MAAA,IAAA,IAAA,CAAA,QAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,YAAA,GAAA,IAAA,CAAA,OAAA,CAAA,cAAA,EAAA,CAAA,EAAAC,qBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"9.17.0"}
1
+ {"type":"module","version":"9.19.0"}
@@ -0,0 +1,101 @@
1
+ import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
2
+ import { SDK_VERSION, getActiveSpan, getRootSpan, logger, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
3
+ import { DEBUG_BUILD } from '../../common/debug-build.js';
4
+ import { isDataRequest, SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE, getOpName, getSpanName } from './util.js';
5
+
6
+ const supportedVersions = ['>=7.0.0'];
7
+ const COMPONENT = 'react-router';
8
+
9
+ /**
10
+ * Instrumentation for React Router's server request handler.
11
+ * This patches the requestHandler function to add Sentry performance monitoring for data loaders.
12
+ */
13
+ class ReactRouterInstrumentation extends InstrumentationBase {
14
+ constructor(config = {}) {
15
+ super('ReactRouterInstrumentation', SDK_VERSION, config);
16
+ }
17
+
18
+ /**
19
+ * Initializes the instrumentation by defining the React Router server modules to be patched.
20
+ */
21
+ // eslint-disable-next-line @typescript-eslint/naming-convention
22
+ init() {
23
+ const reactRouterServerModule = new InstrumentationNodeModuleDefinition(
24
+ COMPONENT,
25
+ supportedVersions,
26
+ (moduleExports) => {
27
+ return this._createPatchedModuleProxy(moduleExports);
28
+ },
29
+ (_moduleExports) => {
30
+ // nothing to unwrap here
31
+ return _moduleExports;
32
+ },
33
+ );
34
+
35
+ return reactRouterServerModule;
36
+ }
37
+
38
+ /**
39
+ * Creates a proxy around the React Router module exports that patches the createRequestHandler function.
40
+ * This allows us to wrap the request handler to add performance monitoring for data loaders and actions.
41
+ */
42
+ _createPatchedModuleProxy(moduleExports) {
43
+ return new Proxy(moduleExports, {
44
+ get(target, prop, receiver) {
45
+ if (prop === 'createRequestHandler') {
46
+ const original = target[prop];
47
+ return function sentryWrappedCreateRequestHandler( ...args) {
48
+ const originalRequestHandler = original.apply(this, args);
49
+
50
+ return async function sentryWrappedRequestHandler(request, initialContext) {
51
+ let url;
52
+ try {
53
+ url = new URL(request.url);
54
+ } catch (error) {
55
+ return originalRequestHandler(request, initialContext);
56
+ }
57
+
58
+ // We currently just want to trace loaders and actions
59
+ if (!isDataRequest(url.pathname)) {
60
+ return originalRequestHandler(request, initialContext);
61
+ }
62
+
63
+ const activeSpan = getActiveSpan();
64
+ const rootSpan = activeSpan && getRootSpan(activeSpan);
65
+
66
+ if (!rootSpan) {
67
+ DEBUG_BUILD && logger.debug('No active root span found, skipping tracing for data request');
68
+ return originalRequestHandler(request, initialContext);
69
+ }
70
+
71
+ // Set the source and overwrite attributes on the root span to ensure the transaction name
72
+ // is derived from the raw URL pathname rather than any parameterized route that may be set later
73
+ // TODO: try to set derived parameterized route from build here (args[0])
74
+ rootSpan.setAttributes({
75
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
76
+ [SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]: `${request.method} ${url.pathname}`,
77
+ });
78
+
79
+ return startSpan(
80
+ {
81
+ name: getSpanName(url.pathname, request.method),
82
+ attributes: {
83
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router',
84
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: getOpName(url.pathname, request.method),
85
+ },
86
+ },
87
+ () => {
88
+ return originalRequestHandler(request, initialContext);
89
+ },
90
+ );
91
+ };
92
+ };
93
+ }
94
+ return Reflect.get(target, prop, receiver);
95
+ },
96
+ });
97
+ }
98
+ }
99
+
100
+ export { ReactRouterInstrumentation };
101
+ //# sourceMappingURL=reactRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactRouter.js","sources":["../../../../src/server/instrumentation/reactRouter.ts"],"sourcesContent":["import type { InstrumentationConfig } from '@opentelemetry/instrumentation';\nimport { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';\nimport {\n getActiveSpan,\n getRootSpan,\n logger,\n SDK_VERSION,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n} from '@sentry/core';\nimport type * as reactRouter from 'react-router';\nimport { DEBUG_BUILD } from '../../common/debug-build';\nimport { getOpName, getSpanName, isDataRequest, SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE } from './util';\n\ntype ReactRouterModuleExports = typeof reactRouter;\n\nconst supportedVersions = ['>=7.0.0'];\nconst COMPONENT = 'react-router';\n\n/**\n * Instrumentation for React Router's server request handler.\n * This patches the requestHandler function to add Sentry performance monitoring for data loaders.\n */\nexport class ReactRouterInstrumentation extends InstrumentationBase<InstrumentationConfig> {\n public constructor(config: InstrumentationConfig = {}) {\n super('ReactRouterInstrumentation', SDK_VERSION, config);\n }\n\n /**\n * Initializes the instrumentation by defining the React Router server modules to be patched.\n */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n protected init(): InstrumentationNodeModuleDefinition {\n const reactRouterServerModule = new InstrumentationNodeModuleDefinition(\n COMPONENT,\n supportedVersions,\n (moduleExports: ReactRouterModuleExports) => {\n return this._createPatchedModuleProxy(moduleExports);\n },\n (_moduleExports: unknown) => {\n // nothing to unwrap here\n return _moduleExports;\n },\n );\n\n return reactRouterServerModule;\n }\n\n /**\n * Creates a proxy around the React Router module exports that patches the createRequestHandler function.\n * This allows us to wrap the request handler to add performance monitoring for data loaders and actions.\n */\n private _createPatchedModuleProxy(moduleExports: ReactRouterModuleExports): ReactRouterModuleExports {\n return new Proxy(moduleExports, {\n get(target, prop, receiver) {\n if (prop === 'createRequestHandler') {\n const original = target[prop];\n return function sentryWrappedCreateRequestHandler(this: unknown, ...args: unknown[]) {\n const originalRequestHandler = original.apply(this, args);\n\n return async function sentryWrappedRequestHandler(request: Request, initialContext?: unknown) {\n let url: URL;\n try {\n url = new URL(request.url);\n } catch (error) {\n return originalRequestHandler(request, initialContext);\n }\n\n // We currently just want to trace loaders and actions\n if (!isDataRequest(url.pathname)) {\n return originalRequestHandler(request, initialContext);\n }\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan && getRootSpan(activeSpan);\n\n if (!rootSpan) {\n DEBUG_BUILD && logger.debug('No active root span found, skipping tracing for data request');\n return originalRequestHandler(request, initialContext);\n }\n\n // Set the source and overwrite attributes on the root span to ensure the transaction name\n // is derived from the raw URL pathname rather than any parameterized route that may be set later\n // TODO: try to set derived parameterized route from build here (args[0])\n rootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]: `${request.method} ${url.pathname}`,\n });\n\n return startSpan(\n {\n name: getSpanName(url.pathname, request.method),\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: getOpName(url.pathname, request.method),\n },\n },\n () => {\n return originalRequestHandler(request, initialContext);\n },\n );\n };\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Gets the op name for a request based on whether it's a loader or action request.
3
+ * @param pathName The URL pathname to check
4
+ * @param requestMethod The HTTP request method
5
+ */
6
+ function getOpName(pathName, requestMethod) {
7
+ return isLoaderRequest(pathName, requestMethod)
8
+ ? 'function.react-router.loader'
9
+ : isActionRequest(pathName, requestMethod)
10
+ ? 'function.react-router.action'
11
+ : 'function.react-router';
12
+ }
13
+
14
+ /**
15
+ * Gets the span name for a request based on whether it's a loader or action request.
16
+ * @param pathName The URL pathname to check
17
+ * @param requestMethod The HTTP request method
18
+ */
19
+ function getSpanName(pathName, requestMethod) {
20
+ return isLoaderRequest(pathName, requestMethod)
21
+ ? 'Executing Server Loader'
22
+ : isActionRequest(pathName, requestMethod)
23
+ ? 'Executing Server Action'
24
+ : 'Unknown Data Request';
25
+ }
26
+
27
+ /**
28
+ * Checks if the request is a server loader request
29
+ * @param pathname The URL pathname to check
30
+ * @param requestMethod The HTTP request method
31
+ */
32
+ function isLoaderRequest(pathname, requestMethod) {
33
+ return isDataRequest(pathname) && requestMethod === 'GET';
34
+ }
35
+
36
+ /**
37
+ * Checks if the request is a server action request
38
+ * @param pathname The URL pathname to check
39
+ * @param requestMethod The HTTP request method
40
+ */
41
+ function isActionRequest(pathname, requestMethod) {
42
+ return isDataRequest(pathname) && requestMethod === 'POST';
43
+ }
44
+
45
+ /**
46
+ * Checks if the request is a react-router data request
47
+ * @param pathname The URL pathname to check
48
+ */
49
+ function isDataRequest(pathname) {
50
+ return pathname.endsWith('.data');
51
+ }
52
+
53
+ const SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE = 'sentry.overwrite-route';
54
+
55
+ export { SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE, getOpName, getSpanName, isActionRequest, isDataRequest, isLoaderRequest };
56
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sources":["../../../../src/server/instrumentation/util.ts"],"sourcesContent":["/**\n * Gets the op name for a request based on whether it's a loader or action request.\n * @param pathName The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function getOpName(pathName: string, requestMethod: string): string {\n return isLoaderRequest(pathName, requestMethod)\n ? 'function.react-router.loader'\n : isActionRequest(pathName, requestMethod)\n ? 'function.react-router.action'\n : 'function.react-router';\n}\n\n/**\n * Gets the span name for a request based on whether it's a loader or action request.\n * @param pathName The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function getSpanName(pathName: string, requestMethod: string): string {\n return isLoaderRequest(pathName, requestMethod)\n ? 'Executing Server Loader'\n : isActionRequest(pathName, requestMethod)\n ? 'Executing Server Action'\n : 'Unknown Data Request';\n}\n\n/**\n * Checks if the request is a server loader request\n * @param pathname The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function isLoaderRequest(pathname: string, requestMethod: string): boolean {\n return isDataRequest(pathname) && requestMethod === 'GET';\n}\n\n/**\n * Checks if the request is a server action request\n * @param pathname The URL pathname to check\n * @param requestMethod The HTTP request method\n */\nexport function isActionRequest(pathname: string, requestMethod: string): boolean {\n return isDataRequest(pathname) && requestMethod === 'POST';\n}\n\n/**\n * Checks if the request is a react-router data request\n * @param pathname The URL pathname to check\n */\nexport function isDataRequest(pathname: string): boolean {\n return pathname.endsWith('.data');\n}\n\nexport const SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE = 'sentry.overwrite-route';\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACO,SAAS,SAAS,CAAC,QAAQ,EAAU,aAAa,EAAkB;AAC3E,EAAE,OAAO,eAAe,CAAC,QAAQ,EAAE,aAAa;AAChD,MAAM;AACN,MAAM,eAAe,CAAC,QAAQ,EAAE,aAAa;AAC7C,QAAQ;AACR,QAAQ,uBAAuB;AAC/B;;AAEA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW,CAAC,QAAQ,EAAU,aAAa,EAAkB;AAC7E,EAAE,OAAO,eAAe,CAAC,QAAQ,EAAE,aAAa;AAChD,MAAM;AACN,MAAM,eAAe,CAAC,QAAQ,EAAE,aAAa;AAC7C,QAAQ;AACR,QAAQ,sBAAsB;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACO,SAAS,eAAe,CAAC,QAAQ,EAAU,aAAa,EAAmB;AAClF,EAAE,OAAO,aAAa,CAAC,QAAQ,KAAK,aAAA,KAAkB,KAAK;AAC3D;;AAEA;AACA;AACA;AACA;AACA;AACO,SAAS,eAAe,CAAC,QAAQ,EAAU,aAAa,EAAmB;AAClF,EAAE,OAAO,aAAa,CAAC,QAAQ,KAAK,aAAA,KAAkB,MAAM;AAC5D;;AAEA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,QAAQ,EAAmB;AACzD,EAAE,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;AACnC;;AAEO,MAAM,mCAAoC,GAAE;;;;"}
@@ -0,0 +1,31 @@
1
+ import { defineIntegration } from '@sentry/core';
2
+ import { generateInstrumentOnce } from '@sentry/node';
3
+ import { ReactRouterInstrumentation } from '../instrumentation/reactRouter.js';
4
+
5
+ const INTEGRATION_NAME = 'ReactRouterServer';
6
+
7
+ const instrumentReactRouter = generateInstrumentOnce('React-Router-Server', () => {
8
+ return new ReactRouterInstrumentation();
9
+ });
10
+
11
+ const instrumentReactRouterServer = Object.assign(
12
+ () => {
13
+ instrumentReactRouter();
14
+ },
15
+ { id: INTEGRATION_NAME },
16
+ );
17
+
18
+ /**
19
+ * Integration capturing tracing data for React Router server functions.
20
+ */
21
+ const reactRouterServerIntegration = defineIntegration(() => {
22
+ return {
23
+ name: INTEGRATION_NAME,
24
+ setupOnce() {
25
+ instrumentReactRouterServer();
26
+ },
27
+ };
28
+ });
29
+
30
+ export { instrumentReactRouterServer, reactRouterServerIntegration };
31
+ //# sourceMappingURL=reactRouterServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactRouterServer.js","sources":["../../../../src/server/integration/reactRouterServer.ts"],"sourcesContent":["import { defineIntegration } from '@sentry/core';\nimport { generateInstrumentOnce } from '@sentry/node';\nimport { ReactRouterInstrumentation } from '../instrumentation/reactRouter';\n\nconst INTEGRATION_NAME = 'ReactRouterServer';\n\nconst instrumentReactRouter = generateInstrumentOnce('React-Router-Server', () => {\n return new ReactRouterInstrumentation();\n});\n\nexport const instrumentReactRouterServer = Object.assign(\n (): void => {\n instrumentReactRouter();\n },\n { id: INTEGRATION_NAME },\n);\n\n/**\n * Integration capturing tracing data for React Router server functions.\n */\nexport const reactRouterServerIntegration = defineIntegration(() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n instrumentReactRouterServer();\n },\n };\n});\n"],"names":[],"mappings":";;;;AAIA,MAAM,gBAAA,GAAmB,mBAAmB;;AAE5C,MAAM,qBAAA,GAAwB,sBAAsB,CAAC,qBAAqB,EAAE,MAAM;AAClF,EAAE,OAAO,IAAI,0BAA0B,EAAE;AACzC,CAAC,CAAC;;AAEW,MAAA,2BAAA,GAA8B,MAAM,CAAC,MAAM;AACxD,EAAE,MAAY;AACd,IAAI,qBAAqB,EAAE;AAC3B,GAAG;AACH,EAAE,EAAE,EAAE,EAAE,gBAAA,EAAkB;AAC1B;;AAEA;AACA;AACA;MACa,4BAA6B,GAAE,iBAAiB,CAAC,MAAM;AACpE,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB,MAAM,2BAA2B,EAAE;AACnC,KAAK;AACL,GAAG;AACH,CAAC;;;;"}
@@ -0,0 +1,38 @@
1
+ import { defineIntegration, logger } from '@sentry/core';
2
+
3
+ /**
4
+ * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/
5
+ *
6
+ */
7
+
8
+ function _lowQualityTransactionsFilterIntegration(options)
9
+
10
+ {
11
+ const matchedRegexes = [/GET \/node_modules\//, /GET \/favicon\.ico/, /GET \/@id\//];
12
+
13
+ return {
14
+ name: 'LowQualityTransactionsFilter',
15
+
16
+ processEvent(event, _hint, _client) {
17
+ if (event.type !== 'transaction' || !event.transaction) {
18
+ return event;
19
+ }
20
+
21
+ const transaction = event.transaction;
22
+
23
+ if (matchedRegexes.some(regex => transaction.match(regex))) {
24
+ options.debug && logger.log('[ReactRouter] Filtered node_modules transaction:', event.transaction);
25
+ return null;
26
+ }
27
+
28
+ return event;
29
+ },
30
+ };
31
+ }
32
+
33
+ const lowQualityTransactionsFilterIntegration = defineIntegration((options) =>
34
+ _lowQualityTransactionsFilterIntegration(options),
35
+ );
36
+
37
+ export { lowQualityTransactionsFilterIntegration };
38
+ //# sourceMappingURL=lowQualityTransactionsFilterIntegration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../src/server/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import { type Client, type Event, type EventHint, defineIntegration, logger } from '@sentry/core';\nimport type { NodeOptions } from '@sentry/node';\n\n/**\n * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/\n *\n */\n\nfunction _lowQualityTransactionsFilterIntegration(options: NodeOptions): {\n name: string;\n processEvent: (event: Event, hint: EventHint, client: Client) => Event | null;\n} {\n const matchedRegexes = [/GET \\/node_modules\\//, /GET \\/favicon\\.ico/, /GET \\/@id\\//];\n\n return {\n name: 'LowQualityTransactionsFilter',\n\n processEvent(event: Event, _hint: EventHint, _client: Client): Event | null {\n if (event.type !== 'transaction' || !event.transaction) {\n return event;\n }\n\n const transaction = event.transaction;\n\n if (matchedRegexes.some(regex => transaction.match(regex))) {\n options.debug && logger.log('[ReactRouter] Filtered node_modules transaction:', event.transaction);\n return null;\n }\n\n return event;\n },\n };\n}\n\nexport const lowQualityTransactionsFilterIntegration = defineIntegration((options: NodeOptions) =>\n _lowQualityTransactionsFilterIntegration(options),\n);\n"],"names":[],"mappings":";;AAGA;AACA;AACA;AACA;;AAEA,SAAS,wCAAwC,CAAC,OAAO;;AAGzD,CAAE;AACF,EAAE,MAAM,iBAAiB,CAAC,sBAAsB,EAAE,oBAAoB,EAAE,aAAa,CAAC;;AAEtF,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,8BAA8B;;AAExC,IAAI,YAAY,CAAC,KAAK,EAAS,KAAK,EAAa,OAAO,EAAwB;AAChF,MAAM,IAAI,KAAK,CAAC,IAAK,KAAI,aAAc,IAAG,CAAC,KAAK,CAAC,WAAW,EAAE;AAC9D,QAAQ,OAAO,KAAK;AACpB;;AAEA,MAAM,MAAM,WAAA,GAAc,KAAK,CAAC,WAAW;;AAE3C,MAAM,IAAI,cAAc,CAAC,IAAI,CAAC,KAAA,IAAS,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE;AAClE,QAAQ,OAAO,CAAC,KAAM,IAAG,MAAM,CAAC,GAAG,CAAC,kDAAkD,EAAE,KAAK,CAAC,WAAW,CAAC;AAC1G,QAAQ,OAAO,IAAI;AACnB;;AAEA,MAAM,OAAO,KAAK;AAClB,KAAK;AACL,GAAG;AACH;;MAEa,uCAAwC,GAAE,iBAAiB,CAAC,CAAC,OAAO;AACjF,EAAE,wCAAwC,CAAC,OAAO,CAAC;AACnD;;;;"}
@@ -1,6 +1,22 @@
1
- import { logger, applySdkMetadata, setTag } from '@sentry/core';
2
- import { init as init$1 } from '@sentry/node';
1
+ import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';
2
+ import { logger, applySdkMetadata, setTag, getGlobalScope } from '@sentry/core';
3
+ import { init as init$1, getDefaultIntegrations } from '@sentry/node';
3
4
  import { DEBUG_BUILD } from '../common/debug-build.js';
5
+ import { SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE } from './instrumentation/util.js';
6
+ import { reactRouterServerIntegration } from './integration/reactRouterServer.js';
7
+ import { lowQualityTransactionsFilterIntegration } from './lowQualityTransactionsFilterIntegration.js';
8
+
9
+ /**
10
+ * Returns the default integrations for the React Router SDK.
11
+ * @param options The options for the SDK.
12
+ */
13
+ function getDefaultReactRouterServerIntegrations(options) {
14
+ return [
15
+ ...getDefaultIntegrations(options),
16
+ lowQualityTransactionsFilterIntegration(options),
17
+ reactRouterServerIntegration(),
18
+ ];
19
+ }
4
20
 
5
21
  /**
6
22
  * Initializes the server side of the React Router SDK
@@ -8,6 +24,7 @@ import { DEBUG_BUILD } from '../common/debug-build.js';
8
24
  function init(options) {
9
25
  const opts = {
10
26
  ...options,
27
+ defaultIntegrations: getDefaultReactRouterServerIntegrations(options),
11
28
  };
12
29
 
13
30
  DEBUG_BUILD && logger.log('Initializing SDK...');
@@ -18,9 +35,35 @@ function init(options) {
18
35
 
19
36
  setTag('runtime', 'node');
20
37
 
38
+ // Overwrite the transaction name for instrumented data loaders because the trace data gets overwritten at a later point.
39
+ // We only update the tx in case SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE got set in our instrumentation before.
40
+ getGlobalScope().addEventProcessor(
41
+ Object.assign(
42
+ (event => {
43
+ const overwrite = event.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];
44
+ if (
45
+ event.type === 'transaction' &&
46
+ event.transaction === 'GET *' &&
47
+ event.contexts?.trace?.data?.[ATTR_HTTP_ROUTE] === '*' &&
48
+ overwrite
49
+ ) {
50
+ event.transaction = overwrite;
51
+ event.contexts.trace.data[ATTR_HTTP_ROUTE] = 'url';
52
+ }
53
+
54
+ // always yeet this attribute into the void, as this should not reach the server
55
+ delete event.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];
56
+
57
+ return event;
58
+ }) ,
59
+ { id: 'ReactRouterTransactionEnhancer' },
60
+ ),
61
+ );
62
+
21
63
  DEBUG_BUILD && logger.log('SDK successfully initialized');
64
+
22
65
  return client;
23
66
  }
24
67
 
25
- export { init };
68
+ export { getDefaultReactRouterServerIntegrations, init };
26
69
  //# sourceMappingURL=sdk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import { applySdkMetadata, logger, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts = {\n ...options,\n };\n\n DEBUG_BUILD && logger.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n DEBUG_BUILD && logger.log('SDK successfully initialized');\n return client;\n}\n"],"names":["initNodeSdk"],"mappings":";;;;AAKA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuC;AACnE,EAAE,MAAM,OAAO;AACf,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAE,eAAe,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC;;AAElD,EAAE,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;;AAElE,EAAE,MAAM,MAAO,GAAEA,MAAW,CAAC,IAAI,CAAC;;AAElC,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;;AAE3B,EAAE,eAAe,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC;AAC3D,EAAE,OAAO,MAAM;AACf;;;;"}
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport type { EventProcessor, Integration } from '@sentry/core';\nimport { applySdkMetadata, getGlobalScope, logger, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getNodeDefaultIntegrations, init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE } from './instrumentation/util';\nimport { reactRouterServerIntegration } from './integration/reactRouterServer';\nimport { lowQualityTransactionsFilterIntegration } from './lowQualityTransactionsFilterIntegration';\n\n/**\n * Returns the default integrations for the React Router SDK.\n * @param options The options for the SDK.\n */\nexport function getDefaultReactRouterServerIntegrations(options: NodeOptions): Integration[] {\n return [\n ...getNodeDefaultIntegrations(options),\n lowQualityTransactionsFilterIntegration(options),\n reactRouterServerIntegration(),\n ];\n}\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts: NodeOptions = {\n ...options,\n defaultIntegrations: getDefaultReactRouterServerIntegrations(options),\n };\n\n DEBUG_BUILD && logger.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n // Overwrite the transaction name for instrumented data loaders because the trace data gets overwritten at a later point.\n // We only update the tx in case SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE got set in our instrumentation before.\n getGlobalScope().addEventProcessor(\n Object.assign(\n (event => {\n const overwrite = event.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];\n if (\n event.type === 'transaction' &&\n event.transaction === 'GET *' &&\n event.contexts?.trace?.data?.[ATTR_HTTP_ROUTE] === '*' &&\n overwrite\n ) {\n event.transaction = overwrite;\n event.contexts.trace.data[ATTR_HTTP_ROUTE] = 'url';\n }\n\n // always yeet this attribute into the void, as this should not reach the server\n delete event.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE];\n\n return event;\n }) satisfies EventProcessor,\n { id: 'ReactRouterTransactionEnhancer' },\n ),\n );\n\n DEBUG_BUILD && logger.log('SDK successfully initialized');\n\n return client;\n}\n"],"names":["getNodeDefaultIntegrations","initNodeSdk"],"mappings":";;;;;;;;AAUA;AACA;AACA;AACA;AACO,SAAS,uCAAuC,CAAC,OAAO,EAA8B;AAC7F,EAAE,OAAO;AACT,IAAI,GAAGA,sBAA0B,CAAC,OAAO,CAAC;AAC1C,IAAI,uCAAuC,CAAC,OAAO,CAAC;AACpD,IAAI,4BAA4B,EAAE;AAClC,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuC;AACnE,EAAE,MAAM,IAAI,GAAgB;AAC5B,IAAI,GAAG,OAAO;AACd,IAAI,mBAAmB,EAAE,uCAAuC,CAAC,OAAO,CAAC;AACzE,GAAG;;AAEH,EAAE,eAAe,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC;;AAElD,EAAE,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;;AAElE,EAAE,MAAM,MAAO,GAAEC,MAAW,CAAC,IAAI,CAAC;;AAElC,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;;AAE3B;AACA;AACA,EAAE,cAAc,EAAE,CAAC,iBAAiB;AACpC,IAAI,MAAM,CAAC,MAAM;AACjB,OAAO,SAAS;AAChB,QAAQ,MAAM,SAAA,GAAY,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAG,mCAAmC,CAAC;AAC5F,QAAQ;AACR,UAAU,KAAK,CAAC,IAAK,KAAI,aAAc;AACvC,UAAU,KAAK,CAAC,WAAY,KAAI,OAAQ;AACxC,UAAU,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAG,eAAe,CAAE,KAAI,GAAI;AACjE,UAAU;AACV,UAAU;AACV,UAAU,KAAK,CAAC,WAAY,GAAE,SAAS;AACvC,UAAU,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAE,GAAE,KAAK;AAC5D;;AAEA;AACA,QAAQ,OAAO,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAG,mCAAmC,CAAC;;AAEjF,QAAQ,OAAO,KAAK;AACpB,OAAO;AACP,MAAM,EAAE,EAAE,EAAE,gCAAA,EAAkC;AAC9C,KAAK;AACL,GAAG;;AAEH,EAAE,eAAe,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC;;AAE3D,EAAE,OAAO,MAAM;AACf;;;;"}
@@ -1,7 +1,7 @@
1
1
  import { context } from '@opentelemetry/api';
2
2
  import { getRPCMetadata, RPCType } from '@opentelemetry/core';
3
3
  import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';
4
- import { getActiveSpan, getRootSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, getTraceMetaTags } from '@sentry/core';
4
+ import { getActiveSpan, getRootSpan, SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, getTraceMetaTags } from '@sentry/core';
5
5
  import { Transform } from 'stream';
6
6
 
7
7
  /**
@@ -20,6 +20,7 @@ function wrapSentryHandleRequest(originalHandle) {
20
20
  ) {
21
21
  const parameterizedPath =
22
22
  routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;
23
+
23
24
  if (parameterizedPath) {
24
25
  const activeSpan = getActiveSpan();
25
26
  if (activeSpan) {
@@ -28,6 +29,7 @@ function wrapSentryHandleRequest(originalHandle) {
28
29
 
29
30
  // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.
30
31
  const rpcMetadata = getRPCMetadata(context.active());
32
+
31
33
  if (rpcMetadata?.type === RPCType.HTTP) {
32
34
  rpcMetadata.route = routeName;
33
35
  }
@@ -36,6 +38,7 @@ function wrapSentryHandleRequest(originalHandle) {
36
38
  rootSpan.setAttributes({
37
39
  [ATTR_HTTP_ROUTE]: routeName,
38
40
  [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
41
+ [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: `${request.method} ${routeName}`,
39
42
  });
40
43
  }
41
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport { getActiveSpan, getRootSpan, getTraceMetaTags, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\nimport type { PassThrough } from 'stream';\nimport { Transform } from 'stream';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n ) {\n const parameterizedPath =\n routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;\n if (parameterizedPath) {\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n const rootSpan = getRootSpan(activeSpan);\n const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n });\n }\n }\n\n return originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n };\n}\n\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\n\n/**\n * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n *\n * @param body - PassThrough stream containing the HTML response body to modify\n */\nexport function getMetaTagTransformer(body: PassThrough): Transform {\n const headClosingTag = '</head>';\n const htmlMetaTagTransformer = new Transform({\n transform(chunk, _encoding, callback) {\n const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n callback(null, modifiedHtml);\n return;\n }\n callback(null, chunk);\n },\n });\n htmlMetaTagTransformer.pipe(body);\n return htmlMetaTagTransformer;\n}\n"],"names":[],"mappings":";;;;;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAkB;AAC5B,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;AACvH,IAAI,IAAI,iBAAiB,EAAE;AAC3B,MAAM,MAAM,UAAA,GAAa,aAAa,EAAE;AACxC,MAAM,IAAI,UAAU,EAAE;AACtB,QAAQ,MAAM,QAAS,GAAE,WAAW,CAAC,UAAU,CAAC;AAChD,QAAQ,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,QAAA,MAAA,WAAA,GAAA,cAAA,CAAA,OAAA,CAAA,MAAA,EAAA,CAAA;AACA,QAAA,IAAA,WAAA,EAAA,IAAA,KAAA,OAAA,CAAA,IAAA,EAAA;AACA,UAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,QAAA,QAAA,CAAA,aAAA,CAAA;AACA,UAAA,CAAA,eAAA,GAAA,SAAA;AACA,UAAA,CAAA,gCAAA,GAAA,OAAA;AACA,SAAA,CAAA;AACA;AACA;;AAEA,IAAA,OAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,GAAA;AACA;;AAEA;AACA,MAAA,mBAAA,GAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,IAAA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,SAAA;AACA,EAAA,MAAA,sBAAA,GAAA,IAAA,SAAA,CAAA;AACA,IAAA,SAAA,CAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA;AACA,MAAA,MAAA,IAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,GAAA,KAAA,CAAA,QAAA,EAAA,GAAA,MAAA,CAAA,KAAA,CAAA;AACA,MAAA,IAAA,IAAA,CAAA,QAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,YAAA,GAAA,IAAA,CAAA,OAAA,CAAA,cAAA,EAAA,CAAA,EAAA,gBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;"}
1
+ {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport {\n getActiveSpan,\n getRootSpan,\n getTraceMetaTags,\n SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\nimport type { PassThrough } from 'stream';\nimport { Transform } from 'stream';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n ) {\n const parameterizedPath =\n routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;\n\n if (parameterizedPath) {\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n const rootSpan = getRootSpan(activeSpan);\n const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME]: `${request.method} ${routeName}`,\n });\n }\n }\n\n return originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n };\n}\n\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\n\n/**\n * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n *\n * @param body - PassThrough stream containing the HTML response body to modify\n */\nexport function getMetaTagTransformer(body: PassThrough): Transform {\n const headClosingTag = '</head>';\n const htmlMetaTagTransformer = new Transform({\n transform(chunk, _encoding, callback) {\n const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n callback(null, modifiedHtml);\n return;\n }\n callback(null, chunk);\n },\n });\n htmlMetaTagTransformer.pipe(body);\n return htmlMetaTagTransformer;\n}\n"],"names":[],"mappings":";;;;;;AAsBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAkB;AAC5B,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;;AAEvH,IAAI,IAAI,iBAAiB,EAAE;AAC3B,MAAM,MAAM,UAAA,GAAa,aAAa,EAAE;AACxC,MAAM,IAAI,UAAU,EAAE;AACtB,QAAQ,MAAM,QAAS,GAAE,WAAW,CAAC,UAAU,CAAC;AAChD,QAAQ,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,QAAA,MAAA,WAAA,GAAA,cAAA,CAAA,OAAA,CAAA,MAAA,EAAA,CAAA;;AAEA,QAAA,IAAA,WAAA,EAAA,IAAA,KAAA,OAAA,CAAA,IAAA,EAAA;AACA,UAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,QAAA,QAAA,CAAA,aAAA,CAAA;AACA,UAAA,CAAA,eAAA,GAAA,SAAA;AACA,UAAA,CAAA,gCAAA,GAAA,OAAA;AACA,UAAA,CAAA,0CAAA,GAAA,CAAA,EAAA,OAAA,CAAA,MAAA,CAAA,CAAA,EAAA,SAAA,CAAA,CAAA;AACA,SAAA,CAAA;AACA;AACA;;AAEA,IAAA,OAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,GAAA;AACA;;AAEA;AACA,MAAA,mBAAA,GAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,IAAA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,SAAA;AACA,EAAA,MAAA,sBAAA,GAAA,IAAA,SAAA,CAAA;AACA,IAAA,SAAA,CAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA;AACA,MAAA,MAAA,IAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,GAAA,KAAA,CAAA,QAAA,EAAA,GAAA,MAAA,CAAA,KAAA,CAAA;AACA,MAAA,IAAA,IAAA,CAAA,QAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,YAAA,GAAA,IAAA,CAAA,OAAA,CAAA,cAAA,EAAA,CAAA,EAAA,gBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;"}
@@ -0,0 +1,19 @@
1
+ import type { InstrumentationConfig } from '@opentelemetry/instrumentation';
2
+ import { InstrumentationBase, InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation';
3
+ /**
4
+ * Instrumentation for React Router's server request handler.
5
+ * This patches the requestHandler function to add Sentry performance monitoring for data loaders.
6
+ */
7
+ export declare class ReactRouterInstrumentation extends InstrumentationBase<InstrumentationConfig> {
8
+ constructor(config?: InstrumentationConfig);
9
+ /**
10
+ * Initializes the instrumentation by defining the React Router server modules to be patched.
11
+ */
12
+ protected init(): InstrumentationNodeModuleDefinition;
13
+ /**
14
+ * Creates a proxy around the React Router module exports that patches the createRequestHandler function.
15
+ * This allows us to wrap the request handler to add performance monitoring for data loaders and actions.
16
+ */
17
+ private _createPatchedModuleProxy;
18
+ }
19
+ //# sourceMappingURL=reactRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactRouter.d.ts","sourceRoot":"","sources":["../../../../src/server/instrumentation/reactRouter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,mCAAmC,EAAE,MAAM,gCAAgC,CAAC;AAoB1G;;;GAGG;AACH,qBAAa,0BAA2B,SAAQ,mBAAmB,CAAC,qBAAqB,CAAC;gBACrE,MAAM,GAAE,qBAA0B;IAIrD;;OAEG;IAEH,SAAS,CAAC,IAAI,IAAI,mCAAmC;IAgBrD;;;OAGG;IACH,OAAO,CAAC,yBAAyB;CAwDlC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Gets the op name for a request based on whether it's a loader or action request.
3
+ * @param pathName The URL pathname to check
4
+ * @param requestMethod The HTTP request method
5
+ */
6
+ export declare function getOpName(pathName: string, requestMethod: string): string;
7
+ /**
8
+ * Gets the span name for a request based on whether it's a loader or action request.
9
+ * @param pathName The URL pathname to check
10
+ * @param requestMethod The HTTP request method
11
+ */
12
+ export declare function getSpanName(pathName: string, requestMethod: string): string;
13
+ /**
14
+ * Checks if the request is a server loader request
15
+ * @param pathname The URL pathname to check
16
+ * @param requestMethod The HTTP request method
17
+ */
18
+ export declare function isLoaderRequest(pathname: string, requestMethod: string): boolean;
19
+ /**
20
+ * Checks if the request is a server action request
21
+ * @param pathname The URL pathname to check
22
+ * @param requestMethod The HTTP request method
23
+ */
24
+ export declare function isActionRequest(pathname: string, requestMethod: string): boolean;
25
+ /**
26
+ * Checks if the request is a react-router data request
27
+ * @param pathname The URL pathname to check
28
+ */
29
+ export declare function isDataRequest(pathname: string): boolean;
30
+ export declare const SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE = "sentry.overwrite-route";
31
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../src/server/instrumentation/util.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAMzE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAM3E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAEhF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,eAAO,MAAM,mCAAmC,2BAA2B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare const instrumentReactRouterServer: (() => void) & {
2
+ id: string;
3
+ };
4
+ /**
5
+ * Integration capturing tracing data for React Router server functions.
6
+ */
7
+ export declare const reactRouterServerIntegration: () => import("@sentry/core").Integration;
8
+ //# sourceMappingURL=reactRouterServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactRouterServer.d.ts","sourceRoot":"","sources":["../../../../src/server/integration/reactRouterServer.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,2BAA2B,SAClC,IAAI;;CAIT,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,0CAOvC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { NodeOptions } from '@sentry/node';
2
+ export declare const lowQualityTransactionsFilterIntegration: (options: NodeOptions) => import("@sentry/core").Integration;
3
+ //# sourceMappingURL=lowQualityTransactionsFilterIntegration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lowQualityTransactionsFilterIntegration.d.ts","sourceRoot":"","sources":["../../../src/server/lowQualityTransactionsFilterIntegration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAiChD,eAAO,MAAM,uCAAuC,8DAEnD,CAAC"}
@@ -1,4 +1,10 @@
1
+ import type { Integration } from '@sentry/core';
1
2
  import type { NodeClient, NodeOptions } from '@sentry/node';
3
+ /**
4
+ * Returns the default integrations for the React Router SDK.
5
+ * @param options The options for the SDK.
6
+ */
7
+ export declare function getDefaultReactRouterServerIntegrations(options: NodeOptions): Integration[];
2
8
  /**
3
9
  * Initializes the server side of the React Router SDK
4
10
  */
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/server/sdk.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAI5D;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAejE"}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/server/sdk.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAO5D;;;GAGG;AACH,wBAAgB,uCAAuC,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE,CAM3F;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CA0CjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"wrapSentryHandleRequest.d.ts","sourceRoot":"","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,KAAK,qBAAqB,GAAG,CAC3B,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,YAAY,EAC3B,WAAW,EAAE,cAAc,KACxB,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,qBAAqB,GAAG,qBAAqB,CAgCpG;AAED,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,gCAA0B,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAelE"}
1
+ {"version":3,"file":"wrapSentryHandleRequest.d.ts","sourceRoot":"","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"names":[],"mappings":";AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,KAAK,qBAAqB,GAAG,CAC3B,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,YAAY,EAC3B,WAAW,EAAE,cAAc,KACxB,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,qBAAqB,GAAG,qBAAqB,CAmCpG;AAED,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,gCAA0B,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAelE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/react-router",
3
- "version": "9.17.0",
3
+ "version": "9.19.0",
4
4
  "description": "Official Sentry SDK for React Router (Framework)",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/react-router",
@@ -36,11 +36,12 @@
36
36
  "dependencies": {
37
37
  "@opentelemetry/api": "^1.9.0",
38
38
  "@opentelemetry/core": "^1.30.1",
39
+ "@opentelemetry/instrumentation": "0.57.2",
39
40
  "@opentelemetry/semantic-conventions": "^1.30.0",
40
- "@sentry/browser": "9.17.0",
41
+ "@sentry/browser": "9.19.0",
41
42
  "@sentry/cli": "^2.43.0",
42
- "@sentry/core": "9.17.0",
43
- "@sentry/node": "9.17.0",
43
+ "@sentry/core": "9.19.0",
44
+ "@sentry/node": "9.19.0",
44
45
  "@sentry/vite-plugin": "^3.2.4",
45
46
  "glob": "11.0.1"
46
47
  },