function reportSentryError()

in packages/fxa-auth-server/lib/sentry.js [33:114]


function reportSentryError(err, request) {
  let exception = '';
  if (err && err.stack) {
    try {
      exception = err.stack.split('\n')[0];
    } catch (e) {
      // ignore bad stack frames
    }
  }

  if (ignoreErrors(err)) {
    return;
  }

  Sentry.withScope((scope) => {
    if (request) {
      scope.addEventProcessor((sentryEvent) => {
        sentryEvent.request = Sentry.extractRequestData(request.raw.req);
        sentryEvent.level = 'error';
        return sentryEvent;
      });
    }

    // Important! Set a flag so that we know this is an error captured
    // and reported by our code. Once we added tracing, we started seeing errors
    // propagate in other ways. By setting a breakpoint or adding a console.trace
    // in beforeSend, we can see that Sentry's internal libraries are picking up
    // and reporting errors too. This causes problems because:
    //  - It means errors are double captured
    //  - It means that extra error info added below won't be there are errors
    //    where captured by this function.
    //  - It means the duplicate error might have a different shape, and fool
    //    our ignoreErrors() check.
    //
    // See the filterSentryEvent function to see how this flag is used.
    //
    scope.setExtra('report', true);
    scope.setExtra('exception', exception);
    // If additional data was added to the error, extract it.
    if (err.output && typeof err.output.payload === 'object') {
      const payload = err.output.payload;
      if (typeof payload.data === 'object') {
        scope.setContext('payload.data', payload.data);
        delete payload.data;
      }
      scope.setContext('payload', payload);
    }
    const cause = verror.cause(err);
    if (cause && cause.message) {
      const causeContext = {
        errorName: cause.name,
        reason: cause.reason,
        errorMessage: cause.message,
      };

      // Poolee EndpointError's have a few other things and oddly don't include
      // a stack at all. We try and extract a bit more to reflect what actually
      // happened as 'socket hang up' is somewhat inaccurate when the remote server
      // throws a 500.
      const output = cause.output;
      if (output && output.payload) {
        for (const key of ['error', 'message', 'statusCode']) {
          causeContext[key] = output.payload[key];
        }
      }
      const attempt = cause.attempt;
      if (attempt) {
        causeContext.method = attempt.method;
        causeContext.path = attempt.path
          ? attempt.path.replace(TOKENREGEX, FILTERED)
          : null;
      }
      scope.setContext('cause', causeContext);
    }

    if (request) {
      // Merge the request scope into the temp scope
      Hoek.merge(scope, request.sentryScope);
    }
    Sentry.captureException(err);
  });
}