Skip to content
Browse files

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
  • Loading branch information...
1 parent ea7a695 commit 169c82acfc6f833a8822048fcf7cc37a4e1b19dd @BerkeleyTrue BerkeleyTrue committed
Showing with 72 additions and 2 deletions.
  1. +2 −1 package.json
  2. +57 −0 pm2Start.js
  3. +13 −1 server/middlewares/keymetrics.js
View
3 package.json
@@ -31,11 +31,11 @@
"babel-core": "^6.3.26", "babel-core": "^6.3.26",
"babel-eslint": "^4.1.4", "babel-eslint": "^4.1.4",
"babel-loader": "^6.2.1", "babel-loader": "^6.2.1",
- "babel-register": "^6.3.0",
"babel-plugin-add-module-exports": "^0.1.2", "babel-plugin-add-module-exports": "^0.1.2",
"babel-preset-es2015": "^6.3.13", "babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13", "babel-preset-react": "^6.3.13",
"babel-preset-stage-0": "^6.3.13", "babel-preset-stage-0": "^6.3.13",
+ "babel-register": "^6.3.0",
"body-parser": "^1.13.2", "body-parser": "^1.13.2",
"chai-jquery": "^2.0.0", "chai-jquery": "^2.0.0",
"cheerio": "~0.19.0", "cheerio": "~0.19.0",
@@ -94,6 +94,7 @@
"merge-stream": "^1.0.0", "merge-stream": "^1.0.0",
"method-override": "^2.3.0", "method-override": "^2.3.0",
"moment": "^2.10.2", "moment": "^2.10.2",
+ "moment-timezone": "^0.5.0",
"mongodb": "^2.0.33", "mongodb": "^2.0.33",
"morgan": "^1.6.1", "morgan": "^1.6.1",
"node-uuid": "^1.4.3", "node-uuid": "^1.4.3",
View
57 pm2Start.js
@@ -1,8 +1,22 @@
require('dotenv').load(); require('dotenv').load();
var pm2 = require('pm2'); var pm2 = require('pm2');
+var nodemailer = require('nodemailer');
+var moment = require('moment-timezone');
+var _ = require('lodash');
+
var instances = process.env.INSTANCES || 1; var instances = process.env.INSTANCES || 1;
var serverName = process.env.SERVER_NAME || 'server'; var serverName = process.env.SERVER_NAME || 'server';
var maxMemory = process.env.MAX_MEMORY || '390M'; 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.connect(function() {
pm2.start({ pm2.start({
@@ -22,3 +36,46 @@ pm2.connect(function() {
pm2.disconnect(); 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
14 server/middlewares/keymetrics.js
@@ -4,5 +4,17 @@ export default function keymetrics() {
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
return (err, req, res, next) => next(err); 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));
+ };
} }

0 comments on commit 169c82a

Please sign in to comment.
Something went wrong with that request. Please try again.