diff --git a/frontend/lib/shopify-storefront-sdk/index.ts b/frontend/lib/shopify-storefront-sdk/index.ts index 73e84870..b9a797be 100644 --- a/frontend/lib/shopify-storefront-sdk/index.ts +++ b/frontend/lib/shopify-storefront-sdk/index.ts @@ -45,9 +45,8 @@ export function getServerShopifyStorefrontSdk(shop: ShopCredentials) { scope.setExtra('query', doc); scope.setExtra('variables', variables); scope.setExtra('errors', result.errors); - Sentry.captureException(new Error(errorMessage)); + throw new Error(errorMessage); }); - throw new Error(errorMessage); } return result.data; }; diff --git a/frontend/lib/strapi-sdk/index.ts b/frontend/lib/strapi-sdk/index.ts index 6afa6acc..87ea65c0 100644 --- a/frontend/lib/strapi-sdk/index.ts +++ b/frontend/lib/strapi-sdk/index.ts @@ -39,9 +39,7 @@ const requester: Requester = async ( scope.setExtra('query', doc); scope.setExtra('variables', variables); scope.setExtra('errors', result.errors); - Sentry.captureException( - new Error('Strapi SDK GraphQL query failed with errors') - ); + throw new Error('Strapi SDK GraphQL query failed with errors'); }); } throw new Error(`GraphQL query failed to execute: ${response.statusText}`); diff --git a/frontend/next.config.js b/frontend/next.config.js index 81f6fb32..880c90d1 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -149,7 +149,6 @@ const moduleExports = { return config; }, sentry: { - autoInstrumentServerFunctions: false, // Upload artifacts in dist/framework as well; this includes sourcemaps // for react and other next.js code widenClientFileUpload: true, diff --git a/frontend/pages/_error.js b/frontend/pages/_error.js deleted file mode 100644 index 9ab1a293..00000000 --- a/frontend/pages/_error.js +++ /dev/null @@ -1,65 +0,0 @@ -import NextErrorComponent from 'next/error'; - -import * as Sentry from '@sentry/nextjs'; - -const MyError = ({ statusCode, hasGetInitialPropsRun, err }) => { - if (!hasGetInitialPropsRun && err) { - // getInitialProps is not called in case of - // https://github.com/vercel/next.js/issues/8592. As a workaround, we pass - // err via _app.js so it can be captured - Sentry.captureException(err); - // Flushing is not required in this case as it only happens on the client - } - - return ; -}; - -MyError.getInitialProps = async (context) => { - const errorInitialProps = await NextErrorComponent.getInitialProps(context); - - const { res, err, asPath } = context; - - // Workaround for https://github.com/vercel/next.js/issues/8592, mark when - // getInitialProps has run - errorInitialProps.hasGetInitialPropsRun = true; - - // Returning early because we don't want to log 404 errors to Sentry. - if (res?.statusCode === 404) { - return errorInitialProps; - } - - // Running on the server, the response object (`res`) is available. - // - // Next.js will pass an err on the server if a page's data fetching methods - // threw or returned a Promise that rejected - // - // Running on the client (browser), Next.js will provide an err if: - // - // - a page's `getInitialProps` threw or returned a Promise that rejected - // - an exception was thrown somewhere in the React lifecycle (render, - // componentDidMount, etc) that was caught by Next.js's React Error - // Boundary. Read more about what types of exceptions are caught by Error - // Boundaries: https://reactjs.org/docs/error-boundaries.html - - if (err) { - Sentry.captureException(err); - - // Flushing before returning is necessary if deploying to Vercel, see - // https://vercel.com/docs/platform/limits#streaming-responses - await Sentry.flush(2000); - - return errorInitialProps; - } - - // If this point is reached, getInitialProps was called without any - // information about what the error might be. This is unexpected and may - // indicate a bug introduced in Next.js, so record it in Sentry - Sentry.captureException( - new Error(`_error.js getInitialProps missing data at path: ${asPath}`) - ); - await Sentry.flush(2000); - - return errorInitialProps; -}; - -export default MyError; diff --git a/frontend/pages/_error.tsx b/frontend/pages/_error.tsx new file mode 100644 index 00000000..55785f91 --- /dev/null +++ b/frontend/pages/_error.tsx @@ -0,0 +1,38 @@ +/** + * NOTE: This requires `@sentry/nextjs` version 7.3.0 or higher. + * + * This page is loaded by Nextjs: + * - on the server, when data-fetching methods throw or reject + * - on the client, when `getInitialProps` throws or rejects + * - on the client, when a React lifecycle method throws or rejects, and it's + * caught by the built-in Nextjs error boundary + * + * See: + * - https://nextjs.org/docs/basic-features/data-fetching/overview + * - https://nextjs.org/docs/api-reference/data-fetching/get-initial-props + * - https://reactjs.org/docs/error-boundaries.html + */ + +import * as Sentry from '@sentry/nextjs'; +import type { NextPage } from 'next'; +import type { ErrorProps } from 'next/error'; +import NextErrorComponent from 'next/error'; + +const CustomErrorComponent: NextPage = (props) => { + // If you're using a Nextjs version prior to 12.2.1, uncomment this to + // compensate for https://github.com/vercel/next.js/issues/8592 + // Sentry.captureUnderscoreErrorException(props); + + return ; +}; + +CustomErrorComponent.getInitialProps = async (contextData) => { + // In case this is running in a serverless function, await this in order to give Sentry + // time to send the error before the lambda exits + await Sentry.captureUnderscoreErrorException(contextData); + + // This will contain the status code of the response + return NextErrorComponent.getInitialProps(contextData); +}; + +export default CustomErrorComponent; diff --git a/packages/sentry/index.tsx b/packages/sentry/index.tsx index ed063040..b05fa799 100644 --- a/packages/sentry/index.tsx +++ b/packages/sentry/index.tsx @@ -36,13 +36,6 @@ export const applySentryFetchMiddleware = () => { } }; -export const reportException: CaptureWithContextFn = (e, context) => { - Sentry.captureException(e, (scope) => { - scope.setContext('request', context); - return scope; - }); -}; - const withSentry: FetchMiddleware = (fetcher, shouldSkipRequest) => async (input, init) => { if (shouldSkipRequest?.(input, init)) { diff --git a/packages/shopify-storefront-client/index.tsx b/packages/shopify-storefront-client/index.tsx index cd4246a3..8cafc108 100644 --- a/packages/shopify-storefront-client/index.tsx +++ b/packages/shopify-storefront-client/index.tsx @@ -1,4 +1,3 @@ -import { reportException } from '@ifixit/sentry'; import * as React from 'react'; interface ShopifyStorefrontClientOptions { diff --git a/packages/shopify-storefront-client/package.json b/packages/shopify-storefront-client/package.json index 2677374b..be679af6 100644 --- a/packages/shopify-storefront-client/package.json +++ b/packages/shopify-storefront-client/package.json @@ -4,9 +4,6 @@ "main": "./index.tsx", "types": "./index.tsx", "license": "MIT", - "dependencies": { - "@ifixit/sentry": "workspace:*" - }, "devDependencies": { "@types/react": "18.0.24", "@types/react-dom": "18.0.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 695c3c7e..b418c287 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -497,13 +497,10 @@ importers: packages/shopify-storefront-client: specifiers: - '@ifixit/sentry': workspace:* '@ifixit/tsconfig': workspace:* '@types/react': 18.0.24 '@types/react-dom': 18.0.8 typescript: 4.8.4 - dependencies: - '@ifixit/sentry': link:../sentry devDependencies: '@ifixit/tsconfig': link:../tsconfig '@types/react': 18.0.24