Open utterances-bot opened 11 months ago
This was extremely useful, thanks so much for sharing!
after adding all these, i still don't get meaningful info. any idea?
queryClient
export const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (error, query) => {
withScope((scope) => {
scope.setContext('query', { queryHash: query.queryHash });
scope.setFingerprint([query.queryHash.replaceAll(/[0-9]/g, '0')]);
captureException(error);
});
const withErrorToast =
query.meta?.withErrorToast === undefined ? true : query.meta?.withErrorToast;
if (!withErrorToast && process.env.EXPO_PUBLIC_ENV_NAME === 'PROD') {
return;
}
const errorMessage = getHttpErrorMessages(error)?.[0].message;
Toast.show({
type: 'error',
text1: errorMessage,
visibilityTime: 3000,
});
},
}),
mutationCache: new MutationCache({
onError: (error, _var, _context, mutation) => {
withScope((scope) => {
scope.setContext('mutation', {
mutationId: mutation.mutationId,
variables: mutation.state.variables,
});
if (mutation.options.mutationKey) {
scope.setFingerprint(
// Duplicate to prevent modification
Array.from(mutation.options.mutationKey) as string[],
);
}
captureException(error);
});
const withErrorToast =
mutation.meta?.withErrorToast === undefined ? true : mutation.meta?.withErrorToast;
if (!withErrorToast && process.env.EXPO_PUBLIC_ENV_NAME === 'PROD') {
return;
}
const errorMessage = getHttpErrorMessages(error)?.[0].message;
Toast.show({
type: 'error',
text1: errorMessage,
visibilityTime: 3000,
});
},
}),
});
export const init = () => {
return Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
environment: process.env.EXPO_PUBLIC_ENV_NAME,
/**
* Set to true for local debugging
* Set back to false when pushing commits
*/
enableInExpoDevelopment: true,
/**
* If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production
*/
debug: __DEV__,
tracesSampleRate: 1.0,
integrations: [
new Sentry.Native.ReactNativeTracing({
shouldCreateSpanForRequest: (url) => {
return !__DEV__ || !url.startsWith(`http://${Constants?.expoConfig?.hostUri}/logs`);
},
}),
new ExtraErrorDataIntegration(),
],
});
};
The fingerprinting is really cool, but I found that it doesn't group errors as well as I'd like. For example, my app frequently makes requests to an endpoint GET /resources/<resource_uuid>/
where resource_uuid
is an arbitrary UUID. However, the queryHash is unable to map all of them to the same value.
I suspect that queryHash.replaceAll(/[0-9]/g, "0")
is attempting to do this for integer value ids only, but it fails because a UUID contains hex and hyphens? Perhaps we need a more complex regex matcher that replaces any UUID, like this stackoverflow suggests? https://stackoverflow.com/a/6640851
Here's something I came up with:
function canonicalizeQueryHash(queryHash: string): string {
return (
queryHash
// Numbers wrapped in forward-slashes, or at the end of the string
.replaceAll(/\/[0-9]+(\/|$)/g, '/<id>$1')
.replaceAll(
// UUIDs wrapped in forward-slashes, or at the end of the string
/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(\/|$)/g,
'/<uuid>$1'
)
)
}
Meaningful Sentry issues with react-query + axios - Lakur
This post shows how to enrich axios errors when using react-query and how to handle them on a global level.
https://lakur.tech/2022/12/16/generating-meaningful-issues-in-sentry-with-react-query-+-axios/