node.js - PM2 log uncaught exceptions to third-party service (as Logentries) - javascript

I'm using pm2 (https://github.com/Unitech/pm2) in my node.js project. Also I'm sending logs of errors of the app in Logentries (https://logentries.com).
I wonder is it possible to log uncaught exceptions from the app (when something fails badly and pm2 restarts the app for example)? I know that using process.on('uncaughtException') is bad practice so would like to hear some suggestions.
Thanks!

Where did you read that process.on('uncaughtException') is a bad practice?
As long as you exit the process after logging the exception I don't see what's bad, here is an example:
process.on('uncaughtException', function(e) {
console.error('Ouch, an unhandled exception');
//I like using new Error() for my errors (1)
console.error(e instanceof Error ? e.message : e);
process.exit(1);
});
(1): Javascript Error reference
Edit
pm2-interface is now deprecated, use require('pm2') instead. You will be able to do exactly the same as below by using bus system events.
An alternative with pm2 is to use pm2-interface and listening to the process:exit or process:exception events:
var ipm2 = require('pm2-interface')();
ipm2.on('ready', function() {
console.log('Connected to pm2');
ipm2.bus.on('process:exception', function(data){
console.log(data.pm2_env.name + 'had an exception');
});
});
This is really usefull when managing more than one process through a monitoring process.
You might want to check the blog post on how to build a custom pm2 logger. It can give you some ideas about monitoring processes through pm2-interface.

Related

Detect internet connection in Electron

Our Electron app needs some configuration files and usually downloads them from our server. In case the client is offline, we don't want him to see any error messages. We are using Electron Download Manager to get the files.
This is how we request the files
try{
DownloadManager.bulkDownload({
urls: links
}, function (error, finished, errors) {
if (error) {
console.log("ERROR: Encountered error during config file download!");
console.log("Finished Files: " + finished);
console.log("Errors: " + errors);
return;
}
console.log("Finished loading all configuration files.");
});
} catch (err){
online_status = false;
console.log("Couldn't get online configuration. Starting app as offline.");
}
With this code the error Uncaught Exception: Error: net::ERR_ADDRESS_UNREACHABLE is thrown, when not connected to the internet.
I tried implementing the official event detection from Electron but as they state:
Such as in cases where the computer is running a virtualization
software that has virtual ethernet adapters that are always
“connected.” Therefore, if you really want to determine the internet
access status of Electron, you should develop additional means for
checking.
Then I went on trying just to ping the server like in this thread but this doesn't work at all for me, it's possible that it doesn't work anymore.
This is a bug in Electron Download Manager, documented in an GitHub Issue like #JeffRSon stated. A pull request is ready for a merge but not merged yet (posted 06.06.2019).
I hope this helps you. I will update this question if it get's merged and works.

Why would a NodeJS/restify server *rarely* report EPERM on accept?

I'm running a restify server in NodeJS. On very rare occasions, on the order of 0.05% of HTTPS requests cause net.js to report the following error:
Error: accept EPERM
at exports._errnoException (util.js:742:11)
at TCP.onconnection (net.js:1280:24)
There is nothing special about the HTTP requests. Before this error is reported, the server may have serviced thousands of requests and even responded to dozens of identical requests. I have not been able to find any information about why a server might generate an EPERM error for a socket that has been successfully accepting connections for several hours.
By the way, this error occurs outside of any execution context of our source code. So it's not as if the EPERM is about our code accessing a file or performing some other system call. The EPERM is happening deep within the NodeJS TCP code when the new request arrives and before our code is invoked.
At first, when the error occurred it would cause NodeJS to terminate. So then I added code to catch application-level exceptions:
process.on("uncaughtException", onUncaughtException );
But since I don't know why this error is happening, it's not at all clear what is the recovery process.
Not sure if it will matter, but here is most of the code relevant to starting up the restify service:
var restify = require("restify");
// skipping some other init code
// configuration data is read from a JSON file
var serverOptions = {
name: configuration.server.name,
version: configuration.server.version,
formatters: {
"application/json": jsonResponseFormatter,
"text/html": textResponseFormatter
},
serverOptions.key: fs.readFileSync(configuration.server.sslKey),
serverOptions.cert: fs.readFileSync(configuration.server.sslCert)
}
var server = restify.createServer( serverOptions );
// skipping middleware inits and URL registrations
server.listen(
configuration.server.port, // using HTTPS 443
configuration.server.serverip );
By the way, we are running an old version of NodeJS: v0.11.13. My long-term plan is to upgrade to the latest stable version, but we may not be able to update for a few months.
Let me leave my solution here in case anyone else stumbles across this same problem in the future.
Technically, I did not discover why this error was occurring, but I did find out how to handle the error condition successfully: trap and release. The error must be trapped at the application level because it is being generated deep within net.js outside any try-catch context of my source code. So if I don't trap it, then it will crash my application. But the error is non-fatal and it appears that it can be safely ignored. In testing, the socket continued to receive new connections even after this error occurred.
process.on("uncaughtException", onUncaughtException );
function onUncaughtException(error) {
// put some code here to log the error occurrence, then ...
if( error.code==="EPERM" && error.syscall==="accept" ) {
// non-fatal error: do nothing; just ignore this error
}
else {
// handle other application errors here
}
}
So while it might still be interesting to know why a server socket can occasionally have an EPERM error, for now I'm satisfied knowing the proper way to handle the error when it occurs.
$ man 2 accept
...
In addition, Linux accept() may fail if:
EPERM Firewall rules forbid connection.
To be honest, I'm not entirely sure what type of firewall rule would cause this error, all I can think of is that you may have a rule that allows incoming connections from a particular client but disallows outgoing data to that client's IP/network/port/...

How can I catch an EHOSTDOWN socket error when creating an http request with iojs?

I have a simple iojs http server which communicates with another http backend on my development machine. Now my ip has changed and the backend request won't work due to a wrong ip. I have (or at least thought so) error management in place however the server crashes in some situations due to an unhandled exception:
When doing 2 subsequent requests the first one "hangs" and then the second request crashes the server:
events.js:141
throw er; // Unhandled 'error' event
^
Error: connect EHOSTDOWN 192.168.1.11:80 - Local (192.168.1.10:54125)
at Object.exports._errnoException (util.js:846:11)
at exports._exceptionWithHostPort (util.js:869:20)
at connect (net.js:840:14)
at lookupAndConnect (net.js:933:5)
at Socket.connect (net.js:902:5)
at Agent.exports.connect.exports.createConnection (net.js:61:35)
at Agent.createSocket (_http_agent.js:177:16)
at Agent.addRequest (_http_agent.js:147:23)
at new ClientRequest (_http_client.js:132:16)
at Object.exports.request (http.js:30:10)
The error in question won't trigger backRequest.on("error", errFn) and it is not a standard error as in function(err, response, body). It can't be catched using try...catch.
How can i catch and gracefully handle this error?
I have dugged a bit into net.js/http.js. When emitting a socket error manually:
backendRequest.on("socket", function(socket) {
socket.emit("error", "DIE!");
});
it is handled by the normal error handler. The EHOSTDOWN error however is not. The reason for this seems to be that the socket error handler is only installed on the next tick after Socket.connect() (see https://github.com/joyent/node/blob/master/lib/_http_client.js#L498).
"My" error however is triggered directly upon connect() (must have something to do with the first connection still trying to find the host).
I can gracefully catch that error using a custom Agent.createConnection:
var socket = net.createConnection(options);
// install error handler immediately
socket.on("error", function(err) {
console.log("AHA", err);
});
return socket;
however that seems very verbose and bulky. Is that truly the best way to do that? The error seems to be not that special and seems to be unhandled in the core libs. Why is that so and why is the socket error handler only installed upon nextTick?
How would you properly catch that error? Is the agent the correct way?
A "full" example to play with can be found here: http://pastebin.com/jaCUPaHX
As pointed out by the commenters: It was a bug https://github.com/nodejs/io.js/pull/2054

node.js no interaction with child using child_process

All,
Trying to use node.js to isolate JS plugins created by others through the child_process API in node.js. I can't get the child process to interact with the parent, I get no errors running this code but the client can't send or receive messages, or write to console.log, so I assume the JS isn't running. I do get a console message that the debugger is running from both the parent as well as the client. Code is pretty much straight out of the node.js API docs so I'm not sure why this won't work. Perhaps something wrong with the Windows environment?
parent code:
var fork = require('child_process').fork;
console.log('Starting plugin server...');
var myChild = fork('client.js');
myChild.on('message', function (msg) {
console.log('PARENT got message:', msg)
});
myChild.send({ hello: 'world' });
client.js:
console.log("child");
process.on('message', function (msg) {
console.log('CHILD got message:', msg)
process.send({msg: 'Message receivd & resent from the child.'})
});
process.send({msg: 'Message from the child.'});
Output:
debugger listening on port 5858
Starting plugin server...
debugger listening on port 5858
I'm using Windows 8.1, visual studio 2013 pro with the new tools for node.js add-ins.
Any pointers appreciated. I'm new to node.js so possibly making a silly mistake??
I had problem with fork() on windows machines. Solution/workaround was with silent mode and logging. Here is link https://github.com/rogerwang/node-webkit/issues/1516

Bogart in NodeJS 0.6.10 on Windows Fails to start with message about 'sys' module

I've been learning how to use Bogart (v 0.3.38) under NodeJS (Windows, v 0.6.10), but I can't even get the basic "hello world!" to work, even though I think it must be a problem with the runtime and Bogart.
I'm using the example listed here just try to make it run. At the beginning, I got this message:
The "sys" module is now called "util". It should have a similar interface.
Then I went through all the files in the folder I'm creating the app and change "sys" to "util" in the require statement, and that, for while, got ride of the message above, but then I started getting a message that said that bogart could not access the isRouter property of undefined, that's when I decided to use the "Hello World" example to see if I was doing something wrong.
Now I get the "sys to util" message mentioned above, a message about the server starting on port 8080 and then a stacktrace:
The "sys" module is now called "util". It should have a similar interface.
Server running on port 8080
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: listen EACCES
at errnoException (net.js:646:11)
at Array.0 (net.js:732:28)
at EventEmitter._tickCallback (node.js:192:40)
Any clues of what might be wrong here?
As always, thanks in advance!
Found the problem: I had another application running on the same default port (8080) of Bogart, changed the port and everything worked.
In my case it was an error of mysql2 connection after update of MySQL config.

Categories

Resources