@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
|
@@ -4,317 +4,246 @@ import { DEBUG_BUILD } from '../common/debug-build.js';
|
|
|
4
4
|
import { captureInstrumentationError, getPathFromRequest, normalizeRoutePath, getPattern } from '../common/utils.js';
|
|
5
5
|
import { resolveNavigateArg } from './utils.js';
|
|
6
6
|
|
|
7
|
-
const WINDOW = GLOBAL_OBJ
|
|
8
|
-
|
|
9
|
-
// Tracks active numeric navigation span to prevent duplicate spans when popstate fires
|
|
7
|
+
const WINDOW = GLOBAL_OBJ;
|
|
10
8
|
let currentNumericNavigationSpan;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = '__sentryReactRouterNavigateHookInvoked';
|
|
18
|
-
const SENTRY_POPSTATE_LISTENER_ADDED_FLAG = '__sentryReactRouterPopstateListenerAdded';
|
|
19
|
-
|
|
20
|
-
const GLOBAL_WITH_FLAGS = GLOBAL_OBJ ;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Options for creating Sentry client instrumentation.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Creates a Sentry client instrumentation for React Router's instrumentation API.
|
|
28
|
-
* @experimental
|
|
29
|
-
*/
|
|
30
|
-
function createSentryClientInstrumentation(
|
|
31
|
-
options = {},
|
|
32
|
-
) {
|
|
9
|
+
const middlewareCountersMap = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
const SENTRY_CLIENT_INSTRUMENTATION_FLAG = "__sentryReactRouterClientInstrumentationUsed";
|
|
11
|
+
const SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = "__sentryReactRouterNavigateHookInvoked";
|
|
12
|
+
const SENTRY_POPSTATE_LISTENER_ADDED_FLAG = "__sentryReactRouterPopstateListenerAdded";
|
|
13
|
+
const GLOBAL_WITH_FLAGS = GLOBAL_OBJ;
|
|
14
|
+
function createSentryClientInstrumentation(options = {}) {
|
|
33
15
|
const { captureErrors = true } = options;
|
|
34
|
-
|
|
35
|
-
DEBUG_BUILD && debug.log('React Router client instrumentation API created.');
|
|
36
|
-
|
|
16
|
+
DEBUG_BUILD && debug.log("React Router client instrumentation API created.");
|
|
37
17
|
return {
|
|
38
18
|
router(router) {
|
|
39
|
-
// Set the flag when React Router actually invokes our instrumentation.
|
|
40
|
-
// This ensures the flag is only set in Library Mode (where hooks run),
|
|
41
|
-
// not in Framework Mode (where hooks are never called).
|
|
42
|
-
// See: https://github.com/remix-run/react-router/discussions/13749
|
|
43
19
|
GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG] = true;
|
|
44
|
-
DEBUG_BUILD && debug.log(
|
|
45
|
-
|
|
46
|
-
// Add popstate listener for browser back/forward navigation (persists for session, one listener only)
|
|
20
|
+
DEBUG_BUILD && debug.log("React Router client instrumentation API router hook registered.");
|
|
47
21
|
if (!GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] && WINDOW.addEventListener) {
|
|
48
22
|
GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] = true;
|
|
49
|
-
|
|
50
|
-
WINDOW.addEventListener('popstate', () => {
|
|
23
|
+
WINDOW.addEventListener("popstate", () => {
|
|
51
24
|
const client = getClient();
|
|
52
25
|
if (!client) {
|
|
53
|
-
currentNumericNavigationSpan =
|
|
26
|
+
currentNumericNavigationSpan = void 0;
|
|
54
27
|
return;
|
|
55
28
|
}
|
|
56
|
-
|
|
57
|
-
const pathname = WINDOW.location?.pathname || '/';
|
|
58
|
-
|
|
59
|
-
// If there's an active numeric navigation span, update it instead of creating a duplicate
|
|
29
|
+
const pathname = WINDOW.location?.pathname || "/";
|
|
60
30
|
if (currentNumericNavigationSpan) {
|
|
61
31
|
if (currentNumericNavigationSpan.isRecording()) {
|
|
62
32
|
currentNumericNavigationSpan.updateName(pathname);
|
|
63
33
|
}
|
|
64
|
-
currentNumericNavigationSpan =
|
|
34
|
+
currentNumericNavigationSpan = void 0;
|
|
65
35
|
return;
|
|
66
36
|
}
|
|
67
|
-
|
|
68
|
-
// Only create a new span for actual browser back/forward button clicks
|
|
69
37
|
startBrowserTracingNavigationSpan(client, {
|
|
70
38
|
name: pathname,
|
|
71
39
|
attributes: {
|
|
72
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]:
|
|
73
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
74
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
75
|
-
|
|
76
|
-
}
|
|
40
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
|
41
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
42
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react_router.instrumentation_api",
|
|
43
|
+
"navigation.type": "browser.popstate"
|
|
44
|
+
}
|
|
77
45
|
});
|
|
78
46
|
});
|
|
79
|
-
|
|
80
|
-
DEBUG_BUILD && debug.log('React Router popstate listener registered for browser back/forward navigation.');
|
|
47
|
+
DEBUG_BUILD && debug.log("React Router popstate listener registered for browser back/forward navigation.");
|
|
81
48
|
}
|
|
82
|
-
|
|
83
49
|
router.instrument({
|
|
84
50
|
async navigate(callNavigate, info) {
|
|
85
|
-
// navigate(0) triggers a page reload - skip span creation, but still capture errors
|
|
86
|
-
// (navigation can be rejected before reload, e.g., by a navigation guard)
|
|
87
51
|
if (info.to === 0) {
|
|
88
|
-
const
|
|
89
|
-
if (
|
|
90
|
-
captureInstrumentationError(
|
|
91
|
-
|
|
52
|
+
const result2 = await callNavigate();
|
|
53
|
+
if (result2.status === "error" && result2.error instanceof Error) {
|
|
54
|
+
captureInstrumentationError(result2, captureErrors, "react_router.navigate", {
|
|
55
|
+
"http.url": info.currentUrl
|
|
92
56
|
});
|
|
93
57
|
}
|
|
94
58
|
return;
|
|
95
59
|
}
|
|
96
|
-
|
|
97
60
|
GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG] = true;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (client) {
|
|
105
|
-
const navigationType = info.to < 0 ? 'router.back' : 'router.forward';
|
|
61
|
+
if (typeof info.to === "number") {
|
|
62
|
+
const client2 = getClient();
|
|
63
|
+
let navigationSpan2;
|
|
64
|
+
if (client2) {
|
|
65
|
+
const navigationType = info.to < 0 ? "router.back" : "router.forward";
|
|
106
66
|
const currentPathname = WINDOW.location?.pathname || info.currentUrl;
|
|
107
|
-
|
|
108
|
-
navigationSpan = startBrowserTracingNavigationSpan(client, {
|
|
67
|
+
navigationSpan2 = startBrowserTracingNavigationSpan(client2, {
|
|
109
68
|
name: currentPathname,
|
|
110
69
|
attributes: {
|
|
111
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]:
|
|
112
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
113
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
114
|
-
|
|
115
|
-
}
|
|
70
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
|
71
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
72
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react_router.instrumentation_api",
|
|
73
|
+
"navigation.type": navigationType
|
|
74
|
+
}
|
|
116
75
|
});
|
|
117
|
-
|
|
118
|
-
// Store ref so popstate listener can update it instead of creating a duplicate
|
|
119
|
-
currentNumericNavigationSpan = navigationSpan;
|
|
76
|
+
currentNumericNavigationSpan = navigationSpan2;
|
|
120
77
|
}
|
|
121
|
-
|
|
122
78
|
try {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
navigationSpan.updateName(WINDOW.location.pathname);
|
|
79
|
+
const result2 = await callNavigate();
|
|
80
|
+
if (navigationSpan2 && WINDOW.location) {
|
|
81
|
+
navigationSpan2.updateName(WINDOW.location.pathname);
|
|
127
82
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
|
|
83
|
+
if (result2.status === "error" && result2.error instanceof Error) {
|
|
84
|
+
if (navigationSpan2) {
|
|
85
|
+
navigationSpan2.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
132
86
|
}
|
|
133
|
-
captureInstrumentationError(
|
|
134
|
-
|
|
87
|
+
captureInstrumentationError(result2, captureErrors, "react_router.navigate", {
|
|
88
|
+
"http.url": WINDOW.location?.pathname || info.currentUrl
|
|
135
89
|
});
|
|
136
90
|
}
|
|
137
91
|
} finally {
|
|
138
|
-
currentNumericNavigationSpan =
|
|
92
|
+
currentNumericNavigationSpan = void 0;
|
|
139
93
|
}
|
|
140
94
|
return;
|
|
141
95
|
}
|
|
142
|
-
|
|
143
|
-
// Handle string/object navigations (e.g., navigate('/about') or navigate({ pathname: '/about' }))
|
|
144
96
|
const client = getClient();
|
|
145
97
|
const toPath = resolveNavigateArg(info.to);
|
|
146
98
|
let navigationSpan;
|
|
147
|
-
|
|
148
99
|
if (client) {
|
|
149
100
|
navigationSpan = startBrowserTracingNavigationSpan(client, {
|
|
150
101
|
name: toPath,
|
|
151
102
|
attributes: {
|
|
152
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]:
|
|
153
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
154
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
155
|
-
|
|
156
|
-
}
|
|
103
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
|
104
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
105
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react_router.instrumentation_api",
|
|
106
|
+
"navigation.type": "router.navigate"
|
|
107
|
+
}
|
|
157
108
|
});
|
|
158
109
|
}
|
|
159
|
-
|
|
160
110
|
const result = await callNavigate();
|
|
161
|
-
if (result.status ===
|
|
111
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
162
112
|
if (navigationSpan) {
|
|
163
|
-
navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message:
|
|
113
|
+
navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
164
114
|
}
|
|
165
|
-
captureInstrumentationError(result, captureErrors,
|
|
166
|
-
|
|
115
|
+
captureInstrumentationError(result, captureErrors, "react_router.navigate", {
|
|
116
|
+
"http.url": toPath
|
|
167
117
|
});
|
|
168
118
|
}
|
|
169
119
|
return;
|
|
170
120
|
},
|
|
171
|
-
|
|
172
121
|
async fetch(callFetch, info) {
|
|
173
122
|
await startSpan(
|
|
174
123
|
{
|
|
175
124
|
name: `Fetcher ${info.fetcherKey}`,
|
|
176
125
|
attributes: {
|
|
177
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
178
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
179
|
-
}
|
|
126
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.fetcher",
|
|
127
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
128
|
+
}
|
|
180
129
|
},
|
|
181
|
-
async span => {
|
|
130
|
+
async (span) => {
|
|
182
131
|
const result = await callFetch();
|
|
183
|
-
if (result.status ===
|
|
184
|
-
span.setStatus({ code: SPAN_STATUS_ERROR, message:
|
|
185
|
-
captureInstrumentationError(result, captureErrors,
|
|
186
|
-
|
|
132
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
133
|
+
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
134
|
+
captureInstrumentationError(result, captureErrors, "react_router.fetcher", {
|
|
135
|
+
"http.url": info.href
|
|
187
136
|
});
|
|
188
137
|
}
|
|
189
|
-
}
|
|
138
|
+
}
|
|
190
139
|
);
|
|
191
|
-
}
|
|
140
|
+
}
|
|
192
141
|
});
|
|
193
142
|
},
|
|
194
|
-
|
|
195
143
|
route(route) {
|
|
196
144
|
const routeId = route.id;
|
|
197
|
-
|
|
198
145
|
route.instrument({
|
|
199
146
|
async loader(callLoader, info) {
|
|
200
147
|
const urlPath = getPathFromRequest(info.request);
|
|
201
148
|
const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;
|
|
202
|
-
|
|
203
149
|
await startSpan(
|
|
204
150
|
{
|
|
205
151
|
name: routePattern,
|
|
206
152
|
attributes: {
|
|
207
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
208
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
209
|
-
}
|
|
153
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_loader",
|
|
154
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
155
|
+
}
|
|
210
156
|
},
|
|
211
|
-
async span => {
|
|
157
|
+
async (span) => {
|
|
212
158
|
const result = await callLoader();
|
|
213
|
-
if (result.status ===
|
|
214
|
-
span.setStatus({ code: SPAN_STATUS_ERROR, message:
|
|
215
|
-
captureInstrumentationError(result, captureErrors,
|
|
216
|
-
|
|
159
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
160
|
+
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
161
|
+
captureInstrumentationError(result, captureErrors, "react_router.client_loader", {
|
|
162
|
+
"http.url": urlPath
|
|
217
163
|
});
|
|
218
164
|
}
|
|
219
|
-
}
|
|
165
|
+
}
|
|
220
166
|
);
|
|
221
167
|
},
|
|
222
|
-
|
|
223
168
|
async action(callAction, info) {
|
|
224
169
|
const urlPath = getPathFromRequest(info.request);
|
|
225
170
|
const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;
|
|
226
|
-
|
|
227
171
|
await startSpan(
|
|
228
172
|
{
|
|
229
173
|
name: routePattern,
|
|
230
174
|
attributes: {
|
|
231
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
232
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
233
|
-
}
|
|
175
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_action",
|
|
176
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
177
|
+
}
|
|
234
178
|
},
|
|
235
|
-
async span => {
|
|
179
|
+
async (span) => {
|
|
236
180
|
const result = await callAction();
|
|
237
|
-
if (result.status ===
|
|
238
|
-
span.setStatus({ code: SPAN_STATUS_ERROR, message:
|
|
239
|
-
captureInstrumentationError(result, captureErrors,
|
|
240
|
-
|
|
181
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
182
|
+
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
183
|
+
captureInstrumentationError(result, captureErrors, "react_router.client_action", {
|
|
184
|
+
"http.url": urlPath
|
|
241
185
|
});
|
|
242
186
|
}
|
|
243
|
-
}
|
|
187
|
+
}
|
|
244
188
|
);
|
|
245
189
|
},
|
|
246
|
-
|
|
247
190
|
async middleware(callMiddleware, info) {
|
|
248
191
|
const urlPath = getPathFromRequest(info.request);
|
|
249
192
|
const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;
|
|
250
|
-
|
|
251
193
|
let counters = middlewareCountersMap.get(info.request);
|
|
252
194
|
if (!counters) {
|
|
253
195
|
counters = {};
|
|
254
196
|
middlewareCountersMap.set(info.request, counters);
|
|
255
197
|
}
|
|
256
|
-
|
|
257
198
|
const middlewareIndex = counters[routeId] ?? 0;
|
|
258
199
|
counters[routeId] = middlewareIndex + 1;
|
|
259
|
-
|
|
260
200
|
await startSpan(
|
|
261
201
|
{
|
|
262
202
|
name: `middleware ${routeId}`,
|
|
263
203
|
attributes: {
|
|
264
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
265
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
204
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_middleware",
|
|
205
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api",
|
|
206
|
+
"react_router.route.id": routeId,
|
|
207
|
+
"http.route": routePattern,
|
|
208
|
+
"react_router.middleware.index": middlewareIndex
|
|
209
|
+
}
|
|
270
210
|
},
|
|
271
|
-
async span => {
|
|
211
|
+
async (span) => {
|
|
272
212
|
const result = await callMiddleware();
|
|
273
|
-
if (result.status ===
|
|
274
|
-
span.setStatus({ code: SPAN_STATUS_ERROR, message:
|
|
275
|
-
captureInstrumentationError(result, captureErrors,
|
|
276
|
-
|
|
213
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
214
|
+
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
215
|
+
captureInstrumentationError(result, captureErrors, "react_router.client_middleware", {
|
|
216
|
+
"http.url": urlPath
|
|
277
217
|
});
|
|
278
218
|
}
|
|
279
|
-
}
|
|
219
|
+
}
|
|
280
220
|
);
|
|
281
221
|
},
|
|
282
|
-
|
|
283
222
|
async lazy(callLazy) {
|
|
284
223
|
await startSpan(
|
|
285
224
|
{
|
|
286
|
-
name:
|
|
225
|
+
name: "Lazy Route Load",
|
|
287
226
|
attributes: {
|
|
288
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]:
|
|
289
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]:
|
|
290
|
-
}
|
|
227
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.client_lazy",
|
|
228
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
229
|
+
}
|
|
291
230
|
},
|
|
292
|
-
async span => {
|
|
231
|
+
async (span) => {
|
|
293
232
|
const result = await callLazy();
|
|
294
|
-
if (result.status ===
|
|
295
|
-
span.setStatus({ code: SPAN_STATUS_ERROR, message:
|
|
296
|
-
captureInstrumentationError(result, captureErrors,
|
|
233
|
+
if (result.status === "error" && result.error instanceof Error) {
|
|
234
|
+
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
235
|
+
captureInstrumentationError(result, captureErrors, "react_router.client_lazy", {});
|
|
297
236
|
}
|
|
298
|
-
}
|
|
237
|
+
}
|
|
299
238
|
);
|
|
300
|
-
}
|
|
239
|
+
}
|
|
301
240
|
});
|
|
302
|
-
}
|
|
241
|
+
}
|
|
303
242
|
};
|
|
304
243
|
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Check if React Router's instrumentation API is being used on the client.
|
|
308
|
-
* @experimental
|
|
309
|
-
*/
|
|
310
244
|
function isClientInstrumentationApiUsed() {
|
|
311
245
|
return !!GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG];
|
|
312
246
|
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Check if React Router's instrumentation API's navigate hook was invoked.
|
|
316
|
-
* @experimental
|
|
317
|
-
*/
|
|
318
247
|
function isNavigateHookInvoked() {
|
|
319
248
|
return !!GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG];
|
|
320
249
|
}
|
|
@@ -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":[],"mappings":";;;;;;AAiBA,MAAM,MAAA,GAAS,UAAA;;AAEf;AACA,IAAI,4BAA4B;;AAEhC;AACA,MAAM,qBAAA,GAAwB,IAAI,OAAO,EAAkC;;AAE3E,MAAM,kCAAA,GAAqC,8CAA8C;AACzF;AACA,MAAM,iCAAA,GAAoC,wCAAwC;AAClF,MAAM,mCAAA,GAAsC,0CAA0C;;AAQtF,MAAM,iBAAA,GAAoB,UAAA;;AAE1B;AACA;AACA;;AAUA;AACA;AACA;AACA;AACO,SAAS,iCAAiC;AACjD,EAAE,OAAO,GAA6C,EAAE;AACxD,EAAyB;AACzB,EAAE,MAAM,EAAE,aAAA,GAAgB,IAAA,EAAK,GAAI,OAAO;;AAE1C,EAAE,eAAe,KAAK,CAAC,GAAG,CAAC,kDAAkD,CAAC;;AAE9E,EAAE,OAAO;AACT,IAAI,MAAM,CAAC,MAAM,EAAwB;AACzC;AACA;AACA;AACA;AACA,MAAM,iBAAiB,CAAC,kCAAkC,CAAA,GAAI,IAAI;AAClE,MAAM,eAAe,KAAK,CAAC,GAAG,CAAC,iEAAiE,CAAC;;AAEjG;AACA,MAAM,IAAI,CAAC,iBAAiB,CAAC,mCAAmC,CAAA,IAAK,MAAM,CAAC,gBAAgB,EAAE;AAC9F,QAAQ,iBAAiB,CAAC,mCAAmC,CAAA,GAAI,IAAI;;AAErE,QAAQ,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,MAAM;AAClD,UAAU,MAAM,MAAA,GAAS,SAAS,EAAE;AACpC,UAAU,IAAI,CAAC,MAAM,EAAE;AACvB,YAAY,4BAAA,GAA+B,SAAS;AACpD,YAAY;AACZ,UAAU;;AAEV,UAAU,MAAM,WAAW,MAAM,CAAC,QAAQ,EAAE,QAAA,IAAY,GAAG;;AAE3D;AACA,UAAU,IAAI,4BAA4B,EAAE;AAC5C,YAAY,IAAI,4BAA4B,CAAC,WAAW,EAAE,EAAE;AAC5D,cAAc,4BAA4B,CAAC,UAAU,CAAC,QAAQ,CAAC;AAC/D,YAAY;AACZ,YAAY,4BAAA,GAA+B,SAAS;AACpD,YAAY;AACZ,UAAU;;AAEV;AACA,UAAU,iCAAiC,CAAC,MAAM,EAAE;AACpD,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,UAAU,EAAE;AACxB,cAAc,CAAC,gCAAgC,GAAG,KAAK;AACvD,cAAc,CAAC,4BAA4B,GAAG,YAAY;AAC1D,cAAc,CAAC,gCAAgC,GAAG,kDAAkD;AACpG,cAAc,iBAAiB,EAAE,kBAAkB;AACnD,aAAa;AACb,WAAW,CAAC;AACZ,QAAQ,CAAC,CAAC;;AAEV,QAAQ,eAAe,KAAK,CAAC,GAAG,CAAC,gFAAgF,CAAC;AAClH,MAAM;;AAEN,MAAM,MAAM,CAAC,UAAU,CAAC;AACxB,QAAQ,MAAM,QAAQ,CAAC,YAAY,EAAE,IAAI,EAAE;AAC3C;AACA;AACA,UAAU,IAAI,IAAI,CAAC,EAAA,KAAO,CAAC,EAAE;AAC7B,YAAY,MAAM,MAAA,GAAS,MAAM,YAAY,EAAE;AAC/C,YAAY,IAAI,MAAM,CAAC,MAAA,KAAW,OAAA,IAAW,MAAM,CAAC,KAAA,YAAiB,KAAK,EAAE;AAC5E,cAAc,2BAA2B,CAAC,MAAM,EAAE,aAAa,EAAE,uBAAuB,EAAE;AAC1F,gBAAgB,UAAU,EAAE,IAAI,CAAC,UAAU;AAC3C,eAAe,CAAC;AAChB,YAAY;AACZ,YAAY;AACZ,UAAU;;AAEV,UAAU,iBAAiB,CAAC,iCAAiC,CAAA,GAAI,IAAI;;AAErE;AACA,UAAU,IAAI,OAAO,IAAI,CAAC,EAAA,KAAO,QAAQ,EAAE;AAC3C,YAAY,MAAM,MAAA,GAAS,SAAS,EAAE;AACtC,YAAY,IAAI,cAAc;;AAE9B,YAAY,IAAI,MAAM,EAAE;AACxB,cAAc,MAAM,cAAA,GAAiB,IAAI,CAAC,EAAA,GAAK,CAAA,GAAI,aAAA,GAAgB,gBAAgB;AACnF,cAAc,MAAM,eAAA,GAAkB,MAAM,CAAC,QAAQ,EAAE,QAAA,IAAY,IAAI,CAAC,UAAU;;AAElF,cAAc,cAAA,GAAiB,iCAAiC,CAAC,MAAM,EAAE;AACzE,gBAAgB,IAAI,EAAE,eAAe;AACrC,gBAAgB,UAAU,EAAE;AAC5B,kBAAkB,CAAC,gCAAgC,GAAG,KAAK;AAC3D,kBAAkB,CAAC,4BAA4B,GAAG,YAAY;AAC9D,kBAAkB,CAAC,gCAAgC,GAAG,kDAAkD;AACxG,kBAAkB,iBAAiB,EAAE,cAAc;AACnD,iBAAiB;AACjB,eAAe,CAAC;;AAEhB;AACA,cAAc,4BAAA,GAA+B,cAAc;AAC3D,YAAY;;AAEZ,YAAY,IAAI;AAChB,cAAc,MAAM,MAAA,GAAS,MAAM,YAAY,EAAE;;AAEjD,cAAc,IAAI,cAAA,IAAkB,MAAM,CAAC,QAAQ,EAAE;AACrD,gBAAgB,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACnE,cAAc;;AAEd,cAAc,IAAI,MAAM,CAAC,MAAA,KAAW,OAAA,IAAW,MAAM,CAAC,KAAA,YAAiB,KAAK,EAAE;AAC9E,gBAAgB,IAAI,cAAc,EAAE;AACpC,kBAAkB,cAAc,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,gBAAA,EAAkB,CAAC;AAClG,gBAAgB;AAChB,gBAAgB,2BAA2B,CAAC,MAAM,EAAE,aAAa,EAAE,uBAAuB,EAAE;AAC5F,kBAAkB,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAA,IAAY,IAAI,CAAC,UAAU;AAC1E,iBAAiB,CAAC;AAClB,cAAc;AACd,YAAY,UAAU;AACtB,cAAc,4BAAA,GAA+B,SAAS;AACtD,YAAY;AACZ,YAAY;AACZ,UAAU;;AAEV;AACA,UAAU,MAAM,MAAA,GAAS,SAAS,EAAE;AACpC,UAAU,MAAM,SAAS,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AACpD,UAAU,IAAI,cAAc;;AAE5B,UAAU,IAAI,MAAM,EAAE;AACtB,YAAY,cAAA,GAAiB,iCAAiC,CAAC,MAAM,EAAE;AACvE,cAAc,IAAI,EAAE,MAAM;AAC1B,cAAc,UAAU,EAAE;AAC1B,gBAAgB,CAAC,gCAAgC,GAAG,KAAK;AACzD,gBAAgB,CAAC,4BAA4B,GAAG,YAAY;AAC5D,gBAAgB,CAAC,gCAAgC,GAAG,kDAAkD;AACtG,gBAAgB,iBAAiB,EAAE,iBAAiB;AACpD,eAAe;AACf,aAAa,CAAC;AACd,UAAU;;AAEV,UAAU,MAAM,MAAA,GAAS,MAAM,YAAY,EAAE;AAC7C,UAAU,IAAI,MAAM,CAAC,MAAA,KAAW,OAAA,IAAW,MAAM,CAAC,KAAA,YAAiB,KAAK,EAAE;AAC1E,YAAY,IAAI,cAAc,EAAE;AAChC,cAAc,cAAc,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,gBAAA,EAAkB,CAAC;AAC9F,YAAY;AACZ,YAAY,2BAA2B,CAAC,MAAM,EAAE,aAAa,EAAE,uBAAuB,EAAE;AACxF,cAAc,UAAU,EAAE,MAAM;AAChC,aAAa,CAAC;AACd,UAAU;AACV,UAAU;AACV,QAAQ,CAAC;;AAET,QAAQ,MAAM,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE;AACrC,UAAU,MAAM,SAAS;AACzB,YAAY;AACZ,cAAc,IAAI,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;AACA,cAAA,UAAA,EAAA;AACA,gBAAA,CAAA,4BAAA,GAAA,+BAAA;AACA,gBAAA,CAAA,gCAAA,GAAA,gDAAA;AACA,eAAA;AACA,aAAA;AACA,YAAA,MAAA,IAAA,IAAA;AACA,cAAA,MAAA,MAAA,GAAA,MAAA,SAAA,EAAA;AACA,cAAA,IAAA,MAAA,CAAA,MAAA,KAAA,OAAA,IAAA,MAAA,CAAA,KAAA,YAAA,KAAA,EAAA;AACA,gBAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,CAAA;AACA,gBAAA,2BAAA,CAAA,MAAA,EAAA,aAAA,EAAA,sBAAA,EAAA;AACA,kBAAA,UAAA,EAAA,IAAA,CAAA,IAAA;AACA,iBAAA,CAAA;AACA,cAAA;AACA,YAAA,CAAA;AACA,WAAA;AACA,QAAA,CAAA;AACA,OAAA,CAAA;AACA,IAAA,CAAA;;AAEA,IAAA,KAAA,CAAA,KAAA,EAAA;AACA,MAAA,MAAA,OAAA,GAAA,KAAA,CAAA,EAAA;;AAEA,MAAA,KAAA,CAAA,UAAA,CAAA;AACA,QAAA,MAAA,MAAA,CAAA,UAAA,EAAA,IAAA,EAAA;AACA,UAAA,MAAA,OAAA,GAAA,kBAAA,CAAA,IAAA,CAAA,OAAA,CAAA;AACA,UAAA,MAAA,YAAA,GAAA,kBAAA,CAAA,UAAA,CAAA,IAAA,CAAA,CAAA,IAAA,OAAA;;AAEA,UAAA,MAAA,SAAA;AACA,YAAA;AACA,cAAA,IAAA,EAAA,YAAA;AACA,cAAA,UAAA,EAAA;AACA,gBAAA,CAAA,4BAAA,GAAA,qCAAA;AACA,gBAAA,CAAA,gCAAA,GAAA,gDAAA;AACA,eAAA;AACA,aAAA;AACA,YAAA,MAAA,IAAA,IAAA;AACA,cAAA,MAAA,MAAA,GAAA,MAAA,UAAA,EAAA;AACA,cAAA,IAAA,MAAA,CAAA,MAAA,KAAA,OAAA,IAAA,MAAA,CAAA,KAAA,YAAA,KAAA,EAAA;AACA,gBAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,CAAA;AACA,gBAAA,2BAAA,CAAA,MAAA,EAAA,aAAA,EAAA,4BAAA,EAAA;AACA,kBAAA,UAAA,EAAA,OAAA;AACA,iBAAA,CAAA;AACA,cAAA;AACA,YAAA,CAAA;AACA,WAAA;AACA,QAAA,CAAA;;AAEA,QAAA,MAAA,MAAA,CAAA,UAAA,EAAA,IAAA,EAAA;AACA,UAAA,MAAA,OAAA,GAAA,kBAAA,CAAA,IAAA,CAAA,OAAA,CAAA;AACA,UAAA,MAAA,YAAA,GAAA,kBAAA,CAAA,UAAA,CAAA,IAAA,CAAA,CAAA,IAAA,OAAA;;AAEA,UAAA,MAAA,SAAA;AACA,YAAA;AACA,cAAA,IAAA,EAAA,YAAA;AACA,cAAA,UAAA,EAAA;AACA,gBAAA,CAAA,4BAAA,GAAA,qCAAA;AACA,gBAAA,CAAA,gCAAA,GAAA,gDAAA;AACA,eAAA;AACA,aAAA;AACA,YAAA,MAAA,IAAA,IAAA;AACA,cAAA,MAAA,MAAA,GAAA,MAAA,UAAA,EAAA;AACA,cAAA,IAAA,MAAA,CAAA,MAAA,KAAA,OAAA,IAAA,MAAA,CAAA,KAAA,YAAA,KAAA,EAAA;AACA,gBAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,CAAA;AACA,gBAAA,2BAAA,CAAA,MAAA,EAAA,aAAA,EAAA,4BAAA,EAAA;AACA,kBAAA,UAAA,EAAA,OAAA;AACA,iBAAA,CAAA;AACA,cAAA;AACA,YAAA,CAAA;AACA,WAAA;AACA,QAAA,CAAA;;AAEA,QAAA,MAAA,UAAA,CAAA,cAAA,EAAA,IAAA,EAAA;AACA,UAAA,MAAA,OAAA,GAAA,kBAAA,CAAA,IAAA,CAAA,OAAA,CAAA;AACA,UAAA,MAAA,YAAA,GAAA,kBAAA,CAAA,UAAA,CAAA,IAAA,CAAA,CAAA,IAAA,OAAA;;AAEA,UAAA,IAAA,QAAA,GAAA,qBAAA,CAAA,GAAA,CAAA,IAAA,CAAA,OAAA,CAAA;AACA,UAAA,IAAA,CAAA,QAAA,EAAA;AACA,YAAA,QAAA,GAAA,EAAA;AACA,YAAA,qBAAA,CAAA,GAAA,CAAA,IAAA,CAAA,OAAA,EAAA,QAAA,CAAA;AACA,UAAA;;AAEA,UAAA,MAAA,eAAA,GAAA,QAAA,CAAA,OAAA,CAAA,IAAA,CAAA;AACA,UAAA,QAAA,CAAA,OAAA,CAAA,GAAA,eAAA,GAAA,CAAA;;AAEA,UAAA,MAAA,SAAA;AACA,YAAA;AACA,cAAA,IAAA,EAAA,CAAA,WAAA,EAAA,OAAA,CAAA,CAAA;AACA,cAAA,UAAA,EAAA;AACA,gBAAA,CAAA,4BAAA,GAAA,yCAAA;AACA,gBAAA,CAAA,gCAAA,GAAA,gDAAA;AACA,gBAAA,uBAAA,EAAA,OAAA;AACA,gBAAA,YAAA,EAAA,YAAA;AACA,gBAAA,+BAAA,EAAA,eAAA;AACA,eAAA;AACA,aAAA;AACA,YAAA,MAAA,IAAA,IAAA;AACA,cAAA,MAAA,MAAA,GAAA,MAAA,cAAA,EAAA;AACA,cAAA,IAAA,MAAA,CAAA,MAAA,KAAA,OAAA,IAAA,MAAA,CAAA,KAAA,YAAA,KAAA,EAAA;AACA,gBAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,CAAA;AACA,gBAAA,2BAAA,CAAA,MAAA,EAAA,aAAA,EAAA,gCAAA,EAAA;AACA,kBAAA,UAAA,EAAA,OAAA;AACA,iBAAA,CAAA;AACA,cAAA;AACA,YAAA,CAAA;AACA,WAAA;AACA,QAAA,CAAA;;AAEA,QAAA,MAAA,IAAA,CAAA,QAAA,EAAA;AACA,UAAA,MAAA,SAAA;AACA,YAAA;AACA,cAAA,IAAA,EAAA,iBAAA;AACA,cAAA,UAAA,EAAA;AACA,gBAAA,CAAA,4BAAA,GAAA,mCAAA;AACA,gBAAA,CAAA,gCAAA,GAAA,gDAAA;AACA,eAAA;AACA,aAAA;AACA,YAAA,MAAA,IAAA,IAAA;AACA,cAAA,MAAA,MAAA,GAAA,MAAA,QAAA,EAAA;AACA,cAAA,IAAA,MAAA,CAAA,MAAA,KAAA,OAAA,IAAA,MAAA,CAAA,KAAA,YAAA,KAAA,EAAA;AACA,gBAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,CAAA;AACA,gBAAA,2BAAA,CAAA,MAAA,EAAA,aAAA,EAAA,0BAAA,EAAA,EAAA,CAAA;AACA,cAAA;AACA,YAAA,CAAA;AACA,WAAA;AACA,QAAA,CAAA;AACA,OAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,8BAAA,GAAA;AACA,EAAA,OAAA,CAAA,CAAA,iBAAA,CAAA,kCAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,qBAAA,GAAA;AACA,EAAA,OAAA,CAAA,CAAA,iBAAA,CAAA,iCAAA,CAAA;AACA;;;;"}
|
|
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":["result","client","navigationSpan"],"mappings":"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"}
|