Skip to content

Instantly share code, notes, and snippets.

@pulkitsinghal
Last active February 8, 2019 18:00
Show Gist options
  • Save pulkitsinghal/82e659ca4b56bc1b4b2c to your computer and use it in GitHub Desktop.
Save pulkitsinghal/82e659ca4b56bc1b4b2c to your computer and use it in GitHub Desktop.
Loopback: How to log any errors via a global error handler?

Pitfalls

The REST adapter for strong-remoting sets up its own error handler! So you cannot accomplish this for REST API related calls by replacing:

  1. app.use(loopback.errorHandler()); in server/server.js
  2. or, loopback#errorHandler in middleware.json

So don't waste your time there.

Deeper Understanding

Part 1

The REST adapter's error handler is wired here:

  // Use our own error handler to make sure the error response has
  // always the format expected by remoting clients.
  root.use(RestAdapter.errorHandler(this.remotes.options.errorHandler));

The code for the error handler itself can be found here:

RestAdapter.errorHandler = function(options) {...};

If you look at the source for the default error handler, you may wonder, why not just turn on logging:

var debug = require('debug')('strong-remoting:rest-adapter');

via DEBUG=strong-remoting:rest-adapter as it already logs the error stack and the path:

debug('Error in %s %s: %s', req.method, req.url, err.stack);

My reason for not doing so was because there are a whole lot of other verbose logs that fall under strong-remoting:rest-adapter namespace that end up cluttering the logs with a 100 lines when all we want is 1.

Part 2

If we specify a custom error handler AND in our handler we choose to pass control along via next(), then the loopback framework will courteously chain the default handler as well!

options.handler(err, req, res, defaultHandler);

So we can choose to do very little work in our own custom error handler and leave the remaining work to loopback's default handler.

Solution

Configuration based approach

Add the error handler callback function to server/config.js or server/config.<env>.js as follows:

module.exports = {
  remoting: {
    errorHandler: {
      handler: function(err, req, res, next) {
        // custom error handling logic
        var log = require('debug')('server:rest:errorHandler'); // you may choose to use a different namespace or logging mechanism
        log(req.method, req.originalUrl, res.statusCode, err);

        next(); // let the default error handler (RestAdapter.errorHandler) run next
      }
    }
  }
};

Code based approach

https://github.com/strongloop/loopback-faq-middleware#how-do-you-create-a-custom-error-message-for-all-errors

// at the very bottom of server.js
app.get('remoting').errorHandler = {
  handler: function(error, req, res, next) {
    var log = require('debug')('server:rest:errorHandler');
    if (error instanceof Error) {
      log('Error in %s %s: errorName=%s errorMessage=%s \n errorStack=%s',
        req.method, req.url, error.name, error.message, error.stack);
    }
    else {
      log(req.method, req.originalUrl, res.statusCode, error);
    }
    next(); /* let the default error handler (RestAdapter.errorHandler) run next */
  },
  disableStackTrace: true
};

References

  1. Instructions for customising REST errorHandler - issue #688
  2. https://docs.strongloop.com/display/public/LB/Environment-specific+configuration#Environment-specificconfiguration-CustomizingRESTerrorhandling
@shaharz
Copy link

shaharz commented Apr 22, 2016

Thanks! My two cents: server/config.js didn't work for me. Docs suggest server/config.local.js which did.

@dohjon
Copy link

dohjon commented May 22, 2016

Thanks! Great explanation and examples.

@bamoo456
Copy link

Thanks a lot

@yotamsha
Copy link

yotamsha commented Aug 7, 2016

Thanks!

@virendra656
Copy link

Is there any way that i can merge other object with error object?

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