Add emailing on server exceptions

Keymetrics VC's are coming. They no longer let you see reported
errors or notify you on their free tier which renders the service
useless for us.

This will emailing you using mandrill with a stack trace and
context of the error when it receives it
pull/6430/head
Berkeley Martinez 2016-01-24 20:05:35 -08:00
parent ea7a695852
commit 169c82acfc
3 changed files with 72 additions and 2 deletions

View File

@ -31,11 +31,11 @@
"babel-core": "^6.3.26",
"babel-eslint": "^4.1.4",
"babel-loader": "^6.2.1",
"babel-register": "^6.3.0",
"babel-plugin-add-module-exports": "^0.1.2",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-stage-0": "^6.3.13",
"babel-register": "^6.3.0",
"body-parser": "^1.13.2",
"chai-jquery": "^2.0.0",
"cheerio": "~0.19.0",
@ -94,6 +94,7 @@
"merge-stream": "^1.0.0",
"method-override": "^2.3.0",
"moment": "^2.10.2",
"moment-timezone": "^0.5.0",
"mongodb": "^2.0.33",
"morgan": "^1.6.1",
"node-uuid": "^1.4.3",

View File

@ -1,8 +1,22 @@
require('dotenv').load();
var pm2 = require('pm2');
var nodemailer = require('nodemailer');
var moment = require('moment-timezone');
var _ = require('lodash');
var instances = process.env.INSTANCES || 1;
var serverName = process.env.SERVER_NAME || 'server';
var maxMemory = process.env.MAX_MEMORY || '390M';
var transportOptions = {
type: 'smtp',
service: 'Mandrill',
auth: {
user: process.env.MANDRILL_USER || false,
pass: process.env.MANDRILL_PASSWORD
}
};
var mailReceiver = process.env.MAIL_RECEIVER || false;
pm2.connect(function() {
pm2.start({
@ -22,3 +36,46 @@ pm2.connect(function() {
pm2.disconnect();
});
});
if (transportOptions.auth.user && mailReceiver) {
console.log('setting up mailer');
var transporter = nodemailer.createTransport(transportOptions);
var compiled = _.template(
'An error has occurred on server ' +
'<% name %>\n' +
'Stack Trace:\n\n\n<%= stack %>\n\n\n' +
'Context:\n\n<%= text %>'
);
pm2.launchBus(function(err, bus) {
if (err) {
return console.error(err);
}
console.log('event bus connected');
bus.on('process:exception', function(data) {
var text;
var stack;
var name;
try {
data.date = moment(data.at || new Date())
.tz('America/Los_Angeles')
.format('MMMM Do YYYY, h:mm:ss a z');
text = JSON.stringify(data, null, 2);
stack = data.data.stack;
name = data.process.name;
} catch (e) {
return e;
}
transporter.sendMail({
to: mailReceiver,
from: 'team@freecodecamp.com',
subject: 'Server exception',
text: compiled({ name: name, text: text, stack: stack })
});
});
});
}

View File

@ -4,5 +4,17 @@ export default function keymetrics() {
if (process.env.NODE_ENV !== 'production') {
return (err, req, res, next) => next(err);
}
return pmx.expressErrorHandler();
return (err, req, res, next) => {
if (res.statusCode < 400) { res.statusCode = 500; }
err.url = req.url;
err.component = req.url;
err.action = req.method;
err.params = req.body;
err.session = req.session;
err.username = req.user ? req.user.username : 'anonymous';
err.userId = req.user ? req.user.id : 'anonymous';
return next(pmx.notify(err));
};
}