Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save EddieCanales/7cb9b854b22389268d7effacd35ad700 to your computer and use it in GitHub Desktop.
Save EddieCanales/7cb9b854b22389268d7effacd35ad700 to your computer and use it in GitHub Desktop.
Record client-side exceptions in Google Analytics
import ga from 'universal-ga';
window.addEventListener('error', e => {
let message;
if (e.error && e.error.stack) {
message = e.error.stack;
} else {
message = e.error || e.message || 'Unknown error';
}
if (
e.error &&
e.error.stack &&
!e.error.stack.includes(e.message.replace('Uncaught ', ''))
) {
message = `${e.message} - ${e.error.stack}`;
}
// 1. Track the full exception as a GA exception.
// This is visible in custom reports that look at exceptions and can include the full stack trace.
ga.exception(message);
// 2. Track the name and message as an event.
// This shows up in event flows and the user explorer and is used to track what happened right before an exception.
ga.event('Exception', e.name, {
eventLabel: e.message,
eventValue: 1,
nonInteractive: true,
});
});
@coreysnyder04
Copy link

One thing I'm still not sure on, In cases where you have an operational error like where the user tries to sign in with a user that doesn't exist. What's the best way to get that error back to the FE for display.

Here's an API endpoint for login for example

async login(parent, args, context, info) {
      let user = await context.prisma.user({
        email: args.email.toLowerCase(),
      })

      if (!user) {
        throw new AppError('No such user found', true)
      }
}

Here I'm throwing an instance of my app-error, which sets it to operational so it doesn't get passed Sentry.io for error logging.
Here's how it comes through on the FE:
Status Code: 200 OK
image

But is it best to throw an error for an operational error? Or should I instead be returning a JSON block like:

{
  success: false
  reason: "No such user found"
}

@EddieCanales
Copy link
Author

The question about throwing vs returning an object vs something else is a good one. I am in favor of throwing where appropriate in Node APIs, but I feel like doing so in a UI app (like a React.js app) seems to not fit their ideas of how to manage state. So you could in this case lets say if the user isn't logged in, you want to redirect to store what page the user was on, then redirect them to the login screen. You could just handle the redirect right in the login function, update redux with the user (or in this case the lack of a user) and have middleware redirect based on that state change, or return a null value or a null value with a message like you've shown and have the thing calling login do the redirect. I think it all depends on how you have your app setup.

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