Skip to content

Instantly share code, notes, and snippets.

@dusterio
Created Nov 15, 2019
Embed
What would you like to do?
Simple status page generation using Pingdom and AWS Lambda
const fetch = require("node-fetch")
const fs = require("fs")
const PINGDOM_API_KEY = process.env.PINGDOM_API_KEY
const AWS = require('aws-sdk')
const s3 = new AWS.S3({signatureVersion: 'v4'})
const checksConfig = [
{
id: 123,
title: 'event'
},
{
id: 456,
title: 'city'
}
]
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
exports.handler = async (event) => {
const now = new Date();
let render = template.replace('%update_timestamp%', now.toISOString())
let days = new Array(30)
// Always display the last 30 days
days = days.fill(0).map((day, index) => {
return new Date(now - index * 86400000)
}).reverse().map(day => {
return {
timestamp: Math.round(day.getTime() / 1000),
text: monthNames[day.getMonth()] + ' ' + day.getDate()
}
})
// Proper day/month labels for the charts
render = render.replace('%day_labels%', JSON.stringify(days.map(d => d.text)))
// Get actual data from Pingdom
let data = await fetch(`https://api.pingdom.com/api/3.1/checks`, {headers: {'Authorization': `Bearer ${PINGDOM_API_KEY}`}})
let checksOverview = await data.json()
// Go check by check and update current status and current value
checksOverview.checks.forEach(checkData => {
let config = checksConfig.find(config => config.id == checkData.id)
if (config) {
render = render.replace(`%${config.title}_status%`, ucWords(checkData.status))
render = render.replace(`%${config.title}_current_value%`, checkData.lastresponsetime)
}
})
// Normalize Pingdom data
for (let index = 0; index < checksConfig.length; index++) {
let data = await fetch(`https://api.pingdom.com/api/3.1/summary.performance/${checksConfig[index].id}?includeuptime=true&resolution=day&from=${monthAgoTimestamp}`, {headers: {'Authorization': `Bearer ${PINGDOM_API_KEY}`}})
let daysData = await data.json()
let totalUptime = 0
let totalDowntime = 0
daysData.summary.days.forEach(dayData => {
totalUptime = totalUptime + dayData.uptime
totalDowntime = totalDowntime + dayData.downtime
})
// Pingdom returned 30 periods with uptime value for each one, let's get a total
let uptime = ((totalUptime / (totalDowntime + totalUptime)) * 100).toFixed(4)
// Pingdom returned 30 average latency values, let's get one
let average = Math.round((daysData.summary.days.reduce((sum, day) => { return sum + day.avgresponse; }, 0)) / daysData.summary.days.length);
let chartData = days.map(day => {
let timeMatch = daysData.summary.days.find((data, i) => {
if (i == daysData.summary.days.length - 1) return day.timestamp >= data.starttime
let endTime = daysData.summary.days[i+1].starttime - 1;
return day.timestamp >= data.starttime && day.timestamp < endTime;
})
if (! timeMatch) return 0
return timeMatch.avgresponse
})
// Finally, let's put everything in the resulting HTML
render = render.replace(`%${checksConfig[index].title}_uptime%`, uptime)
render = render.replace(`%${checksConfig[index].title}_average%`, average)
render = render.replace(`%${checksConfig[index].title}_chart_data%`, JSON.stringify(chartData))
}
// Ready to upload the result
await s3.putObject({
Body: render,
Bucket: process.env.DESTINATION_BUCKET,
Key: "index.html",
CacheControl: "no-store",
ContentType: "text/html"
}).promise();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment