From 169c82acfc6f833a8822048fcf7cc37a4e1b19dd Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Sun, 24 Jan 2016 20:05:35 -0800 Subject: [PATCH] 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 --- package.json | 3 +- pm2Start.js | 57 ++++++++++++++++++++++++++++++++ server/middlewares/keymetrics.js | 14 +++++++- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8ec11c6ca53..07ae1bfaa00 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pm2Start.js b/pm2Start.js index 3b9ec6b74bb..b0755e4b348 100644 --- a/pm2Start.js +++ b/pm2Start.js @@ -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 }) + }); + }); + }); +} diff --git a/server/middlewares/keymetrics.js b/server/middlewares/keymetrics.js index 0902d6caab7..183f6708628 100644 --- a/server/middlewares/keymetrics.js +++ b/server/middlewares/keymetrics.js @@ -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)); + }; }