@sentry/react-router 11.0.0-alpha.1 → 11.0.0-alpha.2
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.
- package/README.md +2 -2
- package/build/cjs/client/createClientInstrumentation.js +30 -23
- package/build/cjs/client/createClientInstrumentation.js.map +1 -1
- package/build/cjs/client/hydratedRouter.js +11 -19
- package/build/cjs/client/hydratedRouter.js.map +1 -1
- package/build/cjs/client/tracingIntegration.js.map +1 -1
- package/build/cjs/client/utils.js +32 -12
- package/build/cjs/client/utils.js.map +1 -1
- package/build/cjs/cloudflare/index.js +3 -2
- package/build/cjs/cloudflare/index.js.map +1 -1
- package/build/cjs/common/utils.js.map +1 -1
- package/build/cjs/index.server.js +0 -6
- package/build/cjs/index.server.js.map +1 -1
- package/build/cjs/server/createServerInstrumentation.js +22 -15
- package/build/cjs/server/createServerInstrumentation.js.map +1 -1
- package/build/cjs/server/getMetaTagTransformer.js +3 -2
- package/build/cjs/server/getMetaTagTransformer.js.map +1 -1
- package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js +3 -2
- package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
- package/build/cjs/server/wrapSentryHandleRequest.js +2 -2
- package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +17 -29
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/cjs/vite/index.js +12 -0
- package/build/cjs/vite/index.js.map +1 -0
- package/build/cjs/vite/makeCustomSentryVitePlugins.js +21 -32
- package/build/cjs/vite/makeCustomSentryVitePlugins.js.map +1 -1
- package/build/esm/client/createClientInstrumentation.js +22 -15
- package/build/esm/client/createClientInstrumentation.js.map +1 -1
- package/build/esm/client/hydratedRouter.js +14 -22
- package/build/esm/client/hydratedRouter.js.map +1 -1
- package/build/esm/client/tracingIntegration.js.map +1 -1
- package/build/esm/client/utils.js +34 -14
- package/build/esm/client/utils.js.map +1 -1
- package/build/esm/cloudflare/index.js +3 -2
- package/build/esm/cloudflare/index.js.map +1 -1
- package/build/esm/common/utils.js.map +1 -1
- package/build/esm/index.server.js +0 -3
- package/build/esm/index.server.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server/createServerInstrumentation.js +25 -18
- package/build/esm/server/createServerInstrumentation.js.map +1 -1
- package/build/esm/server/getMetaTagTransformer.js +3 -2
- package/build/esm/server/getMetaTagTransformer.js.map +1 -1
- package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js +3 -2
- package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
- package/build/esm/server/wrapSentryHandleRequest.js +4 -4
- package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js +17 -29
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/esm/vite/index.js +4 -0
- package/build/esm/vite/index.js.map +1 -0
- package/build/esm/vite/makeCustomSentryVitePlugins.js +21 -32
- package/build/esm/vite/makeCustomSentryVitePlugins.js.map +1 -1
- package/build/types/client/createClientInstrumentation.d.ts +1 -1
- package/build/types/client/createClientInstrumentation.d.ts.map +1 -1
- package/build/types/client/hydratedRouter.d.ts.map +1 -1
- package/build/types/client/tracingIntegration.d.ts +1 -1
- package/build/types/client/tracingIntegration.d.ts.map +1 -1
- package/build/types/client/utils.d.ts +7 -1
- package/build/types/client/utils.d.ts.map +1 -1
- package/build/types/cloudflare/index.d.ts.map +1 -1
- package/build/types/common/utils.d.ts +3 -2
- package/build/types/common/utils.d.ts.map +1 -1
- package/build/types/index.server.d.ts +0 -1
- package/build/types/index.server.d.ts.map +1 -1
- package/build/types/index.types.d.ts +3 -1
- package/build/types/index.types.d.ts.map +1 -1
- package/build/types/server/createServerInstrumentation.d.ts +1 -1
- package/build/types/server/createServerInstrumentation.d.ts.map +1 -1
- package/build/types/server/getMetaTagTransformer.d.ts.map +1 -1
- package/build/types/server/integration/lowQualityTransactionsFilterIntegration.d.ts.map +1 -1
- package/build/types/server/wrapSentryHandleRequest.d.ts.map +1 -1
- package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts.map +1 -1
- package/build/types/vite/makeCustomSentryVitePlugins.d.ts.map +1 -1
- package/build/types/vite/types.d.ts +15 -13
- package/build/types/vite/types.d.ts.map +1 -1
- package/package.json +16 -10
- package/build/types/common/types.d.ts +0 -86
- package/build/types/common/types.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/common/utils.ts"],"sourcesContent":["import { captureException, debug } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/common/utils.ts"],"sourcesContent":["import { captureException, debug } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\n\n/**\n * Extracts pathname from request URL.\n * Falls back to '<unknown>' with DEBUG warning if URL cannot be parsed.\n */\nexport function getPathFromRequest(request: { url: string }): string {\n try {\n return new URL(request.url).pathname;\n } catch {\n try {\n // Fallback: use a dummy base URL since we only care about the pathname\n return new URL(request.url, 'http://example.com').pathname;\n } catch (error) {\n DEBUG_BUILD && debug.warn('Failed to parse URL from request:', request.url, error);\n return '<unknown>';\n }\n }\n}\n\n/**\n * Extracts route pattern from instrumentation info.\n * Prefers `pattern` (planned for v8) over `unstable_pattern` (v7.x).\n */\nexport function getPattern(info: { pattern?: string; unstable_pattern?: string }): string | undefined {\n return info.pattern ?? info.unstable_pattern;\n}\n\n/**\n * Normalizes route path by ensuring it starts with a slash.\n * Returns undefined if the input is falsy.\n */\nexport function normalizeRoutePath(pattern?: string): string | undefined {\n if (!pattern) {\n return undefined;\n }\n return pattern.startsWith('/') ? pattern : `/${pattern}`;\n}\n\n/**\n * Captures an error from instrumentation result.\n * Caller must verify result contains an Error before calling.\n */\nexport function captureInstrumentationError(\n result: { error: unknown },\n captureErrors: boolean,\n mechanismType: string,\n data: Record<string, string | boolean>,\n): void {\n if (captureErrors) {\n captureException(result.error, {\n mechanism: {\n type: mechanismType,\n handled: false,\n data,\n },\n });\n }\n}\n"],"names":["DEBUG_BUILD","debug","captureException"],"mappings":";;;;;AAOO,SAAS,mBAAmB,OAAA,EAAkC;AACnE,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA,CAAE,QAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI;AAEF,MAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,EAAK,oBAAoB,CAAA,CAAE,QAAA;AAAA,IACpD,SAAS,KAAA,EAAO;AACd,MAAAA,sBAAA,IAAeC,UAAA,CAAM,IAAA,CAAK,mCAAA,EAAqC,OAAA,CAAQ,KAAK,KAAK,CAAA;AACjF,MAAA,OAAO,WAAA;AAAA,IACT;AAAA,EACF;AACF;AAMO,SAAS,WAAW,IAAA,EAA2E;AACpG,EAAA,OAAO,IAAA,CAAK,WAAW,IAAA,CAAK,gBAAA;AAC9B;AAMO,SAAS,mBAAmB,OAAA,EAAsC;AACvE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAQ,UAAA,CAAW,GAAG,CAAA,GAAI,OAAA,GAAU,IAAI,OAAO,CAAA,CAAA;AACxD;AAMO,SAAS,2BAAA,CACd,MAAA,EACA,aAAA,EACA,aAAA,EACA,IAAA,EACM;AACN,EAAA,IAAI,aAAA,EAAe;AACjB,IAAAC,qBAAA,CAAiB,OAAO,KAAA,EAAO;AAAA,MAC7B,SAAA,EAAW;AAAA,QACT,IAAA,EAAM,aAAA;AAAA,QACN,OAAA,EAAS,KAAA;AAAA,QACT;AAAA;AACF,KACD,CAAA;AAAA,EACH;AACF;;;;;;;"}
|
|
@@ -7,9 +7,6 @@ const createSentryHandleRequest = require('./server/createSentryHandleRequest.js
|
|
|
7
7
|
const createSentryHandleError = require('./server/createSentryHandleError.js');
|
|
8
8
|
const getMetaTagTransformer = require('./server/getMetaTagTransformer.js');
|
|
9
9
|
const createServerInstrumentation = require('./server/createServerInstrumentation.js');
|
|
10
|
-
const plugin = require('./vite/plugin.js');
|
|
11
|
-
const handleOnBuildEnd = require('./vite/buildEnd/handleOnBuildEnd.js');
|
|
12
|
-
const makeConfigInjectorPlugin = require('./vite/makeConfigInjectorPlugin.js');
|
|
13
10
|
const serverGlobals = require('./server/serverGlobals.js');
|
|
14
11
|
|
|
15
12
|
|
|
@@ -20,9 +17,6 @@ exports.createSentryHandleRequest = createSentryHandleRequest.createSentryHandle
|
|
|
20
17
|
exports.createSentryHandleError = createSentryHandleError.createSentryHandleError;
|
|
21
18
|
exports.getMetaTagTransformer = getMetaTagTransformer.getMetaTagTransformer;
|
|
22
19
|
exports.createSentryServerInstrumentation = createServerInstrumentation.createSentryServerInstrumentation;
|
|
23
|
-
exports.sentryReactRouter = plugin.sentryReactRouter;
|
|
24
|
-
exports.sentryOnBuildEnd = handleOnBuildEnd.sentryOnBuildEnd;
|
|
25
|
-
exports.makeConfigInjectorPlugin = makeConfigInjectorPlugin.makeConfigInjectorPlugin;
|
|
26
20
|
exports.isInstrumentationApiUsed = serverGlobals.isInstrumentationApiUsed;
|
|
27
21
|
Object.prototype.hasOwnProperty.call(node, '__proto__') &&
|
|
28
22
|
!Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -20,12 +20,14 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
20
20
|
const pathname = utils.getPathFromRequest(info.request);
|
|
21
21
|
const activeSpan = core.getActiveSpan();
|
|
22
22
|
const existingRootSpan = activeSpan ? core.getRootSpan(activeSpan) : void 0;
|
|
23
|
+
const client = core.getClient();
|
|
24
|
+
const unparameterizedName = client && core.hasSpanStreamingEnabled(client) ? info.request.method?.toUpperCase() || core.HTTP_SPAN_NAME_FALLBACK : `${info.request.method} ${pathname}`;
|
|
23
25
|
if (existingRootSpan) {
|
|
24
|
-
core.updateSpanName(existingRootSpan,
|
|
26
|
+
core.updateSpanName(existingRootSpan, unparameterizedName);
|
|
25
27
|
existingRootSpan.setAttributes({
|
|
26
28
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
|
|
27
29
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
|
|
28
|
-
[
|
|
30
|
+
[attributes.SENTRY_SEGMENT_NAME_SOURCE]: "url",
|
|
29
31
|
[attributes.URL_FULL]: core.filterCollectedUrl(info.request.url),
|
|
30
32
|
[attributes.URL_PATH]: pathname
|
|
31
33
|
});
|
|
@@ -34,7 +36,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
34
36
|
if (result.status === "error" && result.error instanceof Error) {
|
|
35
37
|
existingRootSpan.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
36
38
|
utils.captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
|
|
37
|
-
|
|
39
|
+
[attributes.HTTP_REQUEST_METHOD]: info.request.method,
|
|
38
40
|
[attributes.URL_FULL]: pathname
|
|
39
41
|
});
|
|
40
42
|
}
|
|
@@ -44,12 +46,12 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
44
46
|
} else {
|
|
45
47
|
await core.startSpan(
|
|
46
48
|
{
|
|
47
|
-
name:
|
|
49
|
+
name: unparameterizedName,
|
|
48
50
|
forceTransaction: true,
|
|
49
51
|
attributes: {
|
|
50
52
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
|
|
51
53
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
|
|
52
|
-
[
|
|
54
|
+
[attributes.SENTRY_SEGMENT_NAME_SOURCE]: "url",
|
|
53
55
|
[attributes.HTTP_REQUEST_METHOD]: info.request.method,
|
|
54
56
|
[attributes.URL_PATH]: pathname,
|
|
55
57
|
[attributes.URL_FULL]: core.filterCollectedUrl(info.request.url)
|
|
@@ -61,7 +63,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
61
63
|
if (result.status === "error" && result.error instanceof Error) {
|
|
62
64
|
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
63
65
|
utils.captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
|
|
64
|
-
|
|
66
|
+
[attributes.HTTP_REQUEST_METHOD]: info.request.method,
|
|
65
67
|
[attributes.URL_FULL]: pathname
|
|
66
68
|
});
|
|
67
69
|
}
|
|
@@ -87,7 +89,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
87
89
|
{
|
|
88
90
|
name: routePattern,
|
|
89
91
|
attributes: {
|
|
90
|
-
[attributes.SENTRY_OP]: op.
|
|
92
|
+
[attributes.SENTRY_OP]: op.FUNCTION,
|
|
91
93
|
[attributes.CODE_FUNCTION_NAME]: "loader",
|
|
92
94
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
93
95
|
}
|
|
@@ -97,7 +99,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
97
99
|
if (result.status === "error" && result.error instanceof Error) {
|
|
98
100
|
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
99
101
|
utils.captureInstrumentationError(result, captureErrors, "react_router.loader", {
|
|
100
|
-
|
|
102
|
+
[attributes.HTTP_REQUEST_METHOD]: info.request.method,
|
|
101
103
|
[attributes.URL_FULL]: urlPath
|
|
102
104
|
});
|
|
103
105
|
}
|
|
@@ -113,7 +115,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
113
115
|
{
|
|
114
116
|
name: routePattern,
|
|
115
117
|
attributes: {
|
|
116
|
-
[attributes.SENTRY_OP]: op.
|
|
118
|
+
[attributes.SENTRY_OP]: op.FUNCTION,
|
|
117
119
|
[attributes.CODE_FUNCTION_NAME]: "action",
|
|
118
120
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
119
121
|
}
|
|
@@ -123,7 +125,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
123
125
|
if (result.status === "error" && result.error instanceof Error) {
|
|
124
126
|
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
125
127
|
utils.captureInstrumentationError(result, captureErrors, "react_router.action", {
|
|
126
|
-
|
|
128
|
+
[attributes.HTTP_REQUEST_METHOD]: info.request.method,
|
|
127
129
|
[attributes.URL_FULL]: urlPath
|
|
128
130
|
});
|
|
129
131
|
}
|
|
@@ -152,7 +154,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
152
154
|
{
|
|
153
155
|
name: `middleware ${middlewareName || routeId}`,
|
|
154
156
|
attributes: {
|
|
155
|
-
[attributes.SENTRY_OP]: op.
|
|
157
|
+
[attributes.SENTRY_OP]: op.MIDDLEWARE,
|
|
156
158
|
[attributes.CODE_FUNCTION_NAME]: "middleware",
|
|
157
159
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api",
|
|
158
160
|
"react_router.route.id": routeId,
|
|
@@ -166,7 +168,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
166
168
|
if (result.status === "error" && result.error instanceof Error) {
|
|
167
169
|
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
168
170
|
utils.captureInstrumentationError(result, captureErrors, "react_router.middleware", {
|
|
169
|
-
|
|
171
|
+
[attributes.HTTP_REQUEST_METHOD]: info.request.method,
|
|
170
172
|
[attributes.URL_FULL]: urlPath
|
|
171
173
|
});
|
|
172
174
|
}
|
|
@@ -178,7 +180,7 @@ function createSentryServerInstrumentation(options = {}) {
|
|
|
178
180
|
{
|
|
179
181
|
name: "Lazy Route Load",
|
|
180
182
|
attributes: {
|
|
181
|
-
[attributes.SENTRY_OP]: op.
|
|
183
|
+
[attributes.SENTRY_OP]: op.FUNCTION,
|
|
182
184
|
[attributes.CODE_FUNCTION_NAME]: "lazy",
|
|
183
185
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
184
186
|
}
|
|
@@ -208,10 +210,15 @@ function updateRootSpanWithRoute(method, pattern, urlPath) {
|
|
|
208
210
|
const hasPattern = !!pattern;
|
|
209
211
|
const routeName = hasPattern ? utils.normalizeRoutePath(pattern) || urlPath : urlPath;
|
|
210
212
|
const transactionName = `${method} ${routeName}`;
|
|
211
|
-
core.
|
|
213
|
+
const client = core.getClient();
|
|
214
|
+
const isUnparameterizedStreamedSpan = !hasPattern && !!client && core.hasSpanStreamingEnabled(client);
|
|
215
|
+
core.updateSpanName(
|
|
216
|
+
rootSpan,
|
|
217
|
+
isUnparameterizedStreamedSpan ? method.toUpperCase() || core.HTTP_SPAN_NAME_FALLBACK : transactionName
|
|
218
|
+
);
|
|
212
219
|
rootSpan.setAttributes({
|
|
213
220
|
[attributes.HTTP_ROUTE]: routeName,
|
|
214
|
-
[
|
|
221
|
+
[attributes.SENTRY_SEGMENT_NAME_SOURCE]: hasPattern ? "route" : "url"
|
|
215
222
|
});
|
|
216
223
|
core.getCurrentScope().setTransactionName(transactionName);
|
|
217
224
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createServerInstrumentation.js","sources":["../../../src/server/createServerInstrumentation.ts"],"sourcesContent":["import {\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_METHOD,\n HTTP_ROUTE,\n SENTRY_OP,\n URL_FULL,\n URL_PATH,\n} from '@sentry/conventions/attributes';\nimport { WEB_SERVER_FUNCTION_SPAN_OP, WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';\nimport {\n debug,\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { InstrumentableRequestHandler, InstrumentableRoute, ServerInstrumentation } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { getMiddlewareName } from './serverBuild';\nimport { markInstrumentationApiUsed } from './serverGlobals';\n\n// Per-request middleware counters, keyed by the request's root span (the one transaction all of a\n// request's middlewares run under). The root span is the same instance across those middleware hooks\n// whether or not a Sentry OpenTelemetry tracer provider is set up, unlike the OTel context the counter\n// used to live on (which does not propagate without a provider).\nconst middlewareCountersByRootSpan = new WeakMap<object, Record<string, number>>();\n\n// Re-export for backward compatibility and external use\nexport { isInstrumentationApiUsed } from './serverGlobals';\n\n/**\n * Options for creating Sentry server instrumentation.\n */\nexport interface CreateSentryServerInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry server instrumentation for React Router's instrumentation API.\n */\nexport function createSentryServerInstrumentation(\n options: CreateSentryServerInstrumentationOptions = {},\n): ServerInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router server instrumentation created.');\n\n return {\n handler(handler: InstrumentableRequestHandler) {\n // Mark the instrumentation API active only when React Router actually invokes this\n markInstrumentationApiUsed();\n handler.instrument({\n async request(handleRequest, info) {\n const pathname = getPathFromRequest(info.request);\n const activeSpan = getActiveSpan();\n const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n if (existingRootSpan) {\n updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);\n existingRootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [URL_FULL]: filterCollectedUrl(info.request.url),\n [URL_PATH]: pathname,\n });\n\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n 'http.method': info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n } else {\n await startSpan(\n {\n name: `${info.request.method} ${pathname}`,\n forceTransaction: true,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_PATH]: pathname,\n [URL_FULL]: filterCollectedUrl(info.request.url),\n },\n },\n async span => {\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n 'http.method': info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n },\n );\n }\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n // Also mark active here, in case route registration runs (mirrors the handler callback above).\n markInstrumentationApiUsed();\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'loader',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLoader();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.loader', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'action',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callAction();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.action', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n let middlewareIndex = 0;\n if (rootSpan) {\n let counters = middlewareCountersByRootSpan.get(rootSpan);\n if (!counters) {\n counters = {};\n middlewareCountersByRootSpan.set(rootSpan, counters);\n }\n middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n }\n\n const middlewareName = getMiddlewareName(routeId, middlewareIndex);\n\n await startSpan(\n {\n name: `middleware ${middlewareName || routeId}`,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n [HTTP_ROUTE]: routePattern,\n ...(middlewareName && { 'react_router.middleware.name': middlewareName }),\n 'react_router.middleware.index': middlewareIndex,\n },\n },\n async span => {\n const result = await callMiddleware();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.middleware', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'lazy',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLazy();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\nfunction updateRootSpanWithRoute(method: string, pattern: string | undefined, urlPath: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) return;\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) return;\n\n // Skip update if URL path is invalid (failed to parse)\n if (!urlPath || urlPath === '<unknown>') {\n DEBUG_BUILD && debug.warn('Cannot update span with invalid URL path:', urlPath);\n return;\n }\n\n const hasPattern = !!pattern;\n const routeName = hasPattern ? normalizeRoutePath(pattern) || urlPath : urlPath;\n\n const transactionName = `${method} ${routeName}`;\n updateSpanName(rootSpan, transactionName);\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: hasPattern ? 'route' : 'url',\n });\n\n // Also update the scope's transaction name so errors captured during this request\n // have the correct transaction name (not the initial placeholder like \"GET *\")\n getCurrentScope().setTransactionName(transactionName);\n}\n"],"names":["DEBUG_BUILD","debug","markInstrumentationApiUsed","getPathFromRequest","getActiveSpan","getRootSpan","updateSpanName","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","URL_FULL","filterCollectedUrl","URL_PATH","SPAN_STATUS_ERROR","captureInstrumentationError","flushIfServerless","startSpan","HTTP_REQUEST_METHOD","getPattern","normalizeRoutePath","SENTRY_OP","WEB_SERVER_FUNCTION_SPAN_OP","CODE_FUNCTION_NAME","getMiddlewareName","WEB_SERVER_MIDDLEWARE_SPAN_OP","HTTP_ROUTE","getCurrentScope"],"mappings":";;;;;;;;;;AAiCA,MAAM,4BAAA,uBAAmC,OAAA,EAAwC;AAmB1E,SAAS,iCAAA,CACd,OAAA,GAAoD,EAAC,EAC9B;AACvB,EAAA,MAAM,EAAE,aAAA,GAAgB,IAAA,EAAK,GAAI,OAAA;AAEjC,EAAAA,sBAAA,IAAeC,UAAA,CAAM,IAAI,8CAA8C,CAAA;AAEvE,EAAA,OAAO;AAAA,IACL,QAAQ,OAAA,EAAuC;AAE7C,MAAAC,wCAAA,EAA2B;AAC3B,MAAA,OAAA,CAAQ,UAAA,CAAW;AAAA,QACjB,MAAM,OAAA,CAAQ,aAAA,EAAe,IAAA,EAAM;AACjC,UAAA,MAAM,QAAA,GAAWC,wBAAA,CAAmB,IAAA,CAAK,OAAO,CAAA;AAChD,UAAA,MAAM,aAAaC,kBAAA,EAAc;AACjC,UAAA,MAAM,gBAAA,GAAmB,UAAA,GAAaC,gBAAA,CAAY,UAAU,CAAA,GAAI,MAAA;AAEhE,UAAA,IAAI,gBAAA,EAAkB;AACpB,YAAAC,mBAAA,CAAe,kBAAkB,CAAA,EAAG,IAAA,CAAK,QAAQ,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA;AACrE,YAAA,gBAAA,CAAiB,aAAA,CAAc;AAAA,cAC7B,CAACC,iCAA4B,GAAG,aAAA;AAAA,cAChC,CAACC,qCAAgC,GAAG,4CAAA;AAAA,cACpC,CAACC,qCAAgC,GAAG,KAAA;AAAA,cACpC,CAACC,mBAAQ,GAAGC,uBAAA,CAAmB,IAAA,CAAK,QAAQ,GAAG,CAAA;AAAA,cAC/C,CAACC,mBAAQ,GAAG;AAAA,aACb,CAAA;AAED,YAAA,IAAI;AACF,cAAA,MAAM,MAAA,GAAS,MAAM,aAAA,EAAc;AACnC,cAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,iBAAiB,KAAA,EAAO;AAC9D,gBAAA,gBAAA,CAAiB,UAAU,EAAE,IAAA,EAAMC,sBAAA,EAAmB,OAAA,EAAS,kBAAkB,CAAA;AACjF,gBAAAC,iCAAA,CAA4B,MAAA,EAAQ,eAAe,8BAAA,EAAgC;AAAA,kBACjF,aAAA,EAAe,KAAK,OAAA,CAAQ,MAAA;AAAA,kBAC5B,CAACJ,mBAAQ,GAAG;AAAA,iBACb,CAAA;AAAA,cACH;AAAA,YACF,CAAA,SAAE;AACA,cAAA,MAAMK,sBAAA,EAAkB;AAAA,YAC1B;AAAA,UACF,CAAA,MAAO;AACL,YAAA,MAAMC,cAAA;AAAA,cACJ;AAAA,gBACE,MAAM,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,MAAM,IAAI,QAAQ,CAAA,CAAA;AAAA,gBACxC,gBAAA,EAAkB,IAAA;AAAA,gBAClB,UAAA,EAAY;AAAA,kBACV,CAACT,iCAA4B,GAAG,aAAA;AAAA,kBAChC,CAACC,qCAAgC,GAAG,4CAAA;AAAA,kBACpC,CAACC,qCAAgC,GAAG,KAAA;AAAA,kBACpC,CAACQ,8BAAmB,GAAG,IAAA,CAAK,OAAA,CAAQ,MAAA;AAAA,kBACpC,CAACL,mBAAQ,GAAG,QAAA;AAAA,kBACZ,CAACF,mBAAQ,GAAGC,uBAAA,CAAmB,IAAA,CAAK,QAAQ,GAAG;AAAA;AACjD,eACF;AAAA,cACA,OAAM,IAAA,KAAQ;AACZ,gBAAA,IAAI;AACF,kBAAA,MAAM,MAAA,GAAS,MAAM,aAAA,EAAc;AACnC,kBAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,iBAAiB,KAAA,EAAO;AAC9D,oBAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAME,sBAAA,EAAmB,OAAA,EAAS,kBAAkB,CAAA;AACrE,oBAAAC,iCAAA,CAA4B,MAAA,EAAQ,eAAe,8BAAA,EAAgC;AAAA,sBACjF,aAAA,EAAe,KAAK,OAAA,CAAQ,MAAA;AAAA,sBAC5B,CAACJ,mBAAQ,GAAG;AAAA,qBACb,CAAA;AAAA,kBACH;AAAA,gBACF,CAAA,SAAE;AACA,kBAAA,MAAMK,sBAAA,EAAkB;AAAA,gBAC1B;AAAA,cACF;AAAA,aACF;AAAA,UACF;AAAA,QACF;AAAA,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,KAAA,EAA4B;AAEhC,MAAAb,wCAAA,EAA2B;AAC3B,MAAA,MAAM,UAAU,KAAA,CAAM,EAAA;AAEtB,MAAA,KAAA,CAAM,UAAA,CAAW;AAAA,QACf,MAAM,MAAA,CAAO,UAAA,EAAY,IAAA,EAAM;AAC7B,UAAA,MAAM,OAAA,GAAUC,wBAAA,CAAmB,IAAA,CAAK,OAAO,CAAA;AAC/C,UAAA,MAAM,OAAA,GAAUe,iBAAW,IAAI,CAAA;AAC/B,UAAA,MAAM,YAAA,GAAeC,wBAAA,CAAmB,OAAO,CAAA,IAAK,OAAA;AACpD,UAAA,uBAAA,CAAwB,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAE7D,UAAA,MAAMH,cAAA;AAAA,YACJ;AAAA,cACE,IAAA,EAAM,YAAA;AAAA,cACN,UAAA,EAAY;AAAA,gBACV,CAACI,oBAAS,GAAGC,8BAAA;AAAA,gBACb,CAACC,6BAAkB,GAAG,QAAA;AAAA,gBACtB,CAACd,qCAAgC,GAAG;AAAA;AACtC,aACF;AAAA,YACA,OAAM,IAAA,KAAQ;AACZ,cAAA,MAAM,MAAA,GAAS,MAAM,UAAA,EAAW;AAChC,cAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,iBAAiB,KAAA,EAAO;AAC9D,gBAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAMK,sBAAA,EAAmB,OAAA,EAAS,kBAAkB,CAAA;AACrE,gBAAAC,iCAAA,CAA4B,MAAA,EAAQ,eAAe,qBAAA,EAAuB;AAAA,kBACxE,aAAA,EAAe,KAAK,OAAA,CAAQ,MAAA;AAAA,kBAC5B,CAACJ,mBAAQ,GAAG;AAAA,iBACb,CAAA;AAAA,cACH;AAAA,YACF;AAAA,WACF;AAAA,QACF,CAAA;AAAA,QAEA,MAAM,MAAA,CAAO,UAAA,EAAY,IAAA,EAAM;AAC7B,UAAA,MAAM,OAAA,GAAUP,wBAAA,CAAmB,IAAA,CAAK,OAAO,CAAA;AAC/C,UAAA,MAAM,OAAA,GAAUe,iBAAW,IAAI,CAAA;AAC/B,UAAA,MAAM,YAAA,GAAeC,wBAAA,CAAmB,OAAO,CAAA,IAAK,OAAA;AACpD,UAAA,uBAAA,CAAwB,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAE7D,UAAA,MAAMH,cAAA;AAAA,YACJ;AAAA,cACE,IAAA,EAAM,YAAA;AAAA,cACN,UAAA,EAAY;AAAA,gBACV,CAACI,oBAAS,GAAGC,8BAAA;AAAA,gBACb,CAACC,6BAAkB,GAAG,QAAA;AAAA,gBACtB,CAACd,qCAAgC,GAAG;AAAA;AACtC,aACF;AAAA,YACA,OAAM,IAAA,KAAQ;AACZ,cAAA,MAAM,MAAA,GAAS,MAAM,UAAA,EAAW;AAChC,cAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,iBAAiB,KAAA,EAAO;AAC9D,gBAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAMK,sBAAA,EAAmB,OAAA,EAAS,kBAAkB,CAAA;AACrE,gBAAAC,iCAAA,CAA4B,MAAA,EAAQ,eAAe,qBAAA,EAAuB;AAAA,kBACxE,aAAA,EAAe,KAAK,OAAA,CAAQ,MAAA;AAAA,kBAC5B,CAACJ,mBAAQ,GAAG;AAAA,iBACb,CAAA;AAAA,cACH;AAAA,YACF;AAAA,WACF;AAAA,QACF,CAAA;AAAA,QAEA,MAAM,UAAA,CAAW,cAAA,EAAgB,IAAA,EAAM;AACrC,UAAA,MAAM,OAAA,GAAUP,wBAAA,CAAmB,IAAA,CAAK,OAAO,CAAA;AAC/C,UAAA,MAAM,OAAA,GAAUe,iBAAW,IAAI,CAAA;AAC/B,UAAA,MAAM,YAAA,GAAeC,wBAAA,CAAmB,OAAO,CAAA,IAAK,OAAA;AAEpD,UAAA,uBAAA,CAAwB,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAE7D,UAAA,MAAM,aAAaf,kBAAA,EAAc;AACjC,UAAA,MAAM,QAAA,GAAW,UAAA,GAAaC,gBAAA,CAAY,UAAU,CAAA,GAAI,MAAA;AACxD,UAAA,IAAI,eAAA,GAAkB,CAAA;AACtB,UAAA,IAAI,QAAA,EAAU;AACZ,YAAA,IAAI,QAAA,GAAW,4BAAA,CAA6B,GAAA,CAAI,QAAQ,CAAA;AACxD,YAAA,IAAI,CAAC,QAAA,EAAU;AACb,cAAA,QAAA,GAAW,EAAC;AACZ,cAAA,4BAAA,CAA6B,GAAA,CAAI,UAAU,QAAQ,CAAA;AAAA,YACrD;AACA,YAAA,eAAA,GAAkB,QAAA,CAAS,OAAO,CAAA,IAAK,CAAA;AACvC,YAAA,QAAA,CAAS,OAAO,IAAI,eAAA,GAAkB,CAAA;AAAA,UACxC;AAEA,UAAA,MAAM,cAAA,GAAiBkB,6BAAA,CAAkB,OAAA,EAAS,eAAe,CAAA;AAEjE,UAAA,MAAMP,cAAA;AAAA,YACJ;AAAA,cACE,IAAA,EAAM,CAAA,WAAA,EAAc,cAAA,IAAkB,OAAO,CAAA,CAAA;AAAA,cAC7C,UAAA,EAAY;AAAA,gBACV,CAACI,oBAAS,GAAGI,gCAAA;AAAA,gBACb,CAACF,6BAAkB,GAAG,YAAA;AAAA,gBACtB,CAACd,qCAAgC,GAAG,gDAAA;AAAA,gBACpC,uBAAA,EAAyB,OAAA;AAAA,gBACzB,CAACiB,qBAAU,GAAG,YAAA;AAAA,gBACd,GAAI,cAAA,IAAkB,EAAE,8BAAA,EAAgC,cAAA,EAAe;AAAA,gBACvE,+BAAA,EAAiC;AAAA;AACnC,aACF;AAAA,YACA,OAAM,IAAA,KAAQ;AACZ,cAAA,MAAM,MAAA,GAAS,MAAM,cAAA,EAAe;AACpC,cAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,iBAAiB,KAAA,EAAO;AAC9D,gBAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAMZ,sBAAA,EAAmB,OAAA,EAAS,kBAAkB,CAAA;AACrE,gBAAAC,iCAAA,CAA4B,MAAA,EAAQ,eAAe,yBAAA,EAA2B;AAAA,kBAC5E,aAAA,EAAe,KAAK,OAAA,CAAQ,MAAA;AAAA,kBAC5B,CAACJ,mBAAQ,GAAG;AAAA,iBACb,CAAA;AAAA,cACH;AAAA,YACF;AAAA,WACF;AAAA,QACF,CAAA;AAAA,QAEA,MAAM,KAAK,QAAA,EAAU;AACnB,UAAA,MAAMM,cAAA;AAAA,YACJ;AAAA,cACE,IAAA,EAAM,iBAAA;AAAA,cACN,UAAA,EAAY;AAAA,gBACV,CAACI,oBAAS,GAAGC,8BAAA;AAAA,gBACb,CAACC,6BAAkB,GAAG,MAAA;AAAA,gBACtB,CAACd,qCAAgC,GAAG;AAAA;AACtC,aACF;AAAA,YACA,OAAM,IAAA,KAAQ;AACZ,cAAA,MAAM,MAAA,GAAS,MAAM,QAAA,EAAS;AAC9B,cAAA,IAAI,MAAA,CAAO,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,iBAAiB,KAAA,EAAO;AAC9D,gBAAA,IAAA,CAAK,UAAU,EAAE,IAAA,EAAMK,sBAAA,EAAmB,OAAA,EAAS,kBAAkB,CAAA;AACrE,gBAAAC,iCAAA,CAA4B,MAAA,EAAQ,aAAA,EAAe,mBAAA,EAAqB,EAAE,CAAA;AAAA,cAC5E;AAAA,YACF;AAAA,WACF;AAAA,QACF;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACF;AACF;AAEA,SAAS,uBAAA,CAAwB,MAAA,EAAgB,OAAA,EAA6B,OAAA,EAAuB;AACnG,EAAA,MAAM,aAAaV,kBAAA,EAAc;AACjC,EAAA,IAAI,CAAC,UAAA,EAAY;AACjB,EAAA,MAAM,QAAA,GAAWC,iBAAY,UAAU,CAAA;AACvC,EAAA,IAAI,CAAC,QAAA,EAAU;AAGf,EAAA,IAAI,CAAC,OAAA,IAAW,OAAA,KAAY,WAAA,EAAa;AACvC,IAAAL,sBAAA,IAAeC,UAAA,CAAM,IAAA,CAAK,2CAAA,EAA6C,OAAO,CAAA;AAC9E,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,UAAA,GAAa,CAAC,CAAC,OAAA;AACrB,EAAA,MAAM,SAAA,GAAY,UAAA,GAAakB,wBAAA,CAAmB,OAAO,KAAK,OAAA,GAAU,OAAA;AAExE,EAAA,MAAM,eAAA,GAAkB,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAC9C,EAAAb,mBAAA,CAAe,UAAU,eAAe,CAAA;AACxC,EAAA,QAAA,CAAS,aAAA,CAAc;AAAA,IACrB,CAACmB,qBAAU,GAAG,SAAA;AAAA,IACd,CAAChB,qCAAgC,GAAG,UAAA,GAAa,OAAA,GAAU;AAAA,GAC5D,CAAA;AAID,EAAAiB,oBAAA,EAAgB,CAAE,mBAAmB,eAAe,CAAA;AACtD;;;;;"}
|
|
1
|
+
{"version":3,"file":"createServerInstrumentation.js","sources":["../../../src/server/createServerInstrumentation.ts"],"sourcesContent":["import {\n SENTRY_SEGMENT_NAME_SOURCE,\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_METHOD,\n HTTP_ROUTE,\n SENTRY_OP,\n URL_FULL,\n URL_PATH,\n} from '@sentry/conventions/attributes';\nimport { FUNCTION, MIDDLEWARE } from '@sentry/conventions/op';\nimport {\n debug,\n flushIfServerless,\n getActiveSpan,\n getClient,\n getCurrentScope,\n getRootSpan,\n hasSpanStreamingEnabled,\n HTTP_SPAN_NAME_FALLBACK,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n filterCollectedUrl,\n} from '@sentry/core';\nimport type { ServerInstrumentation } from 'react-router';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { getMiddlewareName } from './serverBuild';\nimport { markInstrumentationApiUsed } from './serverGlobals';\n\n// Per-request middleware counters, keyed by the request's root span (the one transaction all of a\n// request's middlewares run under). The root span is the same instance across those middleware hooks\n// whether or not a Sentry OpenTelemetry tracer provider is set up, unlike the OTel context the counter\n// used to live on (which does not propagate without a provider).\nconst middlewareCountersByRootSpan = new WeakMap<object, Record<string, number>>();\n\n// Re-export for backward compatibility and external use\nexport { isInstrumentationApiUsed } from './serverGlobals';\n\n/**\n * Options for creating Sentry server instrumentation.\n */\nexport interface CreateSentryServerInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry server instrumentation for React Router's instrumentation API.\n */\nexport function createSentryServerInstrumentation(\n options: CreateSentryServerInstrumentationOptions = {},\n): ServerInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router server instrumentation created.');\n\n return {\n handler(handler) {\n // Mark the instrumentation API active only when React Router actually invokes this\n markInstrumentationApiUsed();\n handler.instrument({\n async request(handleRequest, info) {\n const pathname = getPathFromRequest(info.request);\n const activeSpan = getActiveSpan();\n const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n const client = getClient();\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL\n // path. `updateRootSpanWithRoute` renames the span once React Router matches a route.\n const unparameterizedName =\n client && hasSpanStreamingEnabled(client)\n ? info.request.method?.toUpperCase() || HTTP_SPAN_NAME_FALLBACK\n : `${info.request.method} ${pathname}`;\n\n if (existingRootSpan) {\n updateSpanName(existingRootSpan, unparameterizedName);\n existingRootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [URL_FULL]: filterCollectedUrl(info.request.url),\n [URL_PATH]: pathname,\n });\n\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n } else {\n await startSpan(\n {\n name: unparameterizedName,\n forceTransaction: true,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_PATH]: pathname,\n [URL_FULL]: filterCollectedUrl(info.request.url),\n },\n },\n async span => {\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n },\n );\n }\n },\n });\n },\n\n route(route) {\n // Also mark active here, in case route registration runs (mirrors the handler callback above).\n markInstrumentationApiUsed();\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: 'loader',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLoader();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.loader', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: 'action',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callAction();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.action', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n let middlewareIndex = 0;\n if (rootSpan) {\n let counters = middlewareCountersByRootSpan.get(rootSpan);\n if (!counters) {\n counters = {};\n middlewareCountersByRootSpan.set(rootSpan, counters);\n }\n middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n }\n\n const middlewareName = getMiddlewareName(routeId, middlewareIndex);\n\n await startSpan(\n {\n name: `middleware ${middlewareName || routeId}`,\n attributes: {\n [SENTRY_OP]: MIDDLEWARE,\n [CODE_FUNCTION_NAME]: 'middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n [HTTP_ROUTE]: routePattern,\n ...(middlewareName && { 'react_router.middleware.name': middlewareName }),\n 'react_router.middleware.index': middlewareIndex,\n },\n },\n async span => {\n const result = await callMiddleware();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.middleware', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: 'lazy',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLazy();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\nfunction updateRootSpanWithRoute(method: string, pattern: string | undefined, urlPath: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) return;\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) return;\n\n // Skip update if URL path is invalid (failed to parse)\n if (!urlPath || urlPath === '<unknown>') {\n DEBUG_BUILD && debug.warn('Cannot update span with invalid URL path:', urlPath);\n return;\n }\n\n const hasPattern = !!pattern;\n const routeName = hasPattern ? normalizeRoutePath(pattern) || urlPath : urlPath;\n\n const transactionName = `${method} ${routeName}`;\n\n const client = getClient();\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL path.\n const isUnparameterizedStreamedSpan = !hasPattern && !!client && hasSpanStreamingEnabled(client);\n updateSpanName(\n rootSpan,\n isUnparameterizedStreamedSpan ? method.toUpperCase() || HTTP_SPAN_NAME_FALLBACK : transactionName,\n );\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SENTRY_SEGMENT_NAME_SOURCE]: hasPattern ? 'route' : 'url',\n });\n\n // Also update the scope's transaction name so errors captured during this request\n // have the correct transaction name (not the initial placeholder like \"GET *\")\n getCurrentScope().setTransactionName(transactionName);\n}\n"],"names":["DEBUG_BUILD","debug","markInstrumentationApiUsed","getPathFromRequest","getActiveSpan","getRootSpan","getClient","hasSpanStreamingEnabled","HTTP_SPAN_NAME_FALLBACK","updateSpanName","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","URL_FULL","filterCollectedUrl","URL_PATH","SPAN_STATUS_ERROR","captureInstrumentationError","HTTP_REQUEST_METHOD","flushIfServerless","startSpan","getPattern","normalizeRoutePath","SENTRY_OP","FUNCTION","CODE_FUNCTION_NAME","getMiddlewareName","MIDDLEWARE","HTTP_ROUTE","getCurrentScope"],"mappings":"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"}
|
|
@@ -5,15 +5,16 @@ const core = require('@sentry/core');
|
|
|
5
5
|
|
|
6
6
|
function getMetaTagTransformer(body) {
|
|
7
7
|
const headClosingTag = "</head>";
|
|
8
|
+
const decoder = new TextDecoder();
|
|
8
9
|
const htmlMetaTagTransformer = new node_stream.Transform({
|
|
9
10
|
transform(chunk, _encoding, callback) {
|
|
10
|
-
const html = Buffer.isBuffer(chunk) ?
|
|
11
|
+
const html = Buffer.isBuffer(chunk) ? decoder.decode(chunk, { stream: true }) : String(chunk);
|
|
11
12
|
if (html.includes(headClosingTag)) {
|
|
12
13
|
const modifiedHtml = html.replace(headClosingTag, `${core.getTraceMetaTags()}${headClosingTag}`);
|
|
13
14
|
callback(null, modifiedHtml);
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
|
-
callback(null,
|
|
17
|
+
callback(null, html);
|
|
17
18
|
}
|
|
18
19
|
});
|
|
19
20
|
htmlMetaTagTransformer.pipe(body);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getMetaTagTransformer.js","sources":["../../../src/server/getMetaTagTransformer.ts"],"sourcesContent":["import type { PassThrough } from 'node:stream';\nimport { Transform } from 'node:stream';\nimport { getTraceMetaTags } from '@sentry/core';\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) ?
|
|
1
|
+
{"version":3,"file":"getMetaTagTransformer.js","sources":["../../../src/server/getMetaTagTransformer.ts"],"sourcesContent":["import type { PassThrough } from 'node:stream';\nimport { Transform } from 'node:stream';\nimport { getTraceMetaTags } from '@sentry/core';\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 // A single streaming decoder carries incomplete multi-byte sequences across chunk\n // boundaries. Decoding each chunk on its own (e.g. `Buffer.toString()`) would flush a\n // split character as U+FFFD, corrupting the response (see\n // https://github.com/whatwg/encoding/issues/184).\n const decoder = new TextDecoder();\n const htmlMetaTagTransformer = new Transform({\n transform(chunk, _encoding, callback) {\n const html = Buffer.isBuffer(chunk) ? decoder.decode(chunk, { stream: true }) : 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, html);\n },\n });\n htmlMetaTagTransformer.pipe(body);\n return htmlMetaTagTransformer;\n}\n"],"names":["Transform","getTraceMetaTags"],"mappings":";;;;;AAUO,SAAS,sBAAsB,IAAA,EAA8B;AAClE,EAAA,MAAM,cAAA,GAAiB,SAAA;AAKvB,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,sBAAA,GAAyB,IAAIA,qBAAA,CAAU;AAAA,IAC3C,SAAA,CAAU,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU;AACpC,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,QAAA,CAAS,KAAK,IAAI,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AAC5F,MAAA,IAAI,IAAA,CAAK,QAAA,CAAS,cAAc,CAAA,EAAG;AACjC,QAAA,MAAM,YAAA,GAAe,KAAK,OAAA,CAAQ,cAAA,EAAgB,GAAGC,qBAAA,EAAkB,CAAA,EAAG,cAAc,CAAA,CAAE,CAAA;AAC1F,QAAA,QAAA,CAAS,MAAM,YAAY,CAAA;AAC3B,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,MAAM,IAAI,CAAA;AAAA,IACrB;AAAA,GACD,CAAA;AACD,EAAA,sBAAA,CAAuB,KAAK,IAAI,CAAA;AAChC,EAAA,OAAO,sBAAA;AACT;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
3
4
|
const core = require('@sentry/core');
|
|
4
5
|
|
|
5
6
|
const LOW_QUALITY_TRANSACTIONS_FILTERS = [
|
|
@@ -7,8 +8,8 @@ const LOW_QUALITY_TRANSACTIONS_FILTERS = [
|
|
|
7
8
|
/GET \/favicon\.ico/,
|
|
8
9
|
/GET \/@id\//,
|
|
9
10
|
// The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).
|
|
10
|
-
// Filter by `
|
|
11
|
-
{ attributes: {
|
|
11
|
+
// Filter by `url.path` instead, which carries the raw request path.
|
|
12
|
+
{ attributes: { [attributes.URL_PATH]: /\/__manifest/ } }
|
|
12
13
|
];
|
|
13
14
|
const _lowQualityTransactionsFilterIntegration = (() => ({
|
|
14
15
|
name: "LowQualityTransactionsFilter",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../../src/server/integration/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\n\nconst LOW_QUALITY_TRANSACTIONS_FILTERS = [\n /GET \\/node_modules\\//,\n /GET \\/favicon\\.ico/,\n /GET \\/@id\\//,\n // The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).\n // Filter by `
|
|
1
|
+
{"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../../src/server/integration/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import { URL_PATH } from '@sentry/conventions/attributes';\nimport type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\n\nconst LOW_QUALITY_TRANSACTIONS_FILTERS = [\n /GET \\/node_modules\\//,\n /GET \\/favicon\\.ico/,\n /GET \\/@id\\//,\n // The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).\n // Filter by `url.path` instead, which carries the raw request path.\n { attributes: { [URL_PATH]: /\\/__manifest/ } },\n];\n\nconst _lowQualityTransactionsFilterIntegration = (() => ({\n name: 'LowQualityTransactionsFilter' as const,\n beforeSetup(client) {\n const opts = client.getOptions();\n opts.ignoreSpans = [...(opts.ignoreSpans || []), ...LOW_QUALITY_TRANSACTIONS_FILTERS];\n },\n})) satisfies IntegrationFn;\n\n/**\n * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/, __manifest.\n * Adds entries to `ignoreSpans` so the filter applies in both static and streaming trace lifecycles.\n */\nexport const lowQualityTransactionsFilterIntegration = defineIntegration(_lowQualityTransactionsFilterIntegration);\n"],"names":["URL_PATH","defineIntegration"],"mappings":";;;;;AAIA,MAAM,gCAAA,GAAmC;AAAA,EACvC,sBAAA;AAAA,EACA,oBAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA,EAGA,EAAE,UAAA,EAAY,EAAE,CAACA,mBAAQ,GAAG,gBAAe;AAC7C,CAAA;AAEA,MAAM,4CAA4C,OAAO;AAAA,EACvD,IAAA,EAAM,8BAAA;AAAA,EACN,YAAY,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAA,GAAO,OAAO,UAAA,EAAW;AAC/B,IAAA,IAAA,CAAK,WAAA,GAAc,CAAC,GAAI,IAAA,CAAK,eAAe,EAAC,EAAI,GAAG,gCAAgC,CAAA;AAAA,EACtF;AACF,CAAA,CAAA,CAAA;AAMO,MAAM,uCAAA,GAA0CC,uBAAkB,wCAAwC;;;;"}
|
|
@@ -17,12 +17,12 @@ function wrapSentryHandleRequest(originalHandle) {
|
|
|
17
17
|
if (serverGlobals.isInstrumentationApiUsed()) {
|
|
18
18
|
rootSpan.setAttributes({
|
|
19
19
|
[attributes.HTTP_ROUTE]: routeName,
|
|
20
|
-
[
|
|
20
|
+
[attributes.SENTRY_SEGMENT_NAME_SOURCE]: "route"
|
|
21
21
|
});
|
|
22
22
|
} else {
|
|
23
23
|
rootSpan.setAttributes({
|
|
24
24
|
[attributes.HTTP_ROUTE]: routeName,
|
|
25
|
-
[
|
|
25
|
+
[attributes.SENTRY_SEGMENT_NAME_SOURCE]: "route",
|
|
26
26
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.request_handler"
|
|
27
27
|
});
|
|
28
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { HTTP_ROUTE } from '@sentry/conventions/attributes';\nimport {\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n
|
|
1
|
+
{"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { SENTRY_SEGMENT_NAME_SOURCE, HTTP_ROUTE } from '@sentry/conventions/attributes';\nimport {\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n updateSpanName,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext, RouterContextProvider } from 'react-router';\nimport { isInstrumentationApiUsed } from './serverGlobals';\n\ntype OriginalHandleRequestWithoutMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\ntype OriginalHandleRequestWithMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: RouterContextProvider,\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(\n originalHandle: OriginalHandleRequestWithoutMiddleware,\n): OriginalHandleRequestWithoutMiddleware;\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(\n originalHandle: OriginalHandleRequestWithMiddleware,\n): OriginalHandleRequestWithMiddleware;\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(\n originalHandle: OriginalHandleRequestWithoutMiddleware | OriginalHandleRequestWithMiddleware,\n): OriginalHandleRequestWithoutMiddleware | OriginalHandleRequestWithMiddleware {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext | RouterContextProvider,\n ) {\n const parameterizedPath =\n routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n if (parameterizedPath && rootSpan) {\n // Normalize route name - avoid \"//\" for root routes\n const routeName = parameterizedPath.startsWith('/') ? parameterizedPath : `/${parameterizedPath}`;\n\n const transactionName = `${request.method} ${routeName}`;\n\n updateSpanName(rootSpan, transactionName);\n getCurrentScope().setTransactionName(transactionName);\n\n // Set route attributes - acts as fallback for lazy-only routes when using instrumentation API\n // Don't override origin when instrumentation API is used (preserve instrumentation_api origin)\n if (isInstrumentationApiUsed()) {\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SENTRY_SEGMENT_NAME_SOURCE]: 'route',\n });\n } else {\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SENTRY_SEGMENT_NAME_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.request_handler',\n });\n }\n }\n\n try {\n // Type guard to call the correct overload based on loadContext type\n if (isRouterContextProvider(loadContext)) {\n // loadContext is RouterContextProvider\n return await (originalHandle as OriginalHandleRequestWithMiddleware)(\n request,\n responseStatusCode,\n responseHeaders,\n routerContext,\n loadContext,\n );\n } else {\n // loadContext is AppLoadContext\n return await (originalHandle as OriginalHandleRequestWithoutMiddleware)(\n request,\n responseStatusCode,\n responseHeaders,\n routerContext,\n loadContext,\n );\n }\n } finally {\n await flushIfServerless();\n }\n\n /**\n * Helper type guard to determine if the context is a RouterContextProvider.\n *\n * @param ctx - The context to check\n * @returns True if the context is a RouterContextProvider\n */\n function isRouterContextProvider(ctx: AppLoadContext | RouterContextProvider): ctx is RouterContextProvider {\n return typeof (ctx as RouterContextProvider)?.get === 'function';\n }\n };\n}\n"],"names":["getActiveSpan","getRootSpan","updateSpanName","getCurrentScope","isInstrumentationApiUsed","HTTP_ROUTE","SENTRY_SEGMENT_NAME_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","flushIfServerless"],"mappings":";;;;;;AAoDO,SAAS,wBACd,cAAA,EAC8E;AAC9E,EAAA,OAAO,eAAe,+BAAA,CACpB,OAAA,EACA,kBAAA,EACA,eAAA,EACA,eACA,WAAA,EACA;AACA,IAAA,MAAM,iBAAA,GACJ,aAAA,EAAe,oBAAA,EAAsB,OAAA,GAAU,aAAA,CAAc,qBAAqB,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,EAAG,KAAA,CAAM,IAAA;AAE/G,IAAA,MAAM,aAAaA,kBAAA,EAAc;AACjC,IAAA,MAAM,QAAA,GAAW,UAAA,GAAaC,gBAAA,CAAY,UAAU,CAAA,GAAI,MAAA;AAExD,IAAA,IAAI,qBAAqB,QAAA,EAAU;AAEjC,MAAA,MAAM,YAAY,iBAAA,CAAkB,UAAA,CAAW,GAAG,CAAA,GAAI,iBAAA,GAAoB,IAAI,iBAAiB,CAAA,CAAA;AAE/F,MAAA,MAAM,eAAA,GAAkB,CAAA,EAAG,OAAA,CAAQ,MAAM,IAAI,SAAS,CAAA,CAAA;AAEtD,MAAAC,mBAAA,CAAe,UAAU,eAAe,CAAA;AACxC,MAAAC,oBAAA,EAAgB,CAAE,mBAAmB,eAAe,CAAA;AAIpD,MAAA,IAAIC,wCAAyB,EAAG;AAC9B,QAAA,QAAA,CAAS,aAAA,CAAc;AAAA,UACrB,CAACC,qBAAU,GAAG,SAAA;AAAA,UACd,CAACC,qCAA0B,GAAG;AAAA,SAC/B,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,aAAA,CAAc;AAAA,UACrB,CAACD,qBAAU,GAAG,SAAA;AAAA,UACd,CAACC,qCAA0B,GAAG,OAAA;AAAA,UAC9B,CAACC,qCAAgC,GAAG;AAAA,SACrC,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,IAAI;AAEF,MAAA,IAAI,uBAAA,CAAwB,WAAW,CAAA,EAAG;AAExC,QAAA,OAAO,MAAO,cAAA;AAAA,UACZ,OAAA;AAAA,UACA,kBAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,OAAO,MAAO,cAAA;AAAA,UACZ,OAAA;AAAA,UACA,kBAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,IACF,CAAA,SAAE;AACA,MAAA,MAAMC,sBAAA,EAAkB;AAAA,IAC1B;AAQA,IAAA,SAAS,wBAAwB,GAAA,EAA2E;AAC1G,MAAA,OAAO,OAAQ,KAA+B,GAAA,KAAQ,UAAA;AAAA,IACxD;AAAA,EACF,CAAA;AACF;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const promises = require('node:fs/promises');
|
|
4
|
-
const
|
|
4
|
+
const sentry = require('sentry');
|
|
5
5
|
const glob = require('glob');
|
|
6
6
|
|
|
7
7
|
function getSentryConfig(viteConfig) {
|
|
@@ -10,43 +10,38 @@ function getSentryConfig(viteConfig) {
|
|
|
10
10
|
}
|
|
11
11
|
return viteConfig.sentryConfig;
|
|
12
12
|
}
|
|
13
|
-
function resolveSourceMapsDisable(sentryConfig) {
|
|
14
|
-
return sentryConfig.sourcemaps?.disable ?? sentryConfig.unstable_sentryVitePluginOptions?.sourcemaps?.disable;
|
|
15
|
-
}
|
|
16
13
|
const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
|
|
17
14
|
const sentryConfig = getSentryConfig(viteConfig);
|
|
18
|
-
const unstableSentryVitePluginOptions = sentryConfig.unstable_sentryVitePluginOptions;
|
|
19
15
|
const {
|
|
20
16
|
authToken,
|
|
17
|
+
headers,
|
|
21
18
|
org,
|
|
22
19
|
project,
|
|
23
20
|
release,
|
|
21
|
+
sentryUrl,
|
|
24
22
|
sourcemaps = { disable: false },
|
|
25
23
|
debug = false
|
|
26
24
|
} = {
|
|
27
|
-
...unstableSentryVitePluginOptions,
|
|
28
25
|
...sentryConfig,
|
|
29
26
|
sourcemaps: {
|
|
30
|
-
...unstableSentryVitePluginOptions?.sourcemaps,
|
|
31
27
|
...sentryConfig.sourcemaps,
|
|
32
|
-
disable:
|
|
28
|
+
disable: sentryConfig.sourcemaps?.disable
|
|
33
29
|
},
|
|
34
30
|
release: {
|
|
35
|
-
...unstableSentryVitePluginOptions?.release,
|
|
36
31
|
...sentryConfig.release
|
|
37
|
-
}
|
|
38
|
-
project: unstableSentryVitePluginOptions?.project ? Array.isArray(unstableSentryVitePluginOptions?.project) ? unstableSentryVitePluginOptions?.project[0] : unstableSentryVitePluginOptions?.project : sentryConfig.project
|
|
32
|
+
}
|
|
39
33
|
};
|
|
40
|
-
const
|
|
41
|
-
authToken,
|
|
34
|
+
const sentryOptions = {
|
|
35
|
+
token: authToken,
|
|
42
36
|
org,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
37
|
+
url: sentryUrl,
|
|
38
|
+
project,
|
|
39
|
+
headers
|
|
40
|
+
};
|
|
41
|
+
const sentry$1 = sentry.createSentrySDK(sentryOptions);
|
|
47
42
|
if (release?.name) {
|
|
48
43
|
try {
|
|
49
|
-
await
|
|
44
|
+
await sentry$1.release.create({ orgVersion: release.name });
|
|
50
45
|
} catch (error) {
|
|
51
46
|
console.error("[Sentry] Could not create release", error);
|
|
52
47
|
}
|
|
@@ -55,22 +50,15 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
|
|
|
55
50
|
const uploadDisabled = sourceMapsFullyDisabled || sourcemaps?.disable === "disable-upload";
|
|
56
51
|
if (!sourceMapsFullyDisabled && viteConfig.build.sourcemap !== false) {
|
|
57
52
|
try {
|
|
58
|
-
await
|
|
59
|
-
["sourcemaps", "inject", reactRouterConfig.buildDirectory],
|
|
60
|
-
debug ? "rejectOnError" : false
|
|
61
|
-
);
|
|
53
|
+
await sentry$1.sourcemap.inject({ directory: reactRouterConfig.buildDirectory });
|
|
62
54
|
} catch (error) {
|
|
63
55
|
console.error("[Sentry] Could not inject debug ids", error);
|
|
64
56
|
}
|
|
65
57
|
if (!uploadDisabled) {
|
|
66
58
|
try {
|
|
67
|
-
await
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
paths: [reactRouterConfig.buildDirectory]
|
|
71
|
-
}
|
|
72
|
-
],
|
|
73
|
-
live: "rejectOnError"
|
|
59
|
+
await sentry$1.sourcemap.upload({
|
|
60
|
+
directory: reactRouterConfig.buildDirectory,
|
|
61
|
+
release: release?.name || "undefined"
|
|
74
62
|
});
|
|
75
63
|
} catch (error) {
|
|
76
64
|
console.error("[Sentry] Could not upload sourcemaps", error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleOnBuildEnd.js","sources":["../../../../src/vite/buildEnd/handleOnBuildEnd.ts"],"sourcesContent":["import { rm } from 'node:fs/promises';\nimport type { Config } from '@react-router/dev/config';\nimport
|
|
1
|
+
{"version":3,"file":"handleOnBuildEnd.js","sources":["../../../../src/vite/buildEnd/handleOnBuildEnd.ts"],"sourcesContent":["import { rm } from 'node:fs/promises';\nimport type { Config } from '@react-router/dev/config';\nimport { createSentrySDK } from 'sentry';\nimport type { SentryVitePluginOptions } from '@sentry/bundler-plugins/vite';\nimport { glob } from 'glob';\nimport type { SentryReactRouterBuildOptions } from '../types';\n\ntype BuildEndHook = NonNullable<Config['buildEnd']>;\ntype SentryOptions = NonNullable<Parameters<typeof createSentrySDK>[0]>;\n\n/**\n * The CLI accepts `headers` since 0.44.0, but its bundled type declarations do not list the\n * option yet.\n * TODO: Drop once `SentryOptions` in the `sentry` package declares `headers`: https://github.com/getsentry/cli/pull/1500\n */\ntype SentryOptionsWithHeaders = SentryOptions & { headers?: Record<string, string> };\n\nfunction getSentryConfig(viteConfig: unknown): SentryReactRouterBuildOptions {\n if (!viteConfig || typeof viteConfig !== 'object' || !('sentryConfig' in viteConfig)) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] sentryConfig not found - it needs to be passed to vite.config.ts');\n }\n\n return (viteConfig as { sentryConfig: SentryReactRouterBuildOptions }).sentryConfig;\n}\n\n/**\n * A build end hook that handles Sentry release creation and source map uploads.\n * It creates a new Sentry release if configured, uploads source maps to Sentry,\n * and optionally deletes the source map files after upload.\n */\nexport const sentryOnBuildEnd: BuildEndHook = async ({ reactRouterConfig, viteConfig }) => {\n const sentryConfig = getSentryConfig(viteConfig);\n\n const {\n authToken,\n headers,\n org,\n project,\n release,\n sentryUrl,\n sourcemaps = { disable: false },\n debug = false,\n }: Omit<SentryReactRouterBuildOptions, 'sourcemaps'> &\n // Pick 'sourcemaps' from Vite plugin options as the types allow more (e.g. Promise values for `deleteFilesAfterUpload`)\n Pick<SentryVitePluginOptions, 'sourcemaps'> = {\n ...sentryConfig,\n sourcemaps: {\n ...sentryConfig.sourcemaps,\n disable: sentryConfig.sourcemaps?.disable,\n },\n release: {\n ...sentryConfig.release,\n },\n };\n\n const sentryOptions: SentryOptionsWithHeaders = {\n token: authToken,\n org,\n url: sentryUrl,\n project,\n headers,\n };\n\n const sentry = createSentrySDK(sentryOptions);\n\n // check if release should be created\n if (release?.name) {\n try {\n await sentry.release.create({ orgVersion: release.name });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not create release', error);\n }\n }\n\n // `disable: 'disable-upload'` still injects debug IDs, so that source maps can be\n // uploaded manually at a later point - only `true` turns source maps off entirely.\n const sourceMapsFullyDisabled = sourcemaps?.disable === true;\n const uploadDisabled = sourceMapsFullyDisabled || sourcemaps?.disable === 'disable-upload';\n\n if (!sourceMapsFullyDisabled && viteConfig.build.sourcemap !== false) {\n // inject debugIds\n try {\n await sentry.sourcemap.inject({ directory: reactRouterConfig.buildDirectory });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not inject debug ids', error);\n }\n\n if (!uploadDisabled) {\n // upload sourcemaps\n try {\n await sentry.sourcemap.upload({\n directory: reactRouterConfig.buildDirectory,\n release: release?.name || 'undefined',\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not upload sourcemaps', error);\n }\n }\n }\n\n // Only clean up source maps that were actually uploaded. Deleting them after skipping\n // the upload would leave the user with neither, breaking a manual upload.\n if (uploadDisabled) {\n return;\n }\n\n // delete sourcemaps after upload\n let updatedFilesToDeleteAfterUpload = await sourcemaps?.filesToDeleteAfterUpload;\n\n // set a default value no option was set\n if (typeof updatedFilesToDeleteAfterUpload === 'undefined') {\n updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];\n debug &&\n // eslint-disable-next-line no-console\n console.info(\n `[Sentry] Automatically setting \\`sourcemaps.filesToDeleteAfterUpload: ${JSON.stringify(\n updatedFilesToDeleteAfterUpload,\n )}\\` to delete generated source maps after they were uploaded to Sentry.`,\n );\n }\n if (updatedFilesToDeleteAfterUpload) {\n try {\n const filePathsToDelete = await glob(updatedFilesToDeleteAfterUpload, {\n absolute: true,\n nodir: true,\n });\n if (debug) {\n filePathsToDelete.forEach(filePathToDelete => {\n // eslint-disable-next-line no-console\n console.info(`Deleting asset after upload: ${filePathToDelete}`);\n });\n }\n await Promise.all(\n filePathsToDelete.map(filePathToDelete =>\n rm(filePathToDelete, { force: true }).catch((e: unknown) => {\n // This is allowed to fail - we just don't do anything\n debug &&\n // eslint-disable-next-line no-console\n console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);\n }),\n ),\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error deleting files after sourcemap upload:', error);\n }\n }\n};\n"],"names":["sentry","createSentrySDK","glob","rm"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const plugin = require('./plugin.js');
|
|
4
|
+
const handleOnBuildEnd = require('./buildEnd/handleOnBuildEnd.js');
|
|
5
|
+
const makeConfigInjectorPlugin = require('./makeConfigInjectorPlugin.js');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.sentryReactRouter = plugin.sentryReactRouter;
|
|
10
|
+
exports.sentryOnBuildEnd = handleOnBuildEnd.sentryOnBuildEnd;
|
|
11
|
+
exports.makeConfigInjectorPlugin = makeConfigInjectorPlugin.makeConfigInjectorPlugin;
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|