@sentry/remix
Version:
Official Sentry SDK for Remix
134 lines (131 loc) • 5.27 kB
JavaScript
import { hasSpanStreamingEnabled, PAGELOAD_SPAN_NAME_FALLBACK, debug, getCurrentScope, getActiveSpan, getRootSpan, NAVIGATION_SPAN_NAME_FALLBACK } from '@sentry/core';
import { isNodeEnv } from '@sentry/core/server';
import { startBrowserTracingPageLoadSpan, getClient, WINDOW, startBrowserTracingNavigationSpan } from '@sentry/react';
import * as React from 'react';
import { DEBUG_BUILD } from '../utils/debug-build.js';
import { maybeParameterizeRemixRoute, hasManifest } from './remixRouteParameterization.js';
import { SENTRY_SEGMENT_NAME_SOURCE, URL_TEMPLATE, SENTRY_ORIGIN, SENTRY_OP } from '@sentry/conventions/attributes';
import { PAGELOAD, NAVIGATION } from '@sentry/conventions/op';
let _useEffect;
let _useLocation;
let _useMatches;
let _instrumentNavigation;
function getInitPathName() {
if (WINDOW.location) {
return WINDOW.location.pathname;
}
return void 0;
}
function getTransactionNameAndSource(pathname, routeId) {
const parameterizedRoute = pathname ? maybeParameterizeRemixRoute(pathname) : void 0;
if (parameterizedRoute) {
return { name: parameterizedRoute, source: "route" };
}
if (hasManifest()) {
return { name: pathname || routeId, source: "url" };
}
return { name: routeId, source: "route" };
}
function startPageloadSpan(client) {
const initPathName = getInitPathName();
if (!initPathName) {
return;
}
const parameterizedRoute = maybeParameterizeRemixRoute(initPathName);
const spanName = parameterizedRoute || initPathName;
const source = parameterizedRoute ? "route" : "url";
const spanContext = {
// With span streaming, span names have to be low cardinality, so we can't fall back to the URL.
name: source === "route" || !hasSpanStreamingEnabled(client) ? spanName : PAGELOAD_SPAN_NAME_FALLBACK,
attributes: {
[SENTRY_OP]: PAGELOAD,
[SENTRY_ORIGIN]: "auto.pageload.remix",
[SENTRY_SEGMENT_NAME_SOURCE]: source,
...source === "route" && { [URL_TEMPLATE]: spanName }
}
};
startBrowserTracingPageLoadSpan(client, spanContext);
}
function startNavigationSpan(matches, location) {
const lastMatch = matches[matches.length - 1];
const client = getClient();
if (!client || !lastMatch) {
return;
}
const { name, source } = getTransactionNameAndSource(location.pathname, lastMatch.id);
const spanContext = {
// With span streaming, span names have to be low cardinality, so we can't fall back to the URL.
name: source === "route" || !hasSpanStreamingEnabled(client) ? name : NAVIGATION_SPAN_NAME_FALLBACK,
attributes: {
[SENTRY_OP]: NAVIGATION,
[SENTRY_ORIGIN]: "auto.navigation.remix",
[SENTRY_SEGMENT_NAME_SOURCE]: source,
...source === "route" && { [URL_TEMPLATE]: name }
}
};
startBrowserTracingNavigationSpan(client, spanContext);
}
function withSentry(OrigApp, useEffect, useLocation, useMatches, instrumentNavigation) {
const SentryRoot = (props) => {
setGlobals({ useEffect, useLocation, useMatches, instrumentNavigation: instrumentNavigation || true });
if (!_useEffect || !_useLocation || !_useMatches) {
DEBUG_BUILD && !isNodeEnv() && debug.warn("Remix SDK was unable to wrap your root because of one or more missing parameters.");
return /* @__PURE__ */ React.createElement(OrigApp, { ...props });
}
let isBaseLocation = false;
const location = _useLocation();
const matches = _useMatches();
_useEffect(() => {
const lastMatch = matches?.[matches.length - 1];
if (lastMatch) {
const { name, source } = getTransactionNameAndSource(location.pathname, lastMatch.id);
getCurrentScope().setTransactionName(name);
const activeRootSpan = getActiveSpan();
if (activeRootSpan) {
const transaction = getRootSpan(activeRootSpan);
if (transaction) {
const client = getClient();
const isUnparameterizedStreamedPageload = source !== "route" && !!client && hasSpanStreamingEnabled(client);
transaction.updateName(isUnparameterizedStreamedPageload ? PAGELOAD_SPAN_NAME_FALLBACK : name);
transaction.setAttribute(SENTRY_SEGMENT_NAME_SOURCE, source);
if (source === "route") {
transaction.setAttribute(URL_TEMPLATE, name);
}
}
}
}
isBaseLocation = true;
}, []);
_useEffect(() => {
const activeRootSpan = getActiveSpan();
if (isBaseLocation) {
if (activeRootSpan) {
activeRootSpan.end();
}
return;
}
if (_instrumentNavigation && matches?.length) {
if (activeRootSpan) {
activeRootSpan.end();
}
startNavigationSpan(matches, location);
}
}, [location]);
isBaseLocation = false;
return /* @__PURE__ */ React.createElement(OrigApp, { ...props });
};
return SentryRoot;
}
function setGlobals({
useEffect,
useLocation,
useMatches,
instrumentNavigation
}) {
_useEffect = useEffect || _useEffect;
_useLocation = useLocation || _useLocation;
_useMatches = useMatches || _useMatches;
_instrumentNavigation = instrumentNavigation ?? _instrumentNavigation;
}
export { setGlobals, startPageloadSpan, withSentry };
//# sourceMappingURL=performance.js.map