How to handle (i.e. log) errors in restify - node.js

In our restify app, when we pass an error to next, a generic 500 error is returned, which is all just fine. However, I need to also log the details of the error somewhere so that I know what happened.
Previously, I worked on an express application, and a centralized error-handling middleware gave us the ability to do any arbitrary code when receiving errors, like logging.
What's the "restify way" to centralizing the logging of error details? I do not want to sprinkle logging statements throughout the entire app.

A Restify server object emits an 'after' event once all other route handlers are done for a request. You can put your logging code in an 'after' event handler:
var svr = restify.createServer()
.get('/hello-world', hello_world_hndlr)
.on('after', function (req, resp, route, err) {
// logging here
})
.listen(SVR_PORT)

An alternative to listening to 'after' is listening to 'restifyError':
server.on('restifyError', (req, res, err, cb) => {
req.log.error(err)
return cb();
});

Related

How to gracefully handle "SASL: SCRAM-SERVER-FIRST-MESSAGE ..." in node-postgres?

I am using a Pool to resolve PoolClient objects out of. I know why the error is occuring, I just haven't provided a password, but irrespective I would like to handle the authentication error gracefully.
I tried:
Wrapping pool.connect() in try-catch
Adding on('error') to both Pool and PoolClient objects.
This is a well-known issue in the lib itself, and unfortunately it was not resolved ever- github issue reference
If you are using this in express, my suggestion will be to have a global error handler, which catches all unhandled exceptions, which should capture the bubbled up error. Something like this-
app.use(function (err, req, res, next) {
console.error(err.stack)
return res.status(500).send({err});
});

How can I log the express endpoint hit if the server crashes during an asynchronous callback?

I have an express service where a lot of my endpoints look like the following.
var express = require('express');
var router = express.Router();
router.get('/updateThisValue', (req, res) => {
let value = req['query'].value
try {
database.update(value, function() { // callback function on update
console.log(undefinedValue.undefined) // crash the server
})
} catch (err) {
// Log the error and other stuff
}
})
Looking at this code, if a database update is called, something will crash in the callback function and since there is no try-catch, the whole server should crash as well.
Right now, I am okay with the server crashing. The problem is that I would like to be able to log some debugging information in the callback before it crashes, namely the express endpoint hit and the parameters passed to it.
One solution is that I could just log every single endpoint hit, but the only problem with that is that the server starts to have very large logs. So we don't log endpoints hit by default. The frustration however is that recently an endpoint hit the server that did cause it crash and I'm still unsure what the actual endpoint hit and parameters passed to it where.
Basically, I want the server to still crash but at least I would be able to trace the endpoint hit and its parameters
Could this help: https://expressjs.com/en/guide/error-handling.html
Normally you would see the exception in the console or in the logs of your process manager (like pm2).

uncaughtException not catching thrown Errors

I'm working on an api in Node.js and learned about an option to give my errors one last look before crashing my app...(uncaughtException)
Note: I'm well read at this point on all the reasons some people don't like this feature, so please don't post those concerns here.
The problem I'm experiencing is this:
I create custom error classes for different pieces of code. for instance a Redis_Exception, which will get thrown in response to errors in my cache layer.
However the following does not bubble up to my uncaughtException function:
throw new Redis_Exception('Some error here');
Instead my app simply prints Redis_Exception: Some error here to the console. No stack trace as per usual.
Is there some reason that errors thrown in this manner would not bubble up to the top of my applications process?
An easier way around it, add a middleware with your express server with 4 arguments, 1st argument being the error. This will override the finalhandler handler.
app.use((err, req, res, next) => {
// Similar to uncaughtException handler
// Log error, maybe send it to central server
// Send Custom Log message maybe?
return res.send('Nice server error to user');
}
You should also still keep process.on('uncaughtException', fn); to handle any uncaught exceptions outside of the http request response pipeline.
Figured out what it is. For some reason express has decided to handle my errors for me.
In this file /node_modules/finalhandler/index.js on line 67 they basically handle any unhandled errors, which keeps uncaughtErrors from bubbling up to the top of the stack...or down to the bottom. Not really sure which direction this thing is facing.. :D
I added a line to that file and errors starting going through to my exception handler:
66 // unhandled error
67 if (err) {
68 throw err; //my line
I'm not sure how i'm going to move forward knowing this as I don't want to overwrite core functionality, but I'm armed with knowledge now.
UPDATE: After opening tickets with finalhandler and express I got back some info on how to override the default functionality.
The tickets I opened are:
https://github.com/pillarjs/finalhandler/issues/6
https://github.com/strongloop/express/issues/2707
Basically if you wrap your app object in a new http server you can override the last event with your own final function.
var express = require('express')
var http = require('http')
var app = express()
// declare things on app
var server = http.createServer(function (req, res) {
app(req, res, function (err) {
// this is your replacement for finalhandler
})
})
server.listen(3000)

How to render a 500 response after an uncaught error in express?

app.get('/', function(req, res) {
doSomethingAsync(function(err) {
throw new Error('some unexpected/uncaught async exception is thrown');
})
})
Possibly unhandled Error: some unexpected/uncaught async exception is thrown
at ...stacktrace...:95:9
From previous event:
at ...stacktrace...:82:6)
at ...stacktrace...:47:6)
at ...stacktrace...:94:18)
I have tried a bunch of domain middlewares however they all only work for express 3. I am currently on express 4.5 and I am wondering if express had changed that domain no longer works.
Currently, when an exception is thrown, the response basically hangs until a timeout.
assume the error you got is inside router or controller
put this in very end of your app configuration, before listening
app.use(function(err, req, res) {
res.status(err.status || 500);
// if you using view enggine
res.render('error', {
message: err.message,
error: {}
});
// or you can use res.send();
});
your app will catch any uncaught router error and will render "error" page
by the way do not forget to include "next" in your router Initialization
Edited
app.get('/', function(req, res, next) {
try {
signin(req.query.username, req.query.password, function(d){
if (d.success) {
req.session.user = d.data;
}
res.end(JSON.stringify(d));
});
} catch(e) {
next(e);
}
}
Hope it help
As you have found, trying to try/catch an asynchronous function doesn't work. Domains should work just fine in express 4 (or express 3, or straight http, whatever). I've never used any express middleware that attempts to implement domain handling though, so I can't really speak to how well they do or don't work.
I'd suggest just implementing domain handling on your own; it's not that bad. One of the better examples of using domains is right in node's documentation on domains (not the first bad example they show, the second, good one). I strongly recommend reading those docs.
The basic idea is pretty simple:
Create a domain
Add an error handler
Call domain.run(function() { ... }) putting the code you want inside the domain in that run callback.
An extremely simple (and very localized) example:
// This will alwas throw an error after 100ms, but it will still
// nicely return a 500 status code in the response.
app.get('/', function(req, res) {
var d = domain.create();
d.on('error', function(err) {
res.status(500).send(err.message);
});
d.run(function() {
setTimeout(function() {
throw new Error("some unexpected/uncaught async exception");
}, 100);
});
});
So, that will work and it might be enough for your case, but it's not the best solution (If you've read the docs, you might notice that it's pretty darn close to their bad example). The problem is (from the docs again):
By the very nature of how throw works in JavaScript, there is almost
never any way to safely "pick up where you left off", without leaking
references, or creating some other sort of undefined brittle state.
The best solution (as far as I'm aware anyway) is to do what's recommended in the node docs. The basic idea that they suggest is to use cluster (or something similar) to start multiple worker processes which run your web server from a master process. In each of those worker processes, setup a domain which will nicely send back a 500 status when an error is thrown and then exit. Then, in the master process, detect when a worker exits and simply start up a new one.
What that does is eliminate any problems with "picking up where you left off" by simply restarting the entire process when there's a thrown error, but only after handling it gracefully.
Putting an example of that in a SO answer is probably a bit much, but there really is a great example right in the node docs. If you haven't already, go take a look at it. :)

Handling error in node.js & express

I build a server with node.js and Express.
Everything works great, but in some cases the client sends invalid parameter, that I don't predict, and I don't handle with. The result of these requests that my server failed, and can't serve other requests.
For example, In one of my function. I have the next lines:
app.post("/getFile", function (req,res){
// some code...
fs.read(fd, buffer, 0, byteRoRead, start, function(err, bytesRead, buffer){
buffer.pipe(res);
})
})
Because the client sent incorrect start param, my server failed with the next error:
fs.js:457
binding.read(fd, buffer, offset, length, position, wrapper);
^
Error: Offset is out of bounds
So now I can fix it, but there is many other error that I can't predict, so I want to gives a client response of unexpected error, but I want that my server would still alive.
Express has built in error handling as a middleware. See http://expressjs.com/guide.html#error-handling for a more comprehensive guide but as an example:
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
This middleware would catch the error, log it to the console and return a 500 page to the user. This also will stop the server crashing. If you wanted to log the error, but still let the server crash add throw err; to the body of that function.
This is sometimes a good idea as you may not want the server to continue to serve requests if it is in some unexpected error state. Refer to http://shapeshed.com/uncaught-exceptions-in-node/ as a good brief guide on the subject. Also, see http://www.joyent.com/developers/node/design/errors for a more detailed discussion.

Resources