1
0
mirror of https://github.com/tormachris/cf-workers-status-page.git synced 2024-11-23 22:45:43 +01:00

chore(perf): save only failed days to KV storage

This commit is contained in:
Adam Janis 2020-11-11 23:39:54 +01:00
parent e85c5766a7
commit c3af9db11a
5 changed files with 63 additions and 45 deletions

View File

@ -1,7 +1,7 @@
settings: settings:
title: "Status Page" title: "Status Page"
logo: logo-192x192.png logo: logo-192x192.png
daysInHistory: 90 daysInHistogram: 90
allmonitorsOperational: "All Systems Operational" allmonitorsOperational: "All Systems Operational"
notAllmonitorsOperational: "Not All Systems Operational" notAllmonitorsOperational: "Not All Systems Operational"

View File

@ -13,7 +13,7 @@ import MonitorStatusLabel from '../src/components/monitorStatusLabel'
export async function getEdgeProps() { export async function getEdgeProps() {
// get KV data // get KV data
const kvMonitors = await getMonitors() const kvMonitors = await getMonitors()
const kvMonitorsDays = await getMonitorsHistory() const kvMonitorsFailedDays = await getMonitorsHistory()
const kvLastUpdate = await getLastUpdate() const kvLastUpdate = await getLastUpdate()
// prepare data maps for components // prepare data maps for components
@ -24,16 +24,16 @@ export async function getEdgeProps() {
if (x.metadata.operational === false) monitorsOperational = false if (x.metadata.operational === false) monitorsOperational = false
}) })
let kvMonitorsDaysMap = {} // transform KV list to array of failed days
kvMonitorsDays.forEach(x => { const kvMonitorsFailedDaysArray = kvMonitorsFailedDays.map(x => {
kvMonitorsDaysMap[x.name] = x.metadata.operational return x.name
}) })
return { return {
props: { props: {
config, config,
kvMonitorsMap, kvMonitorsMap,
kvMonitorsDaysMap, kvMonitorsFailedDaysArray,
monitorsOperational, monitorsOperational,
kvLastUpdate, kvLastUpdate,
}, },
@ -45,7 +45,7 @@ export async function getEdgeProps() {
export default function Index({ export default function Index({
config, config,
kvMonitorsMap, kvMonitorsMap,
kvMonitorsDaysMap, kvMonitorsFailedDaysArray,
monitorsOperational, monitorsOperational,
kvLastUpdate, kvLastUpdate,
}) { }) {
@ -104,12 +104,13 @@ export default function Index({
</div> </div>
<MonitorHistogram <MonitorHistogram
kvMonitorsDaysMap={kvMonitorsDaysMap} kvMonitorsFailedDaysArray={kvMonitorsFailedDaysArray}
monitor={monitor} monitor={monitor}
kvMonitor={kvMonitorsMap[monitor.id]}
/> />
<div className="horizontal flex between grey-text"> <div className="horizontal flex between grey-text">
<div>{config.settings.daysInHistory} days ago</div> <div>{config.settings.daysInHistogram} days ago</div>
<div>Today</div> <div>Today</div>
</div> </div>
</div> </div>

View File

@ -1,8 +1,13 @@
import config from '../../config.yaml' import config from '../../config.yaml'
export default function MonitorHistogram({ kvMonitorsDaysMap, monitor }) { export default function MonitorHistogram({
kvMonitorsFailedDaysArray,
monitor,
kvMonitor,
}) {
// create date and set date - daysInHistogram for the first day of the histogram
let date = new Date() let date = new Date()
date.setDate(date.getDate() - config.settings.daysInHistory) date.setDate(date.getDate() - config.settings.daysInHistogram)
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
return ( return (
@ -10,7 +15,7 @@ export default function MonitorHistogram({ kvMonitorsDaysMap, monitor }) {
key={`${monitor.id}-histogram`} key={`${monitor.id}-histogram`}
className="horizontal flex histogram" className="horizontal flex histogram"
> >
{Array.from(Array(config.settings.daysInHistory).keys()).map(key => { {Array.from(Array(config.settings.daysInHistogram + 1).keys()).map(key => {
date.setDate(date.getDate() + 1) date.setDate(date.getDate() + 1)
const dayInHistory = date.toISOString().split('T')[0] const dayInHistory = date.toISOString().split('T')[0]
const dayInHistoryKey = 'h_' + monitor.id + '_' + dayInHistory const dayInHistoryKey = 'h_' + monitor.id + '_' + dayInHistory
@ -18,11 +23,15 @@ export default function MonitorHistogram({ kvMonitorsDaysMap, monitor }) {
let bg = '' let bg = ''
let dayInHistoryStatus = 'No data' let dayInHistoryStatus = 'No data'
if (typeof kvMonitorsDaysMap[dayInHistoryKey] !== 'undefined') { // filter all dates before first check, check the rest
bg = kvMonitorsDaysMap[dayInHistoryKey] ? 'green' : 'orange' if (kvMonitor && kvMonitor.firstCheck <= dayInHistory) {
dayInHistoryStatus = kvMonitorsDaysMap[dayInHistoryKey] if (!kvMonitorsFailedDaysArray.includes(dayInHistoryKey)) {
? 'No outages' bg = 'green'
: 'Some outages' dayInHistoryStatus = 'No outage recorded'
} else {
bg = 'orange'
dayInHistoryStatus = 'Some outages'
}
} }
return ( return (

View File

@ -1,6 +1,10 @@
import config from '../../config.yaml' import config from '../../config.yaml'
import { setKV, getKV, getKVWithMetadata, gcMonitors } from './helpers' import { setKV, getKVWithMetadata, gcMonitors, getKV } from './helpers'
function getDate() {
return new Date().toISOString().split('T')[0]
}
export async function processCronTrigger(event) { export async function processCronTrigger(event) {
for (const monitor of config.monitors) { for (const monitor of config.monitors) {
@ -14,41 +18,43 @@ export async function processCronTrigger(event) {
}, },
} }
const response = await fetch(monitor.url, init) const checkResponse = await fetch(monitor.url, init)
const monitorOperational = response.status === (monitor.expectStatus || 200) const kvState = await getKVWithMetadata('s_' + monitor.id)
const kvMonitor = await getKVWithMetadata('s_' + monitor.id)
// metadata from monitor settings // metadata from monitor settings
const metadata = { const newMetadata = {
operational: monitorOperational, operational: checkResponse.status === (monitor.expectStatus || 200),
statusCode: response.status,
id: monitor.id, id: monitor.id,
firstCheck: kvState.metadata ? kvState.metadata.firstCheck : getDate(),
} }
// write current status if status changed or for first time // Write current status if status changed or for first time
if ( if (
!kvMonitor.metadata || !kvState.metadata ||
kvMonitor.metadata.operational !== monitorOperational kvState.metadata.operational !== newMetadata.operational
) { ) {
console.log('saving new results..') console.log('Saving changed state..')
await setKV('s_' + monitor.id, null, newMetadata)
if (typeof SECRET_SLACK_WEBHOOK !== 'undefined') { if (typeof SECRET_SLACK_WEBHOOK !== 'undefined') {
await notifySlack(metadata) await notifySlack(monitor, newMetadata)
} }
await setKV('s_' + monitor.id, null, metadata) if (!newMetadata.operational) {
} // try to get failed daily status first as KV read is cheaper than write
const kvFailedDayStatusKey = 'h_' + monitor.id + '_' + getDate()
// check day status, write only on not operational or for first time const kvFailedDayStatus = await getKV(kvFailedDayStatusKey)
const kvDayStatusKey =
'h_' + monitor.id + '_' + new Date().toISOString().split('T')[0] // write if not found
//console.log(kvDayStatusKey) if (!kvFailedDayStatus) {
const kvDayStatus = await getKV(kvDayStatusKey) console.log('Saving new failed daily status..')
await setKV(kvFailedDayStatusKey, null)
if (!kvDayStatus || (kvDayStatus && !monitorOperational)) { }
await setKV(kvDayStatusKey, null, metadata) }
} }
// save last check timestamp
await setKV('lastUpdate', Date.now()) await setKV('lastUpdate', Date.now())
} }
await gcMonitors(config) await gcMonitors(config)

View File

@ -4,7 +4,7 @@ export async function getMonitors() {
} }
export async function getMonitorsHistory() { export async function getMonitorsHistory() {
const monitorsHistory = await listKV('h_', 600) const monitorsHistory = await listKV('h_', 300)
return monitorsHistory.keys return monitorsHistory.keys
} }
@ -14,11 +14,13 @@ export async function getLastUpdate() {
export async function listKV(prefix = '', cacheTtl = false) { export async function listKV(prefix = '', cacheTtl = false) {
const cacheKey = 'list_' + prefix + '_' + process.env.BUILD_ID const cacheKey = 'list_' + prefix + '_' + process.env.BUILD_ID
const cachedResponse = await getKV(cacheKey)
if (cacheTtl && cachedResponse) { if (cacheTtl) {
const cachedResponse = await getKV(cacheKey)
if (cachedResponse) {
return JSON.parse(cachedResponse) return JSON.parse(cachedResponse)
} }
}
let list = [] let list = []
let cursor = null let cursor = null
@ -30,7 +32,7 @@ export async function listKV(prefix = '', cacheTtl = false) {
} while (!res.list_complete) } while (!res.list_complete)
if (cacheTtl) { if (cacheTtl) {
await setKV(cacheKey, JSON.stringify({ keys: list }), null, 600) await setKV(cacheKey, JSON.stringify({ keys: list }), null, cacheTtl)
} }
return { keys: list } return { keys: list }
} }