Wouldn't it be nice to get a text message if one of your websites is down? In this tutorial, I'll show you how to build a minimum viable uptime monitoring service.
git clone https://github.com/unshift/uptime-monitoring.git
cd uptime-monitoring
npm install
Edit .env:
TWILIO_ACCOUNT_SID={YOUR TWILIO ACCOUNT SID}
TWILIO_AUTH_TOKEN={YOUR TWILIO AUTH TOKEN}
TWILIO_NUMBER={YOUR TWILIO REGISTERED NUMBER}
RECIPIENT_NUMBER={YOUR NUMBER}
cd uptime-monitoring
heroku create
heroku buildpacks:set https://github.com/heroku/heroku-buildpack-nodejs#v107
heroku config:set TWILIO_ACCOUNT_SID={YOUR TWILIO ACCOUNT SID}
heroku config:set TWILIO_AUTH_TOKEN={YOUR TWILIO AUTH TOKEN}
heroku config:set TWILIO_NUMBER={YOUR TWILIO REGISTERED NUMBER}
heroku config:set RECIPIENT_NUMBER={YOUR NUMBER}
git remote -v ## check to make sure you've got the right heroku remote
git push heroku master
We'll use Node. I'll assume that node and npm are installed on your system.
Let's start from scratch.
mkdir uptime-monitoring && cd uptime-monitoring
npm init
touch index.js
First, let's install isomorphic-fetch, twilio, and node-schedule:
npm i twilio isomorphic-fetch node-schedule --save
Why these modules?
We'll use:
require('isomorphic-fetch')
const sites = [
'http://www.example.com'
]
const run = async () => {
for(let i in sites) {
var resp = await fetch(url).catch(err => { return err })
if(resp && resp.status >= 200 && resp.status < 300) {
// Site is OK
} else {
// Site is down; send an SMS
}
}
}
run() // call run() to test things out
The above snippet makes a fetch request to the URIs in sites.
We'll use async/await syntax, but you could just as well use then.
If you don't want to use a for() loop, you could use this syntax:
var responses = await Promise.all(sites.map(site => {
// Map needs to be wrapped in Promise.all()
// Don't forget that await can only be used if the enclosing function is async
return fetch(site)
}))
First, we need to require the twilio node module. Sending an SMS is easy.
var twilio = require('twilio');
const accountSid = ''; // from your twilio dashboard
const authToken = ''; // from your twilio dashboard
var twilioClient = new twilio(accountSid, authToken);
const sendMessage = async () => {
// to is the recipient phone number.
// from is the number you registered with twilio to send text messages.
// body is the actual message to send.
// Note: to and from must be formatted with the country code: +12345678910.
return await twilioClient.messages.create({body, to, from})
}
Create an account at twilio.com. Once you register, you'll see your ACCOUNT SID and AUTH TOKEN in your dashboard. Lastly, you'll need to buy a phone number (the first one is free) to dispatch the text messages.
What we have so far:
We can use node-schedule to execute our function at regular intervals. Node schedule accepts a crontab and a callback as follows:
const schedule = require('node-schedule')
var j = schedule.scheduleJob('*/5 * * *', () => {
// function to execute every 5 minutes
})
Putting everything together, we have:
const schedule = require('node-schedule')
const twilio = require('twilio')
require('isomorphic-fetch')
const sites = ['http://www.example.com']
const config = {
accountSid: '',
authToken: '',
twilioNumber: '',
recipientNumber: ''
}
var twilioClient = new twilio(config.accountSid, config.authToken);
const sendMessage = async (site) => {
return await twilioClient.messages.create({
body: `${site} is down!`,
to: config.recipientNumber,
from: config.twilioNumber
})
}
const run = async () => {
for(let i in sites) {
var resp = await fetch(sites[i]).catch(err => { return err })
if(resp && resp.status >= 200 && resp.status < 300) {
// Site is OK
console.log(`${sites[i]} is OK`)
} else {
// Site is down; send an SMS
var msgResp = await sendMessage(sites[i])
console.log(`${sites[i]} is Down. SMS status: ${msgResp.status}`)
}
}
}
if(process.env.NODE_ENV !== 'production') {
run()
} else {
schedule.scheduleJob('*/5 * * * *', () => { run() })
}
Testing things out:
node index.js
Here's a link to the github repo.