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 8ec11c6ca5..07ae1bfaa0 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 3b9ec6b74b..b0755e4b34 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 0902d6caab..183f670862 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)); + }; }