Fully Automating Chrisfrew.in Productions - Part 2 of ??? - Building a Node.js Server Monitor
Posted on May 11, 2018
Node.js Server Monitor
In my attempt to automate my suite of websites, I wanted to build a simple Node.js server that monitors all my live sites, and sends me an email. Basically the process is simply:
- 'cron' job that every 30 seconds to ping all my websites
- Check for 200 response from each, if not send email
- If an even greater problem is found, i.e., the site doesn't even return a 4** code, also send an email
- A 'reactive' monitor - that is, don't just send a mail when there are problems, try to spool up the server again and log if there is a failure!
To accomplish this I utilized just three Node.js libraries:
http
, to request the various sites I controlnode-schedule
, to create a cron-like checknodemailer
, a fantastic easy-to-use bare bones emailer, we'll send an email when there is a non 2** HTTP response or simple a non-response error (see code below) (there is a great medium post on an about 20ish liner in Node.js to get started, and the setting in gmail you have to change)
Obviously this can be developed into a much more complex monitor, but for now I am happy as to how it runs.
Improvements
A few things I would like to improve with this Server:
- Control the
const
array from somwehere else, perhaps a management GUI where I can maintain sites - A global log class that could also be used in my Chrisfrew.in Productions Twitter Bot (coming soon in another post)
- Increasing the information and complexity of what is sent in the emails?
Code
As always, the most up-to-date code will be on GitHub, but as of this post, the full index.js
code is as follows:
const schedule = require('node-schedule');const http = require("http");const nodemailer = require('nodemailer');const aSitesToTrack = ["http://chrisfrew.in", "http://nlp-champs.chrisfrew.in", "http://sirenapparel.us", "http://chrisfrewin.design", "http://seelengefluester-tirol.com", "http://xn--seelengeflster-tirol-yec.com"];let transporter = nodemailer.createTransport({service: 'gmail',auth: {user: 'chrisfrew.in.productions@gmail.com',pass: process.env.CHRISFREW_IN_PRODUCTIONS_GMAIL_PASSWORD}});let mailOptions = {from: 'chrisfrew.in.productions@gmail.com', // sender addressto: 'frewin.christopher@gmail.com' // list of receivers};// 1. cron this program every 30 secondsvar j = schedule.scheduleJob('30 * * * * *', function() {pingSites();});// 2. loop through all sitesfunction pingSites() {aSitesToTrack.forEach((sSite) => {http.get(sSite, function (res) {// make sure response is 200const { statusCode } = res; // destructure responsE integerconst sStatusCode = statusCode.toString(); // convert to stringif (!sStatusCode.charAt(0) === "2") { // first digit should be a 2mailOptions.subject = 'Site Monitor Chrisfrew.in Productions: Non 2** HTTP Status code'; // Subject linemailOptions.html = "The site <b>" + sSite + "</b> is returning a 404 HTTP error!"; // plain text bodysendEmail();console.log("404 email sent");}}).on('error', function(e) {// major errormailOptions.subject = 'Site Monitor Chrisfrew.in Productions: Site non-responsive'; // Subject linemailOptions.html = "The site <b>" + sSite + "</b> is non responsive! (Not even a 404 response was found!)"; // plain text bodysendEmail();console.log("Error email sent");});console.log("Site ping of " + sSite + " complete.");});}// 3. send email if there was errorfunction sendEmail() {transporter.sendMail(mailOptions, function (err, info) {if(err)console.log(err)elseconsole.log(info);});}