Sentry-javascript: Sentry Express middleware and errorhandler not working with AWS Serverless Express

Created on 25 Aug 2018  路  13Comments  路  Source: getsentry/sentry-javascript

Raven errorhandler does not seem to capture the errors to Sentry when using it with AWS Serverless Express on AWS Lambda.

Following the sentry express example from https://docs.sentry.io/clients/node/integrations/express/ and then also the AWS Serverless Express example from https://github.com/awslabs/aws-serverless-express i get the following serverless handler.js file:

var app = require('express')();
var Raven = require('raven');
var awsServerlessExpress = require('aws-serverless-express')

// Must configure Raven before doing anything else with it
Raven.config(global.process.env.SENTRY_DSN).install();

// The request handler must be the first middleware on the app
app.use(Raven.requestHandler());

app.get('/', function mainHandler(req, res) {
    throw new Error('Broke!');
});

// The error handler must be before any other error middleware
app.use(Raven.errorHandler());

const server = awsServerlessExpress.createServer(app);

exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context);

Using:

"raven": "2.6.3",
"aws-serverless-express": "3.2.0",
"express": "4.16.3",

Most helpful comment

@ondrowan thanks for the repro case, it's very useful! We found out that the issue is with serverless wrapping everything in a domain, which we ourselves use in express middlewares (that's why it works with just node handler.js).
We are working on the fix as we speak.

All 13 comments

I just tested it locally very quickly (just add server.listen(3000) at the end, and it appears to work just fine:

screen shot 2018-08-27 at 16 28 29

So the issue is in the AWS itself. It's probably just freezing the thread what's stopping Sentry from sending an error. Please take a look at this post - https://blog.sentry.io/2018/06/20/how-droplr-uses-sentry-to-debug-serverless

@kamilogorek
I have managed to report errors manually with

Raven.captureException(error, (sendErr, eventId) => {
  callback(error);
});

as mentioned in the post you provided.

But I guess the middleware do not report the error this way with a callback. Is there anyway to get the middleware to do that so it will work?

Express middleware is pretty straightforward in our case.

Original:

  errorHandler: function() {
    var self = this;
    return function ravenErrorMiddleware(err, req, res, next) {
      var status =
        err.status ||
        err.statusCode ||
        err.status_code ||
        (err.output && err.output.statusCode) ||
        500;

      // skip anything not marked as an internal server error
      if (status < 500) return next(err);

      var eventId = self.captureException(err, {req: req});
      res.sentry = eventId;
      return next(err);
    };
  },

so you should just need to change the callback part, and use it as a middleware instead

app.use(function ravenErrorMiddleware(err, req, res, next) {
  var status =
    err.status ||
    err.statusCode ||
    err.status_code ||
    (err.output && err.output.statusCode) ||
    500;

  // skip anything not marked as an internal server error
  if (status < 500) return next(err);

  Raven.captureException(err, { req: req }, (sendErr, eventId) => {
    res.sentry = eventId;
    callback(err);
    next(err);
  });
});

@kamilogorek
Do I not miss anything by not calling self.captureException?

Not at all, it was self.captureException to preserve the context, but in case of Raven.captureException, Raven is already a correct one, so there's no need for this/self.

Closing due to inactivity. Please feel free to reopen if it's still relevant.

@kamilogorek I had similar issues, so I've prepared repo with code / steps to reproduce this: https://github.com/ondrowan/sentry-serverless-repro

@ondrowan thanks for the repro case, it's very useful! We found out that the issue is with serverless wrapping everything in a domain, which we ourselves use in express middlewares (that's why it works with just node handler.js).
We are working on the fix as we speak.

From version 4 of sentry-node the captureException function no longer accepts a callback so the solution described above is no longer working. Do you have any plans to re-add this?

@FredrikSeidl no, but we have a better solution for it now :)

https://docs.sentry.io/learn/draining/?platform=browser

The initially reported issue is resolved I guess, so let me close it. Feel free to ping me if this still needs to be reopened. Cheers!

@FredrikSeidl no, but we have a better solution for it now :)

https://docs.sentry.io/learn/draining/?platform=browser

@kamilogorek i'm trying to use sentry@4 with aws serverless - when exactly would I use this better solution? As far as I know it's not possible to know when the lambda will be shutdown - plus it seems silly to wait for an arbitrary amount of time for shutdown to allow sentry to do its thing - especially on expensive high memory/cpu lambda functions.

Was this page helpful?
0 / 5 - 0 ratings