Rather than react router or tanstack router, I'm trying to do browser tracing with Wouter. Is the right approach here to do a "custom routing" integration? Any gotchas?
Learn what spans are captured after tracing is enabled.
9 messages · Page 1 of 1 (latest)
Rather than react router or tanstack router, I'm trying to do browser tracing with Wouter. Is the right approach here to do a "custom routing" integration? Any gotchas?
Learn what spans are captured after tracing is enabled.
Hi @meager crown. I'm happy to dig into this for you! I'll check my internal sources for answers to your question! :wave:
Yes, for integrating Sentry's browser tracing with Wouter, using a custom routing integration is the right approach. Since Sentry doesn't have a built-in integration specifically for Wouter (unlike React Router or TanStack Router), you'll need to implement custom routing instrumentation.
Here's how you can set it up:
browserTracingIntegration:const client = Sentry.init({
integrations: [
Sentry.browserTracingIntegration({
// disable automatic span creation
instrumentNavigation: false,
instrumentPageLoad: false,
}),
],
});
// Start the pageload span as early as possible
let pageLoadSpan = Sentry.startBrowserTracingPageLoadSpan(client, {
name: window.location.pathname,
attributes: {
[Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
},
});
// Use Wouter's useLocation hook or router events to track navigation
// Example with useLocation:
const [location, setLocation] = useLocation();
// Set up an effect to track location changes
useEffect(() => {
// For the initial pageload
if (pageLoadSpan) {
pageLoadSpan.updateName(location);
pageLoadSpan.setAttribute(
Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
"route"
);
pageLoadSpan = undefined;
} else {
// For subsequent navigations
Sentry.startBrowserTracingNavigationSpan(client, {
op: "navigation",
name: location,
attributes: {
[Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
},
});
}
}, [location]);
As for gotchas, here are a few things to keep in mind:
@meager crown Our robots are still learning and improving, please let us know if this response was correct by reacting below.
@solar pilot Thanks. In a react app, what would be the optimal place to initialize the pageLoadSpan? and then should I use a Ref or something to keep track of it?
Let me check the knowledge base for you again. One moment! :books:
In a React app using Wouter, the optimal place to initialize the pageLoadSpan would be as early as possible in your application's lifecycle. Here are the best practices for implementation:
The ideal place to initialize the pageLoadSpan is in your application's entry point file (typically index.js or App.js), right after initializing Sentry:
// In your app's entry point (e.g., index.js)
import * as Sentry from "@sentry/react";
const client = Sentry.init({
dsn: "your-dsn",
integrations: [
Sentry.browserTracingIntegration({
instrumentNavigation: false,
instrumentPageLoad: false,
}),
],
tracesSampleRate: 1.0,
});
// Start the pageload span immediately after initialization
let pageLoadSpan = Sentry.startBrowserTracingPageLoadSpan(client, {
name: window.location.pathname,
attributes: {
[Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
},
});
Yes, using a React ref is a good approach to keep track of the pageLoadSpan across your application. You can create a context to make it accessible throughout your app:
// Create a context for the span
import { createContext, useRef, useContext } from 'react';
const SpanContext = createContext(null);
export function SpanProvider({ children, initialPageLoadSpan }) {
const pageLoadSpanRef = useRef(initialPageLoadSpan);
return (
<SpanContext.Provider value={pageLoadSpanRef}>
{children}
</SpanContext.Provider>
);
}
export function useSpanContext() {
return useContext(SpanContext);
}
Then in your router component with Wouter:
import { useLocation } from 'wouter';
import { useSpanContext } from './SpanContext';
import * as Sentry from "@sentry/react";
function RouterTracker() {
const [location] = useLocation();
const pageLoadSpanRef = useSpanContext();
useEffect(() => {
const client = Sentry.getClient();
if (pageLoadSpanRef.current) {
// Update the pageload span with the route name
pageLoadSpanRef.current.updateName(location);
pageLoadSpanRef.current.setAttribute(
Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
"route"
);
pageLoadSpanRef.current = undefined; // Clear after first navigation
} else {
// For subsequent navigations
Sentry.startBrowserTracingNavigationSpan(client, {
op: "navigation",
name: location,
attributes: {
[Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
},
});
}
}, [location, pageLoadSpanRef]);
return null; // This component doesn't render anything
}
This approach follows the pattern shown in Sentry's documentation for [custom routing instrumentation](<https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation/#custom-routing>) while adapting it to React's component lifecycle and Wouter's routing system.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------