vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.71k stars 26.94k forks source link

How to catch and handle errors to report logs on server side #1852

Closed acanimal closed 2 years ago

acanimal commented 7 years ago

Hi, I'm in the situation where we want to sent errors, both on server and client side, to Sentry tool.

Our app uses Express as a custom server. Basically we create an express app, apply some middlewares but delegate all the real job to the next.js handle:

  const app = nextJs({ dev: process.env.NODE_ENV !== 'production' });
  const handler = routes.getRequestHandler(app);
  const expressApp = express();

  ...
  ...

  expressApp.use(morgan('combined', { stream: logger.stream }));
  expressApp.use(statsdMiddleware);

  // Add security
  expressApp.use(helmet());

  // Sentry handler
  expressApp.use(sentry.requestHandler());

  // Load locale and translation messages
  expressApp.use(i18n);

  // Next.js handler
  expressApp.use(handler);

  // Sentry error handler.
  // MUST be placed before any other express error handler !!!
  expressApp.use(sentry.errorHandler());

With this approach next.js takes control over the rendering process and any error is catch by next.js and the only way I have to process it is overriding the _error.js page file.

Within that _error.js file I need a universal way to report errors to Sentry. Currently there are two libraries (raven for node and raven-js por javascript). The proble is I can't import both of them because raven works for SSR but fails when webpack builds the bundle, and also raven-js fails due XMLHTTPRequest dependency too.

Is there a way I can be notified for next.js error on server side?

jgautheron commented 7 years ago

For logging errors in the client side we have been doing the following: https://gist.github.com/jgautheron/044b88307d934d486f59ae87c5a5a5a0

It basically sends errors to the server, that are in the end printed to stdout and caught by our Docker logging driver. We have successfully caught SSR errors with react-guard with no need to override core Next files.

ethanresnick commented 7 years ago

I'm also having this problem. I wonder: would simply returning a rejected promise from next's handleRequest be sufficient? That is, changing the code here to be:

handleRequest (req, res, parsedUrl) {
  // .....snip....

   return this.run(req, res, parsedUrl)
     .catch((err) => {
       if (!this.quiet) console.error(err)
       res.statusCode = 500
       res.end(STATUS_CODES[500])

       // rethrow error to create new, rejected promise 
       throw err;
     })
}

Then, in user code:

const app = nextJs({ dev: process.env.NODE_ENV !== 'production' });
const nextJsHandler = app.getRequestHandler();
const expressApp = express();

app.prepare().then(() => {
   // invoke express middlewares
   // ...

   // time to run next
   expressApp.use(function(req, res, next) {
     nextJsHandler(req, res).catch(e => {
       // use rejected promise to forward error to next express middleware
       next(e)
     })
   });

   // Use standard express error middlewares to handle the error from next
   // this makes it easy to log to sentry etc.
})
ethanresnick commented 7 years ago

@arunoda @rauchg Do you think the change I proposed immediately above would work? If so, happy to submit a PR

hunt commented 7 years ago

Agree to re-throw an error so we can play around with it. Also need to re-throw at renderToHTML too...

coox commented 7 years ago

I am also in the situation where we want to sent errors, both on server and client side, to a service similar to Sentry.

I believe that the most valuable feature of such services/tools is to report issues that are most unexpected, which in my experience are uncaught errors in the wild (ie. client-side). Unfortunately, as previously stressed out in related issue #2334, Next.js’ client-side handlers keep these errors to themselves, with no possible way to pass them to Sentry of such other tool.

What has bitten us particularly hard is this: a properly server-side rendered page is re-rendered as an error page if an uncaught exception occurs before React rendering on the client-side. This can be seen as either a great feature, but also a frustrating developer experience, as it essentially ruins the benefits of serving an already rendered document, on a surprisingly portion of clients.

Here is a sample page that illustrates the problem:

import React from 'react';

// Works well in Node 8, but crashes in Chrome<56, Firefox<48, Edge<15, Safari<10, any IE…
const whoops = 'Phew, I made it to the client-side…'.padEnd(80);

export default () => <pre>{whoops}</pre>;

The above code can be perfectly server-side-rendered and delivered to the client, only to become a Flash Of Unwanted Content before the whole page is replaced on the client-side by the dreaded ”An unexpected error has occurred” message on most browsers, without any possible way to report the error to Sentry (or any other service/tool).

This ”error swallowing” also prevents any leverage of the standard onerror handler, which most client-side error reporting tools hook onto (or the more modern, but not widespread, onunhandledrejection, which may be more suitable given the async nature of client-side code).

Possible client-side solution

As far as I can tell, this type of pre-React client-side error is swallowed in the try/catch block in Next.js’ client/index.js where the Component about to be rendered is re-assigned to the value of ErrorComponent (currently lines 67-72).

Dear Next.js authors and maintainers, for the sake of control of what is rendered, what would you think would be acceptable/possible among the following ideas:

timneutkens commented 7 years ago

introduce a hook in that catch block in client/index.js for handling this kind of error? transmit the error to an onerror/onunhandledrejection handler, if any is detected?

This is something we've talked about internally. And we'll be addressing soon.

acanimal commented 7 years ago

I'm using Sentry.io to report errors and the solution we apply is:

1- Configure raven-node on server side 2- Configure ravenjs on client side (we made that on _document.

With this two steps we catch any unhandled exceptions both on client and server.

3- Create an _error page. Any error produced once nextjs handles the request (no matter if client or server side) that page is rendered. In the getInitialProps method of the _error page we report the error to sentry.

The way to decide how to load if raven-node or ravenjs is solved importing dynamically depending if we are in client const Raven = require('raven-js'); or server side const Raven = require('raven');. Note we have configured webpack to not bundle the raven module (the server side one) updating next.config.js with:

const webpack = require('webpack');

module.exports = {
  // Do not show the X-Powered-By header in the responses
  poweredByHeader: false,
  webpack: (config) => {
    config.plugins.push(new webpack.IgnorePlugin(/^raven$/));
    return config;
  },
};
tusgavomelo commented 7 years ago

@acanimal

2- Configure ravenjs on client side (we made that on _document.

Can you show me how did you configured raven-js on your _document.js? It's not working for me, when any error occur nothing happens on sentry.

Do I need to send the all the errors manually at _error.js page to sentry?

// _document constructor
constructor(props) {
    super(props);
    Raven
      .config('...')
      .install();
}
damusnet commented 7 years ago

Next.js still outputs errors to console.error on the server as long as you don't set it to quiet.

With Sentry, you can enable autoBreadcrumbs to capture this output, and then capture your own message manually. The title will be less descriptive, but it will still contain the full stack trace.

Example implementation:

const express = require('express');
const nextjs = require('next');
const Raven = require('raven');

const dev = process.env.NODE_ENV !== 'production';

// Must configure Raven before doing anything else with it
if (!dev) {
  Raven.config('__DSN__', {
    autoBreadcrumbs: true,
    captureUnhandledRejections: true,
  }).install();
}

const app = nextjs({ dev });
const handle = app.getRequestHandler();

const captureMessage = (req, res) => () => {
  if (res.statusCode > 200) {
    Raven.captureMessage(`Next.js Server Side Error: ${res.statusCode}`, {
      req,
      res,
    });
  }
};

app
  .prepare()
  .then(() => {
    const server = express();

    if (!dev) {
      server.use((req, res, next) => {
        res.on('close', captureMessage(req, res));
        res.on('finish', captureMessage(req, res));
        next();
      });
    }

    [...]

    server.get('/', (req, res) => {
      return app.render(req, res, '/home', req.query)
    })

    server.get('*', (req, res) => {
      return handle(req, res)
    })

    server.listen('3000', (err) => {
      if (err) throw err
      console.log(`> Ready on http://localhost:${port}`)
    })
  })
  .catch(ex => {
    console.error(ex.stack);
    process.exit(1);
  });

This is a very contrived example adapted from our actual code. I haven't tested it in this form. Let me know if it breaks.

Of course, it would still be best if Next.js could pass those errors around to Express, so that we can use the Sentry/Express integration out of the box.

acanimal commented 7 years ago

@tusgavomelo Sorry, for the late reply.

We have update. In our app we have a helper file with a method responsible to get a Raven instance taking into account if we are on client or server side.

let clientInstance;
let serverInstance;

const getRavenInstance = (key, config) => {
  const clientSide = typeof window !== 'undefined';

  if (clientSide) {
    if (!clientInstance) {
      const Raven = require('raven-js');  // eslint-disable-line global-require
      Raven.config(key, config).install();
      clientInstance = Raven;
    }

    return clientInstance;
  }

  if (!serverInstance) {
    // NOTE: raven (for node) is not bundled by webpack (see rules in next.config.js).
    const RavenNode = require('raven'); // eslint-disable-line global-require
    RavenNode.config(key, config).install();
    serverInstance = RavenNode;
  }
  return serverInstance;
};

This code runs both server side (when a request arrives) and client side. What we have done is configure webpack (next.config.js file) to avoid bundle the raven package.

Fettah commented 6 years ago

@acanimal can you maybe provide a working example ? It seems I am not getting the full stack trace ? or maybe can you post your _error.js?

I am doing something like RavenInstance.captureException(err) in my _error.js, but I do not get to see the type of errors that occured as well as where?

export default class Error extends React.Component {
  static getInitialProps({ res, err }) {
    const RavenInstance = getRavenInstance('__SENTRY__')
    if (!(err instanceof Error)) {
      err = new Error(err && err.message)
    }
    RavenInstance.captureException(err)
    // const statusCode = res ? res.statusCode : err ? err.statusCode : null;

    return { }
  }

  render() {
    return (
      <div>
        <p>An error occurred on server</p>
      </div>
    )
  }
}
wenzowski commented 6 years ago

This seems like the place to ask for custom logger support since quiet must be set to false to prevent next clearing screen on module rebuild and thus purging errors from view, yet the only workable hack here requires setting quiet to false.

tusgavomelo commented 6 years ago

The errors details are also available on the stderr stream. process.stderr.write = error => yourErrorLog(error);

ghost commented 6 years ago

Gotta love unortodox solutions

function installErrorHandler(app) {
  const _renderErrorToHTML = app.renderErrorToHTML.bind(app)
  const errorHandler = rollbar.errorHandler()

  app.renderErrorToHTML = (err, req, res, pathname, query) => {
    if (err) {
      errorHandler(err, req, res, () => {})
    }

    return _renderErrorToHTML(err, req, res, pathname, query)
  }

  return app
}
// ¯\_(ツ)_/¯
Tarabyte commented 6 years ago

Compact version of how to get correct Raven for node and browser w/o custom webpack config. Inspired by @acanimal comment

// package.json
"browser": {
    "raven": "raven-js"
}

// getRaven.js
const Raven = require('raven')

if (process.env.NODE_ENV === 'production') {
  Raven.config('YOUR_SENTRY_DSN').install()
}

module.exports = Raven

Gist

blackbing commented 6 years ago

a quick recap for anyone who investigating on this problem.

// pages/_error.js
import Raven from 'raven';
...
static async getInitialProps({ store, err, isServer }) {
   if (isServer && err) {
      // https://github.com/zeit/next.js/issues/1852
      // eslint-disable-next-line global-require
      const Raven = require('raven');

      Raven.captureException(err);
    }
    ...
// next.config.js
config.plugins.push(new webpack.IgnorePlugin(/^raven$/));

thanks to @acanimal 's comment.

rozsival commented 6 years ago

Install both raven (ignore with webpack as suggested in previous comments) and raven-js, then create a helper to instantiate isomorphic Raven, e.g. lib/raven.js

import Raven from 'raven-js';

// https://gist.github.com/impressiver/5092952
const clientIgnores = {
  ignoreErrors: [
    'top.GLOBALS',
    'originalCreateNotification',
    'canvas.contentDocument',
    'MyApp_RemoveAllHighlights',
    'http://tt.epicplay.com',
    "Can't find variable: ZiteReader",
    'jigsaw is not defined',
    'ComboSearch is not defined',
    'http://loading.retry.widdit.com/',
    'atomicFindClose',
    'fb_xd_fragment',
    'bmi_SafeAddOnload',
    'EBCallBackMessageReceived',
    'conduitPage',
    'Script error.',
  ],
  ignoreUrls: [
    // Facebook flakiness
    /graph\.facebook\.com/i,
    // Facebook blocked
    /connect\.facebook\.net\/en_US\/all\.js/i,
    // Woopra flakiness
    /eatdifferent\.com\.woopra-ns\.com/i,
    /static\.woopra\.com\/js\/woopra\.js/i,
    // Chrome extensions
    /extensions\//i,
    /^chrome:\/\//i,
    // Other plugins
    /127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
    /webappstoolbarba\.texthelp\.com\//i,
    /metrics\.itunes\.apple\.com\.edgesuite\.net\//i,
  ],
};

const options = {
  autoBreadcrumbs: true,
  captureUnhandledRejections: true,
};

let IsomorphicRaven = null;

if (process.browser === true) {
  IsomorphicRaven = Raven;
  IsomorphicRaven.config(SENTRY_PUBLIC_DSN, {
    ...clientIgnores,
    ...options,
  }).install();
} else {
  // https://arunoda.me/blog/ssr-and-server-only-modules
  IsomorphicRaven = eval("require('raven')");
  IsomorphicRaven.config(
    SENTRY_DSN,
    options,
  ).install();
}

export default IsomorphicRaven;

Then you can use it in your pages/_error.js and it will work both on server and client side.

import NextError from 'next/error';
import IsomorphicRaven from 'lib/raven';

class MyError extends NextError {
  static getInitialProps = async (context) => {
    if (context.err) {
      IsomorphicRaven.captureException(context.err);
    }
    const errorInitialProps = await NextError.getInitialProps(context);
    return errorInitialProps;
  };
}

export default MyError;
MartinKristof commented 6 years ago

Here is my PR for Rollbar sourcemap wepback plugin https://github.com/thredup/rollbar-sourcemap-webpack-plugin/pull/56 with Next.js support :)

Ravalika24 commented 6 years ago

@tusgavomelo , Can you elaborate on how to make use of the error present on the stream ? "process.stderr.write = error => yourErrorLog(error);"

Where should we write this line of code, for it to log the error to Node console ?

MartinKristof commented 6 years ago

That is only Client side. Rollbar.error('some error')

https://docs.rollbar.com/docs/javascript

sheerun commented 6 years ago

@teekey99 Do you have similar solution for @sentry/browser? Maybe update with-sentry example?

rozsival commented 6 years ago

@sheerun I've been using raven and raven-js so far. I am aware that those will probably become deprecated as all new features are now added to @sentry/node and @sentry/browser. The thing is I haven't used these new libraries on my projects yet, but I'll try to look into it. If I have a working example I'll get back with it.

timneutkens commented 6 years ago

The with-sentry example was recently updated.

sheerun commented 6 years ago

@timneutkens I see but it doesn't support server-side errors as Sentry is initialized inside App where it's too late to catch server errors. Proper solution would probably use @sentry/node somewhere

timrogers commented 6 years ago

@sheerun I'm hitting the same issue. Using @sentry/node isn't trivial. The readme for this Sentry example suggests using a custom server, which we already have in the application I'm working on. To capture exceptions in our custom Express.js server, you need to insert a Sentry error handler middleware error as the first error handling middleware. If you insert Sentry's error handler straight after the Next handler, the error has already been swallowed by that point and Sentry doesn't see it.

mcdougal commented 6 years ago

I've been using @sentry/browser in the getInitialProps of _error.js and it seems to be working both client and server-side. I don't know if @sentry/browser is supposed to have server-side support, but I am getting events to Sentry.

Though I am also calling Sentry.init() via @sentry/node in a custom Express server's entry file, so perhaps that is setting some global state that the SSR is using.

Here's a gist of the setup that I'm using: https://gist.github.com/mcdougal/7bf001417c3dc4b579da224b12776691

timrogers commented 6 years ago

Interesting!

There's definitely some kind of global state going on here (which is a bit scary, and probably brittle and undesirable). Applying your changes in _error.js:

It would be good to understand what the official solution is. Next's docs seem to recommend using a custom <App> component now, and that's what the "with Sentry" example does, but this only works for the client side.

sheerun commented 6 years ago

Error reporting for sure won't happen until first time App is rendered. Next can fail way before e.g. when rendering Page. Maybe by chance it happens to work in some cases after app has rendered on server side first time, but for sure it's not a full solution.

conanbatt commented 6 years ago

The with-sentry example does not work for me either @timneutkens. Running the project and testing it with my actual DSN gives out a 400 response and nothing gets to sentry (version 7 of the api).

{"error":"Bad data reconstructing object (JSONDecodeError, Expecting value: line 1 column 1 (char 0))"}

The @mcdougal did not work for me. It was already not quite great to have a global server-side setup that somehow bubbles up to the client, but even with that hack I would get sentry 301 responses.

I dont see how my sentry self-hosted setup could have a misconfiguration, as there aren't many options and Its running on multiple projects.

Jauny commented 6 years ago

I'm using @sentry/browser in the same way that it is recommended in the with-sentry example, and it seems to be sending errors both from the server and the client to my sentry. I don't have any special config, only the same code as the example.

timrogers commented 6 years ago

@Jauny Are you sure it is sending from the server? How have you tested that? The readme of the example even seems to suggest that it won't work on the server.

Jauny commented 6 years ago

@timrogers yes indeed my bad, I assumed a tested error was coming from the server but actually was triggered from the client :(

sheerun commented 6 years ago

It seems that current example with-sentry doesn't catch errors thrown in getInitialProps, just ones in render tree of application.. In my case most of the errors are from getInitialProps.

Enalmada commented 6 years ago

@sheerun Can you try the mcdougal workaround above? It isn't perfect (strange synthetic sentry errors) but I am under the impression it gets all errors and would like to know if that is not true. If it is true, the with-sentry example probably needs to be updated with that until Next.js can advise on how to do it better (ideally making it so the server.js sentry error handler isn't skipped?).

sheerun commented 6 years ago

It seems it kinda works with two major issues:

  1. Probably because asynchronous server-side code is unnecessarily compiled into regenerator code, server-side stacktraces in production are often truncated on internal/process/next_tick.js and no cause of error is visible at all.
  2. Error handling won't work if errors are thrown before next request handler is called (e.g. in custom server code)
sheerun commented 6 years ago

Actually after further testing getInitialProps of custom Error for some reason is not even firing in production when error happens for example inside custom _app's getInitialProps..

mcdougal commented 6 years ago

Yeah, I've definitely been getting some weird behavior after running with my attempt for a few days. Seems like the main problems we're facing are:

  1. Importing @sentry/browser for CSR and @sentry/node for SSR
  2. Finding a place to put error handling that always gets triggered for both CSR and SSR

I've been thinking of trying to use lazy imports and global state to solve #1, something like

const sentryInitialized = false;

# Inside some trigger point
const Sentry = ssr ? eval(`require('@sentry/node')`) : eval(`require('@sentry/browser')`);
if (!sentryInitialized) {
  Sentry.init({dsn: SENTRY_DSN});
}
Sentry.captureException(err);

Maybe Next's dynamic imports could be used, but I'm not that familiar with them yet. I'm also not sure the repercussions of calling require every time the error handling code gets triggered. I'll update if/when I give this a try.

As far as problem #2, seems like the possibilities are:

  1. _app.componentDidCatch, which doesn't fire for SSR
  2. _error.getInitialProps, which has a multitude of problems
  3. ...something else? Is there anything we can do for SSR in the Next server handler function?
timrogers commented 6 years ago

My gut feeling is that there’ll be a way to do this on the server by injecting Sentry’s error handler before Next’s, but I haven’t given it a go yet.

At the moment, Next doesn’t provide any hooks to help you do that. If we found that this works, we could add them 👌

There’s a risk that this won’t work because Next catches too early, though.

Enalmada commented 6 years ago

@mcdougal Ah &#!% I was so happy when your workaround might have been good enough to check off the sentry client/server coverage required to get us into production.

Pardon my complete ignorance but do we just need next to allow us to disable its error handler conditionally so that the nodejs sentry error handler becomes the first? Some flag in next.config.js called "disableErrorHandler"?

timrogers commented 6 years ago

@Enalmada I don’t think you’d want to disable the Next error handler because it’ll be that which renders a nice error page. You just want to insert other middleware before it. I think that will work, but I need to try it.

Even with that fixed, I still don’t feel like client-side error handling works as well as I’d hope :(

This whole issue is a shame and it really is a blocker to safely running Next in production.

sheerun commented 6 years ago

FYI I import everywhere @sentry/node and put following into next.config.js:

        if (!isServer) {
          config.resolve.alias['@sentry/node$'] = '@sentry/browser'
        }

which can be better than eval of @mcdougal

sheerun commented 6 years ago

Here are my extra notes about custom _app component and error handling:

  1. _app.js is used for ALL pages, including _error.js or pages like 404 so you really want to be sure no error is thrown when ctx.err is passed to it..
  2. Don't forget to call Component.getInitialProps in getInitialProps of app as it'll prevent getInitialProps of _error.js to be called (call it even if ctx.err is present)
class MyApp extends App {
  static async getInitialProps (appContext) {
    const { Component, ctx } = appContext
    if (ctx.err) {
      if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx)
      }
      return { error: true, pageProps }
    }
    // here code that can throw an error, and then:
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }
    return { pageProps }
  }
  render() {
    if (this.props.error) return super.render()
    // rest of code that can throw an error
  }
}

So far I find properly setting up error reporting in next.js a very fragile procedure :(

Jauny commented 6 years ago

thanks @sheerun that looks like a good stop towards the right direction. I do agree that error handling in next is not optimal right now, it'll be great to see some extensible module/middleware added so we can add error handling on it etc.

The lack of isomorphic libraries such as sentry is also making things complicated, because that means we can't simple import either library in our components, we need to do it dynamically at runtime to always check if the error is raised server or browser side.

abraxxas commented 5 years ago

Is there an update to this issue? What i tried so far is the following: I moved all our tracking code into the _app.js

constructor(args: any) {
        super(args)
        Sentry.init({
            dsn: 'blah',
            environment: 'local',
        })
        Sentry.configureScope(scope => {
            scope.setTag('errorOrigin', isServer ? 'SSR' : 'Client')
        })
    }
    static async getInitialProps({ Component, router, ctx }: any) {
        let pageProps = {}

        try {
            if (Component.getInitialProps) {
                pageProps = await Component.getInitialProps(ctx)
            }
        } catch (error) {
            // console.log('we caught an error')
            console.log(error)
            Sentry.captureException(error)
            throw error
        }

        return { pageProps }
    }

coupled with the next.config.js addition from @sheerun and initializing sentry in the server.js too if (!isServer) { config.resolve.alias['@sentry/node$'] = '@sentry/browser' } this seems to track all errors on the client side, but on the server side it only seems to track the first error that happens after a restart of the server. Later errors on the server are not tracked though. With this approach i do not have any SyntheticErrors in the log, but only real errors.

Still this feels quite hacky to me and since the server side tracking is only working the first time it is still non-usable.

I also added this part from the with-Sentry example

    componentDidCatch(error: any, errorInfo: any) {
        // if (process.env.FIAAS_NAMESPACE !== undefined) {
        Sentry.configureScope(scope => {
            Object.keys(errorInfo).forEach(key => {
                scope.setExtra(key, errorInfo[key])
            })
        })
        Sentry.captureException(error)
        console.log('componentDidCatch')

        // This is needed to render errors correctly in development / production
        super.componentDidCatch(error, errorInfo)
        // }
    }

but i am not totally sure if this is needed

sheerun commented 5 years ago

In my case with works without issues. also you shuld not init sentry in _app.js constructor but outside of this class entirely

On Wed, Nov 21, 2018 at 2:53 PM abraxxas notifications@github.com wrote:

Is there an update to this issue? What i tried so far is the following: I moved all our tracking code into the _app.js

` constructor(args: any) { super(args) Sentry.init({ dsn: 'blah', environment: 'local', }) Sentry.configureScope(scope => { scope.setTag('errorOrigin', isServer ? 'SSR' : 'Client') }) }

static async getInitialProps({ Component, router, ctx }: any) { let pageProps = {}

try {
    if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx)
    }
} catch (error) {
    // console.log('we caught an error')
    console.log(error)
    Sentry.captureException(error)
    throw error
}

return { pageProps }

}

`

coupled with the next.config.js addition from @sheerun https://github.com/sheerun and initializing sentry in the server.js too if (!isServer) { config.resolve.alias['@sentry/node$'] = '@sentry/browser' } this seems to track all errors on the client side, but on the server side it only seems to track the first error that happens after a restart of the server. Later errors on the server are not tracked though. With this approach i do not have any SyntheticErrors in the log, but only real errors.

Still this feels quite hacky to me and since the server side tracking is only working the first time it is still non-usable.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/zeit/next.js/issues/1852#issuecomment-440668980, or mute the thread https://github.com/notifications/unsubscribe-auth/AAR2DeIhoOj6PdWRA2VqiEZyrO5Jui8vks5uxVrHgaJpZM4NOQlp .

abraxxas commented 5 years ago

I tried moving it out already and still the same behaviour. @sheerun could you maybe post a minimal gist of your setup? I tried setting it up with the snippets you provided and i just can't get it to work. The whole thing seems overly complicated for what i expected to be a rather simple task :( Are you also initializing sentry on the server or only in _app.js outside the class?

sheerun commented 5 years ago

I'd update official sentry example but I'm afraid it'll be rejected as "too complex" I can try to post something though when I'll find time..

Enalmada commented 5 years ago

@sheerun Even an attempt to update to the official example would be of great value. I feel it would get merged if it really is the minimum complexity necessary to get sentry ssr working without SyntheticErrors or only recording the first server error that happens. Then we can go from there to figure out ways of making it better or pushing for nextjs core improvements or sentry isomorphic support.

sheerun commented 5 years ago

Here it goes.. https://github.com/zeit/next.js/pull/5727

Enalmada commented 5 years ago

So now that we have a necessarily complex working example, what are the next steps to improve the situation: