Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FastBoot support #77

Open
mirague opened this issue Apr 20, 2017 · 9 comments
Open

Add FastBoot support #77

mirague opened this issue Apr 20, 2017 · 9 comments

Comments

@mirague
Copy link

mirague commented Apr 20, 2017

Currently it'll always try to app.import the Raven JS library, even in FastBoot (server side).
This results in the below error for every request:

Error: Raven has already been configured

We should wrap the app.import with a check for process.env.EMBER_CLI_FASTBOOT in index.js:

    try {
      var stats = fs.statSync(app.bowerDirectory + '/raven-js/dist/raven.js');
      if (!stats.errno && !process.env.EMBER_CLI_FASTBOOT) {
        app.import(app.bowerDirectory + '/raven-js/dist/raven.js');
      }
    } catch (e) {
      console.log('ember-cli-sentry will not be loaded from bower installation');
    }
@mazondo
Copy link
Contributor

mazondo commented May 28, 2017

I'll probably end up tackling this within the next week or so, but just in case someone gets here first. The above fix is no longer recommended and will not work in fastboot rc.1. New method here: https://gist.github.com/kratiahuja/d22de0fb1660cf0ef58f07a6bcbf1a1c#using-processenvember_cli_fastboot-to-run-import-in-browser-build

@oscarni
Copy link

oscarni commented Jun 14, 2017

Any news on this front? Are none of the 3 PRs applicable since fastboot rc.1?

@mazondo
Copy link
Contributor

mazondo commented Jul 16, 2017

I haven't had a chance to in our app yet, but the problem is that most fastboot fixes just skip it when in fastboot, in this case I think we actually want to use it in fastboot and client side - but it requires some changes to how events are sent to sentry. More info is here: getsentry/raven-node#303

@dashdashzako
Copy link
Contributor

With the recent changes of Sentry packages management (addition of scoped packages), I wonder if this issue could be solved more easily than what could be done a year ago.

@viniciussbs
Copy link

Hi. What's the state of FastBoot support?

@Turbo87
Copy link
Collaborator

Turbo87 commented Apr 14, 2019

@viniciussbs doesn't exist

@viniciussbs
Copy link

@Turbo87 Can you tell if the app crashes on FastBoot land or it just does not report the errors?

@reidab
Copy link

reidab commented Oct 28, 2019

We're working around this using fastboot-app-server by setting up a Node Sentry client in our Express server.js file and exposing it to the FastBoot environment via as FastBootSentry via sandboxGlobals. We then have an Ember.onerror handler set up via an instance-initializer that uses the passed instance.

It's not ideal, since we aren't able to use most Sentry's built-in tooling to extract metadata from the request, but at least these errors aren't just silently being logged and forgotten.

In server.js

const FastBootAppServer = require('fastboot-app-server');
const serverOptions = { <whatever options the FB app server needs> }

if (process.env.SENTRY_DSN) {
  Sentry = require('@sentry/node');
  Sentry.init({ dsn: process.env.SENTRY_DSN });
  serverOptions.sandboxGlobals = { FastBootRaven: Sentry };
}

const server = new FastBootAppServer(serverOptions);
server.start();

Instance initializer in the Ember app:

/* Sets up Ember's global error handler in FastBoot to use a Raven instance
  * provided in our fastboot-server via the Fastboot sandbox.
  */
 export default {
   name: 'app-error-handler',

    initialize(appInstance) {
     let oldOnError;

     if (Ember.onerror === 'undefined' && typeof FastBoot !== 'undefined') {
       /* This replicates the default logging Ember.onerror implementation
        * included with FastBoot, since that implementation isn't installed
        * when any existing Ember.onerror has been set.
        */
       oldOnError = function(err) {
         const errorMessage = `There was an error running your app in fastboot. More info about the error: \n ${err.stack || err}`;
         console.error(errorMessage);
       };
     } else {
       oldOnError = Ember.onerror; // eslint-disable-line ember-suave/no-direct-property-access
     }

      Ember.onerror = (error) => {
       if (typeof FastBootRaven !== 'undefined') {
         const fastboot = appInstance.lookup('service:fastboot');
         const req = fastboot.request;
         const { protocol, headers } = req;
         const host = req.hostname || req.host || headers.host || '<no host>';
         const originalUrl = (req.originalUrl || req.url || req.path);
         const absoluteUrl = `${protocol}://${host}${originalUrl}`;

          FastBootRaven.withScope(function(scope) {
           scope.setTag('url', absoluteUrl);
           scope.setExtra('query_params', req.query_params);
           FastBootRaven.captureException(error);
         });
       }
       if (typeof(oldOnError) === 'function') { oldOnError.call(Ember, error); }
     };
   },
 };

@williamweckl
Copy link

williamweckl commented Dec 29, 2019

For some reason Ember.onerror does not work at fastboot requests anymore. I did something different.

Using ember 3.15 with octane.

Configured an error route, Ember automatically handles errors using this route:

# app/routes/error.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class ErrorRoute extends Route {
  @service('error-handler') errorHandlerService;

  // setupController function receives the error exception as a parameter
  setupController(_controller, error) {
    this.coreErrorHandlerService.handleServerSideError(error);

    super.setupController(...arguments);
  }

}
# app/templates/error.hbs

PUT HERE A NICE HTML THAT WILL SHOW TO USER IN CASE OF ERRORS

A service to handle errors:

# app/services/error-handler.js

import Service from '@ember/service';
import { inject as service } from '@ember/service';

export default class errorHandlerService extends Service {
  @service('fastboot') fastboot;

  handleServerSideError(error) {
    if (!this.fastboot.isFastBoot) return;

    if (typeof FastBootRaven !== 'undefined') {
      const req = fastboot.request;
      const { protocol, headers } = req;
      const host = req.hostname || req.host || headers.host || '<no host>';
      const originalUrl = (req.originalUrl || req.url || req.path);
      const absoluteUrl = `${protocol}://${host}${originalUrl}`;
      // const userScope = this.userScope; // If you have an user scope you can get from service property here

      FastBootRaven.withScope(function(scope) {
        scope.setTag('url', absoluteUrl);
        scope.setExtra('query_params', req.query_params);
        // scope.setUser(userScope);

        FastBootRaven.captureException(error);
      });
    }
  }

And of course, I've setted my server.js like @reidab's example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants