Skip to content
This repository has been archived by the owner on May 5, 2023. It is now read-only.

Commit

Permalink
refactor: update how sentry is configured for ssr
Browse files Browse the repository at this point in the history
vercel/next.js#8684
Signed-off-by: Logan McAnsh <[email protected]>
  • Loading branch information
mcansh committed Sep 17, 2019
1 parent 747828c commit 868b273
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 24 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'warn',
{ extensions: ['.js', '.jsx', '.tsx', '.mdx'] },
],
'react/prop-types': 'off',
'no-underscore-dangle': ['error', { allow: ['__NEXT_DATA__'] }],
'no-console': ['error', { allow: ['warn', 'error'] }],
'@typescript-eslint/explicit-member-accessibility': 'error',
Expand Down
20 changes: 6 additions & 14 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,10 @@ Sentry.init({
});

interface Props {
Component: React.Component;
pageProps: Record<string, any>;
locale: string;
initialNow: number;
err?: Error;
}

class MyApp extends App<Props> {
public componentDidCatch(error: Error, errorInfo: any) {
Sentry.withScope(scope => {
scope.setExtras(errorInfo);
Sentry.captureException(error);
});

super.componentDidCatch(error, errorInfo);
}

public componentDidMount() {
initGA();
logPageView();
Expand All @@ -41,13 +29,17 @@ class MyApp extends App<Props> {
public render() {
const { Component, pageProps } = this.props;

// https://github.com/zeit/next.js/pull/8684/files?file-filters%5B%5D=.js&file-filters%5B%5D=.json#diff-3418d602a84e69f78132b489a2062cc0R14
const { err } = this.props;
const modifiedPageProps = { ...pageProps, err };

return (
<React.StrictMode>
<ThemeProvider theme={colors}>
<>
<GlobalStyle />
<Document>
<Component {...pageProps} />
<Component {...modifiedPageProps} />
</Document>
</>
</ThemeProvider>
Expand Down
13 changes: 3 additions & 10 deletions pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,7 @@ process.on('uncaughtException', err => {
Sentry.captureException(err);
});

interface Props {
styles: string;
locale: string;
localeDataScript: string;
}

class MyDocument extends Document<Props> {
class MyDocument extends Document {
public static async getInitialProps(context: DocumentContext) {
const sheet = new ServerStyleSheet();

Expand All @@ -45,12 +39,11 @@ class MyDocument extends Document<Props> {
}

public render() {
const { locale, inAmpMode } = this.props;

const { inAmpMode } = this.props;
const { csp, hash } = getCSP(this.props);

return (
<Html lang={locale}>
<Html lang="en">
<Head>
{!inAmpMode && (
<meta httpEquiv="Content-Security-Policy" content={csp} />
Expand Down
73 changes: 73 additions & 0 deletions pages/_error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react';
import { NextPage } from 'next';
import NextError, { ErrorProps } from 'next/error';
import * as Sentry from '@sentry/node';

interface Props extends ErrorProps {
hasGetInitialPropsRun?: boolean;
err?: Error;
}

const MyError: NextPage<Props> = ({
statusCode,
hasGetInitialPropsRun,
err,
}) => {
if (!hasGetInitialPropsRun && err) {
// getInitialProps is not called in case of
// https://github.com/zeit/next.js/issues/8592. As a workaround, we pass
// err via _app.js so it can be captured
Sentry.captureException(err);
}

return <NextError statusCode={statusCode} />;
};

MyError.getInitialProps = async context => {
const { res, err, asPath } = context;
const errorInitialProps = await NextError.getInitialProps(context);

if (res) {
// Running on the server, the response object is available.
//
// Next.js will pass an err on the server if a page's `getInitialProps`
// threw or returned a Promise that rejected

if (res.statusCode === 404) {
// Opinionated: do not record an exception in Sentry for 404
return { statusCode: 404 };
}

if (err) {
Sentry.captureException(err);

// Workaround for https://github.com/zeit/next.js/issues/8592, mark when
// getInitialProps has run
return { ...errorInitialProps, hasGetInitialPropsRun: true };
}
} else if (err) {
// 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
Sentry.captureException(err);

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}`)
);

return errorInitialProps;
};

export default MyError;

0 comments on commit 868b273

Please sign in to comment.