@sentry/react-router 10.53.1 → 10.54.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.
- package/build/cjs/client/createClientInstrumentation.js +104 -175
- package/build/cjs/client/createClientInstrumentation.js.map +1 -1
- package/build/cjs/client/hydratedRouter.js +27 -74
- package/build/cjs/client/hydratedRouter.js.map +1 -1
- package/build/cjs/client/sdk.js +5 -16
- package/build/cjs/client/sdk.js.map +1 -1
- package/build/cjs/client/sentryOnError.js +4 -27
- package/build/cjs/client/sentryOnError.js.map +1 -1
- package/build/cjs/client/tracingIntegration.js +4 -18
- package/build/cjs/client/tracingIntegration.js.map +1 -1
- package/build/cjs/client/utils.js +5 -17
- package/build/cjs/client/utils.js.map +1 -1
- package/build/cjs/cloudflare/index.js +2 -15
- package/build/cjs/cloudflare/index.js.map +1 -1
- package/build/cjs/common/debug-build.js +0 -5
- package/build/cjs/common/debug-build.js.map +1 -1
- package/build/cjs/common/utils.js +8 -33
- package/build/cjs/common/utils.js.map +1 -1
- package/build/cjs/server/createSentryHandleError.js +4 -13
- package/build/cjs/server/createSentryHandleError.js.map +1 -1
- package/build/cjs/server/createSentryHandleRequest.js +14 -49
- package/build/cjs/server/createSentryHandleRequest.js.map +1 -1
- package/build/cjs/server/createServerInstrumentation.js +76 -114
- package/build/cjs/server/createServerInstrumentation.js.map +1 -1
- package/build/cjs/server/getMetaTagTransformer.js +2 -8
- package/build/cjs/server/getMetaTagTransformer.js.map +1 -1
- package/build/cjs/server/instrumentation/reactRouter.js +21 -47
- package/build/cjs/server/instrumentation/reactRouter.js.map +1 -1
- package/build/cjs/server/instrumentation/util.js +5 -41
- package/build/cjs/server/instrumentation/util.js.map +1 -1
- package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js +5 -12
- package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
- package/build/cjs/server/integration/reactRouterServer.js +10 -42
- package/build/cjs/server/integration/reactRouterServer.js.map +1 -1
- package/build/cjs/server/sdk.js +6 -20
- package/build/cjs/server/sdk.js.map +1 -1
- package/build/cjs/server/serverBuild.js +6 -31
- package/build/cjs/server/serverBuild.js.map +1 -1
- package/build/cjs/server/serverGlobals.js +6 -26
- package/build/cjs/server/serverGlobals.js.map +1 -1
- package/build/cjs/server/wrapSentryHandleRequest.js +13 -53
- package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
- package/build/cjs/server/wrapServerAction.js +12 -44
- package/build/cjs/server/wrapServerAction.js.map +1 -1
- package/build/cjs/server/wrapServerLoader.js +12 -44
- package/build/cjs/server/wrapServerLoader.js.map +1 -1
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +38 -72
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/cjs/vite/makeConfigInjectorPlugin.js +4 -12
- package/build/cjs/vite/makeConfigInjectorPlugin.js.map +1 -1
- package/build/cjs/vite/makeCustomSentryVitePlugins.js +10 -15
- package/build/cjs/vite/makeCustomSentryVitePlugins.js.map +1 -1
- package/build/cjs/vite/makeEnableSourceMapsPlugin.js +19 -51
- package/build/cjs/vite/makeEnableSourceMapsPlugin.js.map +1 -1
- package/build/cjs/vite/makeServerBuildCapturePlugin.js +4 -15
- package/build/cjs/vite/makeServerBuildCapturePlugin.js.map +1 -1
- package/build/cjs/vite/plugin.js +3 -16
- package/build/cjs/vite/plugin.js.map +1 -1
- package/build/esm/client/createClientInstrumentation.js +104 -175
- package/build/esm/client/createClientInstrumentation.js.map +1 -1
- package/build/esm/client/hydratedRouter.js +27 -74
- package/build/esm/client/hydratedRouter.js.map +1 -1
- package/build/esm/client/sdk.js +5 -16
- package/build/esm/client/sdk.js.map +1 -1
- package/build/esm/client/sentryOnError.js +4 -27
- package/build/esm/client/sentryOnError.js.map +1 -1
- package/build/esm/client/tracingIntegration.js +4 -18
- package/build/esm/client/tracingIntegration.js.map +1 -1
- package/build/esm/client/utils.js +5 -17
- package/build/esm/client/utils.js.map +1 -1
- package/build/esm/cloudflare/index.js +2 -15
- package/build/esm/cloudflare/index.js.map +1 -1
- package/build/esm/common/debug-build.js +0 -5
- package/build/esm/common/debug-build.js.map +1 -1
- package/build/esm/common/utils.js +8 -33
- package/build/esm/common/utils.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server/createSentryHandleError.js +4 -13
- package/build/esm/server/createSentryHandleError.js.map +1 -1
- package/build/esm/server/createSentryHandleRequest.js +14 -49
- package/build/esm/server/createSentryHandleRequest.js.map +1 -1
- package/build/esm/server/createServerInstrumentation.js +76 -114
- package/build/esm/server/createServerInstrumentation.js.map +1 -1
- package/build/esm/server/getMetaTagTransformer.js +2 -8
- package/build/esm/server/getMetaTagTransformer.js.map +1 -1
- package/build/esm/server/instrumentation/reactRouter.js +21 -47
- package/build/esm/server/instrumentation/reactRouter.js.map +1 -1
- package/build/esm/server/instrumentation/util.js +5 -41
- package/build/esm/server/instrumentation/util.js.map +1 -1
- package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js +5 -12
- package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
- package/build/esm/server/integration/reactRouterServer.js +10 -42
- package/build/esm/server/integration/reactRouterServer.js.map +1 -1
- package/build/esm/server/sdk.js +6 -20
- package/build/esm/server/sdk.js.map +1 -1
- package/build/esm/server/serverBuild.js +6 -31
- package/build/esm/server/serverBuild.js.map +1 -1
- package/build/esm/server/serverGlobals.js +6 -26
- package/build/esm/server/serverGlobals.js.map +1 -1
- package/build/esm/server/wrapSentryHandleRequest.js +13 -53
- package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
- package/build/esm/server/wrapServerAction.js +12 -44
- package/build/esm/server/wrapServerAction.js.map +1 -1
- package/build/esm/server/wrapServerLoader.js +12 -44
- package/build/esm/server/wrapServerLoader.js.map +1 -1
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js +38 -72
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/esm/vite/makeConfigInjectorPlugin.js +4 -12
- package/build/esm/vite/makeConfigInjectorPlugin.js.map +1 -1
- package/build/esm/vite/makeCustomSentryVitePlugins.js +10 -15
- package/build/esm/vite/makeCustomSentryVitePlugins.js.map +1 -1
- package/build/esm/vite/makeEnableSourceMapsPlugin.js +19 -51
- package/build/esm/vite/makeEnableSourceMapsPlugin.js.map +1 -1
- package/build/esm/vite/makeServerBuildCapturePlugin.js +4 -15
- package/build/esm/vite/makeServerBuildCapturePlugin.js.map +1 -1
- package/build/esm/vite/plugin.js +3 -16
- package/build/esm/vite/plugin.js.map +1 -1
- package/build/types/client/hydratedRouter.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -6,317 +6,246 @@ const debugBuild = require('../common/debug-build.js');
|
|
|
6
6
|
const utils = require('../common/utils.js');
|
|
7
7
|
const utils$1 = require('./utils.js');
|
|
8
8
|
|
|
9
|
-
const WINDOW = core.GLOBAL_OBJ
|
|
10
|
-
|
|
11
|
-
// Tracks active numeric navigation span to prevent duplicate spans when popstate fires
|
|
9
|
+
const WINDOW = core.GLOBAL_OBJ;
|
|
12
10
|
let currentNumericNavigationSpan;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
const SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = '__sentryReactRouterNavigateHookInvoked';
|
|
20
|
-
const SENTRY_POPSTATE_LISTENER_ADDED_FLAG = '__sentryReactRouterPopstateListenerAdded';
|
|
21
|
-
|
|
22
|
-
const GLOBAL_WITH_FLAGS = core.GLOBAL_OBJ ;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Options for creating Sentry client instrumentation.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Creates a Sentry client instrumentation for React Router's instrumentation API.
|
|
30
|
-
* @experimental
|
|
31
|
-
*/
|
|
32
|
-
function createSentryClientInstrumentation(
|
|
33
|
-
options = {},
|
|
34
|
-
) {
|
|
11
|
+
const middlewareCountersMap = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
const SENTRY_CLIENT_INSTRUMENTATION_FLAG = "__sentryReactRouterClientInstrumentationUsed";
|
|
13
|
+
const SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = "__sentryReactRouterNavigateHookInvoked";
|
|
14
|
+
const SENTRY_POPSTATE_LISTENER_ADDED_FLAG = "__sentryReactRouterPopstateListenerAdded";
|
|
15
|
+
const GLOBAL_WITH_FLAGS = core.GLOBAL_OBJ;
|
|
16
|
+
function createSentryClientInstrumentation(options = {}) {
|
|
35
17
|
const { captureErrors = true } = options;
|
|
36
|
-
|
|
37
|
-
debugBuild.DEBUG_BUILD && core.debug.log('React Router client instrumentation API created.');
|
|
38
|
-
|
|
18
|
+
debugBuild.DEBUG_BUILD && core.debug.log("React Router client instrumentation API created.");
|
|
39
19
|
return {
|
|
40
20
|
router(router) {
|
|
41
|
-
// Set the flag when React Router actually invokes our instrumentation.
|
|
42
|
-
// This ensures the flag is only set in Library Mode (where hooks run),
|
|
43
|
-
// not in Framework Mode (where hooks are never called).
|
|
44
|
-
// See: https://github.com/remix-run/react-router/discussions/13749
|
|
45
21
|
GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG] = true;
|
|
46
|
-
debugBuild.DEBUG_BUILD && core.debug.log(
|
|
47
|
-
|
|
48
|
-
// Add popstate listener for browser back/forward navigation (persists for session, one listener only)
|
|
22
|
+
debugBuild.DEBUG_BUILD && core.debug.log("React Router client instrumentation API router hook registered.");
|
|
49
23
|
if (!GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] && WINDOW.addEventListener) {
|
|
50
24
|
GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] = true;
|
|
51
|
-
|
|
52
|
-
WINDOW.addEventListener('popstate', () => {
|
|
25
|
+
WINDOW.addEventListener("popstate", () => {
|
|
53
26
|
const client = core.getClient();
|
|
54
27
|
if (!client) {
|
|
55
|
-
currentNumericNavigationSpan =
|
|
28
|
+
currentNumericNavigationSpan = void 0;
|
|
56
29
|
return;
|
|
57
30
|
}
|
|
58
|
-
|
|
59
|
-
const pathname = WINDOW.location?.pathname || '/';
|
|
60
|
-
|
|
61
|
-
// If there's an active numeric navigation span, update it instead of creating a duplicate
|
|
31
|
+
const pathname = WINDOW.location?.pathname || "/";
|
|
62
32
|
if (currentNumericNavigationSpan) {
|
|
63
33
|
if (currentNumericNavigationSpan.isRecording()) {
|
|
64
34
|
currentNumericNavigationSpan.updateName(pathname);
|
|
65
35
|
}
|
|
66
|
-
currentNumericNavigationSpan =
|
|
36
|
+
currentNumericNavigationSpan = void 0;
|
|
67
37
|
return;
|
|
68
38
|
}
|
|
69
|
-
|
|
70
|
-
// Only create a new span for actual browser back/forward button clicks
|
|
71
39
|
browser.startBrowserTracingNavigationSpan(client, {
|
|
72
40
|
name: pathname,
|
|
73
41
|
attributes: {
|
|
74
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]:
|
|
75
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
76
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
77
|
-
|
|
78
|
-
}
|
|
42
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
|
43
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
44
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react_router.instrumentation_api",
|
|
45
|
+
"navigation.type": "browser.popstate"
|
|
46
|
+
}
|
|
79
47
|
});
|
|
80
48
|
});
|
|
81
|
-
|
|
82
|
-
debugBuild.DEBUG_BUILD && core.debug.log('React Router popstate listener registered for browser back/forward navigation.');
|
|
49
|
+
debugBuild.DEBUG_BUILD && core.debug.log("React Router popstate listener registered for browser back/forward navigation.");
|
|
83
50
|
}
|
|
84
|
-
|
|
85
51
|
router.instrument({
|
|
86
52
|
async navigate(callNavigate, info) {
|
|
87
|
-
// navigate(0) triggers a page reload - skip span creation, but still capture errors
|
|
88
|
-
// (navigation can be rejected before reload, e.g., by a navigation guard)
|
|
89
53
|
if (info.to === 0) {
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
92
|
-
utils.captureInstrumentationError(
|
|
93
|
-
|
|
54
|
+
const result2 = await callNavigate();
|
|
55
|
+
if (result2.status === "error" && result2.error instanceof Error) {
|
|
56
|
+
utils.captureInstrumentationError(result2, captureErrors, "react_router.navigate", {
|
|
57
|
+
"http.url": info.currentUrl
|
|
94
58
|
});
|
|
95
59
|
}
|
|
96
60
|
return;
|
|
97
61
|
}
|
|
98
|
-
|
|
99
62
|
GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG] = true;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (client) {
|
|
107
|
-
const navigationType = info.to < 0 ? 'router.back' : 'router.forward';
|
|
63
|
+
if (typeof info.to === "number") {
|
|
64
|
+
const client2 = core.getClient();
|
|
65
|
+
let navigationSpan2;
|
|
66
|
+
if (client2) {
|
|
67
|
+
const navigationType = info.to < 0 ? "router.back" : "router.forward";
|
|
108
68
|
const currentPathname = WINDOW.location?.pathname || info.currentUrl;
|
|
109
|
-
|
|
110
|
-
navigationSpan = browser.startBrowserTracingNavigationSpan(client, {
|
|
69
|
+
navigationSpan2 = browser.startBrowserTracingNavigationSpan(client2, {
|
|
111
70
|
name: currentPathname,
|
|
112
71
|
attributes: {
|
|
113
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]:
|
|
114
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
115
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
116
|
-
|
|
117
|
-
}
|
|
72
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
|
73
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
74
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react_router.instrumentation_api",
|
|
75
|
+
"navigation.type": navigationType
|
|
76
|
+
}
|
|
118
77
|
});
|
|
119
|
-
|
|
120
|
-
// Store ref so popstate listener can update it instead of creating a duplicate
|
|
121
|
-
currentNumericNavigationSpan = navigationSpan;
|
|
78
|
+
currentNumericNavigationSpan = navigationSpan2;
|
|
122
79
|
}
|
|
123
|
-
|
|
124
80
|
try {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
navigationSpan.updateName(WINDOW.location.pathname);
|
|
81
|
+
const result2 = await callNavigate();
|
|
82
|
+
if (navigationSpan2 && WINDOW.location) {
|
|
83
|
+
navigationSpan2.updateName(WINDOW.location.pathname);
|
|
129
84
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
navigationSpan.setStatus({ code: core.SPAN_STATUS_ERROR, message: 'internal_error' });
|
|
85
|
+
if (result2.status === "error" && result2.error instanceof Error) {
|
|
86
|
+
if (navigationSpan2) {
|
|
87
|
+
navigationSpan2.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
134
88
|
}
|
|
135
|
-
utils.captureInstrumentationError(
|
|
136
|
-
|
|
89
|
+
utils.captureInstrumentationError(result2, captureErrors, "react_router.navigate", {
|
|
90
|
+
"http.url": WINDOW.location?.pathname || info.currentUrl
|
|
137
91
|
});
|
|
138
92
|
}
|
|
139
93
|
} finally {
|
|
140
|
-
currentNumericNavigationSpan =
|
|
94
|
+
currentNumericNavigationSpan = void 0;
|
|
141
95
|
}
|
|
142
96
|
return;
|
|
143
97
|
}
|
|
144
|
-
|
|
145
|
-
// Handle string/object navigations (e.g., navigate('/about') or navigate({ pathname: '/about' }))
|
|
146
98
|
const client = core.getClient();
|
|
147
99
|
const toPath = utils$1.resolveNavigateArg(info.to);
|
|
148
100
|
let navigationSpan;
|
|
149
|
-
|
|
150
101
|
if (client) {
|
|
151
102
|
navigationSpan = browser.startBrowserTracingNavigationSpan(client, {
|
|
152
103
|
name: toPath,
|
|
153
104
|
attributes: {
|
|
154
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]:
|
|
155
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
156
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
157
|
-
|
|
158
|
-
}
|
|
105
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
|
106
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
107
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react_router.instrumentation_api",
|
|
108
|
+
"navigation.type": "router.navigate"
|
|
109
|
+
}
|
|
159
110
|
});
|
|
160
111
|
}
|
|
161
|
-
|
|
162
112
|
const result = await callNavigate();
|
|
163
|
-
if (result.status ===
|
|
113
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
164
114
|
if (navigationSpan) {
|
|
165
|
-
navigationSpan.setStatus({ code: core.SPAN_STATUS_ERROR, message:
|
|
115
|
+
navigationSpan.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
166
116
|
}
|
|
167
|
-
utils.captureInstrumentationError(result, captureErrors,
|
|
168
|
-
|
|
117
|
+
utils.captureInstrumentationError(result, captureErrors, "react_router.navigate", {
|
|
118
|
+
"http.url": toPath
|
|
169
119
|
});
|
|
170
120
|
}
|
|
171
121
|
return;
|
|
172
122
|
},
|
|
173
|
-
|
|
174
123
|
async fetch(callFetch, info) {
|
|
175
124
|
await core.startSpan(
|
|
176
125
|
{
|
|
177
126
|
name: `Fetcher ${info.fetcherKey}`,
|
|
178
127
|
attributes: {
|
|
179
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
180
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
181
|
-
}
|
|
128
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.fetcher",
|
|
129
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
130
|
+
}
|
|
182
131
|
},
|
|
183
|
-
async span => {
|
|
132
|
+
async (span) => {
|
|
184
133
|
const result = await callFetch();
|
|
185
|
-
if (result.status ===
|
|
186
|
-
span.setStatus({ code: core.SPAN_STATUS_ERROR, message:
|
|
187
|
-
utils.captureInstrumentationError(result, captureErrors,
|
|
188
|
-
|
|
134
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
135
|
+
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
136
|
+
utils.captureInstrumentationError(result, captureErrors, "react_router.fetcher", {
|
|
137
|
+
"http.url": info.href
|
|
189
138
|
});
|
|
190
139
|
}
|
|
191
|
-
}
|
|
140
|
+
}
|
|
192
141
|
);
|
|
193
|
-
}
|
|
142
|
+
}
|
|
194
143
|
});
|
|
195
144
|
},
|
|
196
|
-
|
|
197
145
|
route(route) {
|
|
198
146
|
const routeId = route.id;
|
|
199
|
-
|
|
200
147
|
route.instrument({
|
|
201
148
|
async loader(callLoader, info) {
|
|
202
149
|
const urlPath = utils.getPathFromRequest(info.request);
|
|
203
150
|
const routePattern = utils.normalizeRoutePath(utils.getPattern(info)) || urlPath;
|
|
204
|
-
|
|
205
151
|
await core.startSpan(
|
|
206
152
|
{
|
|
207
153
|
name: routePattern,
|
|
208
154
|
attributes: {
|
|
209
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
210
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
211
|
-
}
|
|
155
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_loader",
|
|
156
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
157
|
+
}
|
|
212
158
|
},
|
|
213
|
-
async span => {
|
|
159
|
+
async (span) => {
|
|
214
160
|
const result = await callLoader();
|
|
215
|
-
if (result.status ===
|
|
216
|
-
span.setStatus({ code: core.SPAN_STATUS_ERROR, message:
|
|
217
|
-
utils.captureInstrumentationError(result, captureErrors,
|
|
218
|
-
|
|
161
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
162
|
+
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
163
|
+
utils.captureInstrumentationError(result, captureErrors, "react_router.client_loader", {
|
|
164
|
+
"http.url": urlPath
|
|
219
165
|
});
|
|
220
166
|
}
|
|
221
|
-
}
|
|
167
|
+
}
|
|
222
168
|
);
|
|
223
169
|
},
|
|
224
|
-
|
|
225
170
|
async action(callAction, info) {
|
|
226
171
|
const urlPath = utils.getPathFromRequest(info.request);
|
|
227
172
|
const routePattern = utils.normalizeRoutePath(utils.getPattern(info)) || urlPath;
|
|
228
|
-
|
|
229
173
|
await core.startSpan(
|
|
230
174
|
{
|
|
231
175
|
name: routePattern,
|
|
232
176
|
attributes: {
|
|
233
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
234
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
235
|
-
}
|
|
177
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_action",
|
|
178
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
179
|
+
}
|
|
236
180
|
},
|
|
237
|
-
async span => {
|
|
181
|
+
async (span) => {
|
|
238
182
|
const result = await callAction();
|
|
239
|
-
if (result.status ===
|
|
240
|
-
span.setStatus({ code: core.SPAN_STATUS_ERROR, message:
|
|
241
|
-
utils.captureInstrumentationError(result, captureErrors,
|
|
242
|
-
|
|
183
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
184
|
+
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
185
|
+
utils.captureInstrumentationError(result, captureErrors, "react_router.client_action", {
|
|
186
|
+
"http.url": urlPath
|
|
243
187
|
});
|
|
244
188
|
}
|
|
245
|
-
}
|
|
189
|
+
}
|
|
246
190
|
);
|
|
247
191
|
},
|
|
248
|
-
|
|
249
192
|
async middleware(callMiddleware, info) {
|
|
250
193
|
const urlPath = utils.getPathFromRequest(info.request);
|
|
251
194
|
const routePattern = utils.normalizeRoutePath(utils.getPattern(info)) || urlPath;
|
|
252
|
-
|
|
253
195
|
let counters = middlewareCountersMap.get(info.request);
|
|
254
196
|
if (!counters) {
|
|
255
197
|
counters = {};
|
|
256
198
|
middlewareCountersMap.set(info.request, counters);
|
|
257
199
|
}
|
|
258
|
-
|
|
259
200
|
const middlewareIndex = counters[routeId] ?? 0;
|
|
260
201
|
counters[routeId] = middlewareIndex + 1;
|
|
261
|
-
|
|
262
202
|
await core.startSpan(
|
|
263
203
|
{
|
|
264
204
|
name: `middleware ${routeId}`,
|
|
265
205
|
attributes: {
|
|
266
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
267
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
206
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_middleware",
|
|
207
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api",
|
|
208
|
+
"react_router.route.id": routeId,
|
|
209
|
+
"http.route": routePattern,
|
|
210
|
+
"react_router.middleware.index": middlewareIndex
|
|
211
|
+
}
|
|
272
212
|
},
|
|
273
|
-
async span => {
|
|
213
|
+
async (span) => {
|
|
274
214
|
const result = await callMiddleware();
|
|
275
|
-
if (result.status ===
|
|
276
|
-
span.setStatus({ code: core.SPAN_STATUS_ERROR, message:
|
|
277
|
-
utils.captureInstrumentationError(result, captureErrors,
|
|
278
|
-
|
|
215
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
216
|
+
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
217
|
+
utils.captureInstrumentationError(result, captureErrors, "react_router.client_middleware", {
|
|
218
|
+
"http.url": urlPath
|
|
279
219
|
});
|
|
280
220
|
}
|
|
281
|
-
}
|
|
221
|
+
}
|
|
282
222
|
);
|
|
283
223
|
},
|
|
284
|
-
|
|
285
224
|
async lazy(callLazy) {
|
|
286
225
|
await core.startSpan(
|
|
287
226
|
{
|
|
288
|
-
name:
|
|
227
|
+
name: "Lazy Route Load",
|
|
289
228
|
attributes: {
|
|
290
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
291
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
292
|
-
}
|
|
229
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_lazy",
|
|
230
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
231
|
+
}
|
|
293
232
|
},
|
|
294
|
-
async span => {
|
|
233
|
+
async (span) => {
|
|
295
234
|
const result = await callLazy();
|
|
296
|
-
if (result.status ===
|
|
297
|
-
span.setStatus({ code: core.SPAN_STATUS_ERROR, message:
|
|
298
|
-
utils.captureInstrumentationError(result, captureErrors,
|
|
235
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
236
|
+
span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
|
|
237
|
+
utils.captureInstrumentationError(result, captureErrors, "react_router.client_lazy", {});
|
|
299
238
|
}
|
|
300
|
-
}
|
|
239
|
+
}
|
|
301
240
|
);
|
|
302
|
-
}
|
|
241
|
+
}
|
|
303
242
|
});
|
|
304
|
-
}
|
|
243
|
+
}
|
|
305
244
|
};
|
|
306
245
|
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Check if React Router's instrumentation API is being used on the client.
|
|
310
|
-
* @experimental
|
|
311
|
-
*/
|
|
312
246
|
function isClientInstrumentationApiUsed() {
|
|
313
247
|
return !!GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG];
|
|
314
248
|
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Check if React Router's instrumentation API's navigate hook was invoked.
|
|
318
|
-
* @experimental
|
|
319
|
-
*/
|
|
320
249
|
function isNavigateHookInvoked() {
|
|
321
250
|
return !!GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG];
|
|
322
251
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createClientInstrumentation.js","sources":["../../../src/client/createClientInstrumentation.ts"],"sourcesContent":["import { startBrowserTracingNavigationSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport {\n debug,\n getClient,\n GLOBAL_OBJ,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SPAN_STATUS_ERROR,\n startSpan,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { ClientInstrumentation, InstrumentableRoute, InstrumentableRouter } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { resolveNavigateArg } from './utils';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\n// Tracks active numeric navigation span to prevent duplicate spans when popstate fires\nlet currentNumericNavigationSpan: Span | undefined;\n\n// Per-request middleware counters, keyed by Request\nconst middlewareCountersMap = new WeakMap<object, Record<string, number>>();\n\nconst SENTRY_CLIENT_INSTRUMENTATION_FLAG = '__sentryReactRouterClientInstrumentationUsed';\n// Intentionally never reset - once set, instrumentation API handles all navigations for the session.\nconst SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = '__sentryReactRouterNavigateHookInvoked';\nconst SENTRY_POPSTATE_LISTENER_ADDED_FLAG = '__sentryReactRouterPopstateListenerAdded';\n\ntype GlobalObjWithFlags = typeof GLOBAL_OBJ & {\n [SENTRY_CLIENT_INSTRUMENTATION_FLAG]?: boolean;\n [SENTRY_NAVIGATE_HOOK_INVOKED_FLAG]?: boolean;\n [SENTRY_POPSTATE_LISTENER_ADDED_FLAG]?: boolean;\n};\n\nconst GLOBAL_WITH_FLAGS = GLOBAL_OBJ as GlobalObjWithFlags;\n\n/**\n * Options for creating Sentry client instrumentation.\n */\nexport interface CreateSentryClientInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * Set to `false` to avoid duplicates if using custom error handlers.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry client instrumentation for React Router's instrumentation API.\n * @experimental\n */\nexport function createSentryClientInstrumentation(\n options: CreateSentryClientInstrumentationOptions = {},\n): ClientInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router client instrumentation API created.');\n\n return {\n router(router: InstrumentableRouter) {\n // Set the flag when React Router actually invokes our instrumentation.\n // This ensures the flag is only set in Library Mode (where hooks run),\n // not in Framework Mode (where hooks are never called).\n // See: https://github.com/remix-run/react-router/discussions/13749\n GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG] = true;\n DEBUG_BUILD && debug.log('React Router client instrumentation API router hook registered.');\n\n // Add popstate listener for browser back/forward navigation (persists for session, one listener only)\n if (!GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] && WINDOW.addEventListener) {\n GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] = true;\n\n WINDOW.addEventListener('popstate', () => {\n const client = getClient();\n if (!client) {\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n const pathname = WINDOW.location?.pathname || '/';\n\n // If there's an active numeric navigation span, update it instead of creating a duplicate\n if (currentNumericNavigationSpan) {\n if (currentNumericNavigationSpan.isRecording()) {\n currentNumericNavigationSpan.updateName(pathname);\n }\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n // Only create a new span for actual browser back/forward button clicks\n startBrowserTracingNavigationSpan(client, {\n name: pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'browser.popstate',\n },\n });\n });\n\n DEBUG_BUILD && debug.log('React Router popstate listener registered for browser back/forward navigation.');\n }\n\n router.instrument({\n async navigate(callNavigate, info) {\n // navigate(0) triggers a page reload - skip span creation, but still capture errors\n // (navigation can be rejected before reload, e.g., by a navigation guard)\n if (info.to === 0) {\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': info.currentUrl,\n });\n }\n return;\n }\n\n GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG] = true;\n\n // Handle numeric navigations (navigate(-1), navigate(1), etc.)\n if (typeof info.to === 'number') {\n const client = getClient();\n let navigationSpan;\n\n if (client) {\n const navigationType = info.to < 0 ? 'router.back' : 'router.forward';\n const currentPathname = WINDOW.location?.pathname || info.currentUrl;\n\n navigationSpan = startBrowserTracingNavigationSpan(client, {\n name: currentPathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': navigationType,\n },\n });\n\n // Store ref so popstate listener can update it instead of creating a duplicate\n currentNumericNavigationSpan = navigationSpan;\n }\n\n try {\n const result = await callNavigate();\n\n if (navigationSpan && WINDOW.location) {\n navigationSpan.updateName(WINDOW.location.pathname);\n }\n\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': WINDOW.location?.pathname || info.currentUrl,\n });\n }\n } finally {\n currentNumericNavigationSpan = undefined;\n }\n return;\n }\n\n // Handle string/object navigations (e.g., navigate('/about') or navigate({ pathname: '/about' }))\n const client = getClient();\n const toPath = resolveNavigateArg(info.to);\n let navigationSpan;\n\n if (client) {\n navigationSpan = startBrowserTracingNavigationSpan(client, {\n name: toPath,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'router.navigate',\n },\n });\n }\n\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': toPath,\n });\n }\n return;\n },\n\n async fetch(callFetch, info) {\n await startSpan(\n {\n name: `Fetcher ${info.fetcherKey}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.fetcher',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callFetch();\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.fetcher', {\n 'http.url': info.href,\n });\n }\n },\n );\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_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.client_loader', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_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.client_action', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n let counters = middlewareCountersMap.get(info.request);\n if (!counters) {\n counters = {};\n middlewareCountersMap.set(info.request, counters);\n }\n\n const middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n\n await startSpan(\n {\n name: `middleware ${routeId}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n 'http.route': routePattern,\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.client_middleware', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_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.client_lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\n/**\n * Check if React Router's instrumentation API is being used on the client.\n * @experimental\n */\nexport function isClientInstrumentationApiUsed(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG];\n}\n\n/**\n * Check if React Router's instrumentation API's navigate hook was invoked.\n * @experimental\n */\nexport function isNavigateHookInvoked(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG];\n}\n"],"names":["GLOBAL_OBJ","DEBUG_BUILD","debug","getClient","startBrowserTracingNavigationSpan","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","captureInstrumentationError","SPAN_STATUS_ERROR","resolveNavigateArg","startSpan","getPathFromRequest","normalizeRoutePath","getPattern"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createClientInstrumentation.js","sources":["../../../src/client/createClientInstrumentation.ts"],"sourcesContent":["import { startBrowserTracingNavigationSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport {\n debug,\n getClient,\n GLOBAL_OBJ,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SPAN_STATUS_ERROR,\n startSpan,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { ClientInstrumentation, InstrumentableRoute, InstrumentableRouter } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { resolveNavigateArg } from './utils';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\n// Tracks active numeric navigation span to prevent duplicate spans when popstate fires\nlet currentNumericNavigationSpan: Span | undefined;\n\n// Per-request middleware counters, keyed by Request\nconst middlewareCountersMap = new WeakMap<object, Record<string, number>>();\n\nconst SENTRY_CLIENT_INSTRUMENTATION_FLAG = '__sentryReactRouterClientInstrumentationUsed';\n// Intentionally never reset - once set, instrumentation API handles all navigations for the session.\nconst SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = '__sentryReactRouterNavigateHookInvoked';\nconst SENTRY_POPSTATE_LISTENER_ADDED_FLAG = '__sentryReactRouterPopstateListenerAdded';\n\ntype GlobalObjWithFlags = typeof GLOBAL_OBJ & {\n [SENTRY_CLIENT_INSTRUMENTATION_FLAG]?: boolean;\n [SENTRY_NAVIGATE_HOOK_INVOKED_FLAG]?: boolean;\n [SENTRY_POPSTATE_LISTENER_ADDED_FLAG]?: boolean;\n};\n\nconst GLOBAL_WITH_FLAGS = GLOBAL_OBJ as GlobalObjWithFlags;\n\n/**\n * Options for creating Sentry client instrumentation.\n */\nexport interface CreateSentryClientInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * Set to `false` to avoid duplicates if using custom error handlers.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry client instrumentation for React Router's instrumentation API.\n * @experimental\n */\nexport function createSentryClientInstrumentation(\n options: CreateSentryClientInstrumentationOptions = {},\n): ClientInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router client instrumentation API created.');\n\n return {\n router(router: InstrumentableRouter) {\n // Set the flag when React Router actually invokes our instrumentation.\n // This ensures the flag is only set in Library Mode (where hooks run),\n // not in Framework Mode (where hooks are never called).\n // See: https://github.com/remix-run/react-router/discussions/13749\n GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG] = true;\n DEBUG_BUILD && debug.log('React Router client instrumentation API router hook registered.');\n\n // Add popstate listener for browser back/forward navigation (persists for session, one listener only)\n if (!GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] && WINDOW.addEventListener) {\n GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] = true;\n\n WINDOW.addEventListener('popstate', () => {\n const client = getClient();\n if (!client) {\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n const pathname = WINDOW.location?.pathname || '/';\n\n // If there's an active numeric navigation span, update it instead of creating a duplicate\n if (currentNumericNavigationSpan) {\n if (currentNumericNavigationSpan.isRecording()) {\n currentNumericNavigationSpan.updateName(pathname);\n }\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n // Only create a new span for actual browser back/forward button clicks\n startBrowserTracingNavigationSpan(client, {\n name: pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'browser.popstate',\n },\n });\n });\n\n DEBUG_BUILD && debug.log('React Router popstate listener registered for browser back/forward navigation.');\n }\n\n router.instrument({\n async navigate(callNavigate, info) {\n // navigate(0) triggers a page reload - skip span creation, but still capture errors\n // (navigation can be rejected before reload, e.g., by a navigation guard)\n if (info.to === 0) {\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': info.currentUrl,\n });\n }\n return;\n }\n\n GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG] = true;\n\n // Handle numeric navigations (navigate(-1), navigate(1), etc.)\n if (typeof info.to === 'number') {\n const client = getClient();\n let navigationSpan;\n\n if (client) {\n const navigationType = info.to < 0 ? 'router.back' : 'router.forward';\n const currentPathname = WINDOW.location?.pathname || info.currentUrl;\n\n navigationSpan = startBrowserTracingNavigationSpan(client, {\n name: currentPathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': navigationType,\n },\n });\n\n // Store ref so popstate listener can update it instead of creating a duplicate\n currentNumericNavigationSpan = navigationSpan;\n }\n\n try {\n const result = await callNavigate();\n\n if (navigationSpan && WINDOW.location) {\n navigationSpan.updateName(WINDOW.location.pathname);\n }\n\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': WINDOW.location?.pathname || info.currentUrl,\n });\n }\n } finally {\n currentNumericNavigationSpan = undefined;\n }\n return;\n }\n\n // Handle string/object navigations (e.g., navigate('/about') or navigate({ pathname: '/about' }))\n const client = getClient();\n const toPath = resolveNavigateArg(info.to);\n let navigationSpan;\n\n if (client) {\n navigationSpan = startBrowserTracingNavigationSpan(client, {\n name: toPath,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'router.navigate',\n },\n });\n }\n\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': toPath,\n });\n }\n return;\n },\n\n async fetch(callFetch, info) {\n await startSpan(\n {\n name: `Fetcher ${info.fetcherKey}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.fetcher',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callFetch();\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.fetcher', {\n 'http.url': info.href,\n });\n }\n },\n );\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_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.client_loader', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_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.client_action', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n let counters = middlewareCountersMap.get(info.request);\n if (!counters) {\n counters = {};\n middlewareCountersMap.set(info.request, counters);\n }\n\n const middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n\n await startSpan(\n {\n name: `middleware ${routeId}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n 'http.route': routePattern,\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.client_middleware', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_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.client_lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\n/**\n * Check if React Router's instrumentation API is being used on the client.\n * @experimental\n */\nexport function isClientInstrumentationApiUsed(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG];\n}\n\n/**\n * Check if React Router's instrumentation API's navigate hook was invoked.\n * @experimental\n */\nexport function isNavigateHookInvoked(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG];\n}\n"],"names":["GLOBAL_OBJ","DEBUG_BUILD","debug","getClient","startBrowserTracingNavigationSpan","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","result","captureInstrumentationError","client","navigationSpan","SPAN_STATUS_ERROR","resolveNavigateArg","startSpan","getPathFromRequest","normalizeRoutePath","getPattern"],"mappings":"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"}
|