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:
parent
c3af9db11a
commit
541bdace4b
56
config.yaml
56
config.yaml
@ -1,6 +1,7 @@
|
|||||||
settings:
|
settings:
|
||||||
title: "Status Page"
|
title: "Status Page"
|
||||||
logo: logo-192x192.png
|
url: "https://status-page.eidam.dev" # for Slack messages
|
||||||
|
logo: logo-192x192.png # image in ./public/ folder
|
||||||
daysInHistogram: 90
|
daysInHistogram: 90
|
||||||
|
|
||||||
allmonitorsOperational: "All Systems Operational"
|
allmonitorsOperational: "All Systems Operational"
|
||||||
@ -8,7 +9,9 @@ settings:
|
|||||||
monitorLabelOperational: "Operational"
|
monitorLabelOperational: "Operational"
|
||||||
monitorLabelNotOperational: "Not great not terrible"
|
monitorLabelNotOperational: "Not great not terrible"
|
||||||
monitorLabelNoData: "No data"
|
monitorLabelNoData: "No data"
|
||||||
|
dayInHistogramNoData: "No data"
|
||||||
|
dayInHistogramOperational: "All good"
|
||||||
|
dayInHistogramNotOperational: "Some checks failed"
|
||||||
|
|
||||||
monitors:
|
monitors:
|
||||||
- id: kiwi-com-homepage
|
- id: kiwi-com-homepage
|
||||||
@ -71,13 +74,6 @@ monitors:
|
|||||||
method: GET
|
method: GET
|
||||||
expectStatus: 403
|
expectStatus: 403
|
||||||
|
|
||||||
- id: google-com-2
|
|
||||||
name: Google.com
|
|
||||||
description: Google homepage
|
|
||||||
url: 'https://www.google.com'
|
|
||||||
method: GET
|
|
||||||
expectStatus: 200
|
|
||||||
|
|
||||||
- id: cf-workers-status-page-2
|
- id: cf-workers-status-page-2
|
||||||
name: This Workers Status Page project made public
|
name: This Workers Status Page project made public
|
||||||
description: /shrug
|
description: /shrug
|
||||||
@ -114,13 +110,6 @@ monitors:
|
|||||||
method: GET
|
method: GET
|
||||||
expectStatus: 403
|
expectStatus: 403
|
||||||
|
|
||||||
- id: google-com-22
|
|
||||||
name: Google.com
|
|
||||||
description: Google homepage
|
|
||||||
url: 'https://www.google.com'
|
|
||||||
method: GET
|
|
||||||
expectStatus: 200
|
|
||||||
|
|
||||||
- id: cf-workers-status-page-22
|
- id: cf-workers-status-page-22
|
||||||
name: This Workers Status Page project made public
|
name: This Workers Status Page project made public
|
||||||
description: /shrug
|
description: /shrug
|
||||||
@ -146,7 +135,7 @@ monitors:
|
|||||||
name: Hello World
|
name: Hello World
|
||||||
url: 'http://cnn.cn/'
|
url: 'http://cnn.cn/'
|
||||||
method: GET
|
method: GET
|
||||||
expectStatus: 200
|
expectStatus: 201
|
||||||
|
|
||||||
|
|
||||||
- id: eidam-dev-333
|
- id: eidam-dev-333
|
||||||
@ -156,13 +145,6 @@ monitors:
|
|||||||
method: GET
|
method: GET
|
||||||
expectStatus: 403
|
expectStatus: 403
|
||||||
|
|
||||||
- id: google-com-333
|
|
||||||
name: Google.com
|
|
||||||
description: Google homepage
|
|
||||||
url: 'https://www.google.com'
|
|
||||||
method: GET
|
|
||||||
expectStatus: 200
|
|
||||||
|
|
||||||
- id: cf-workers-status-page-333
|
- id: cf-workers-status-page-333
|
||||||
name: This Workers Status Page project made public
|
name: This Workers Status Page project made public
|
||||||
description: /shrug
|
description: /shrug
|
||||||
@ -206,13 +188,6 @@ monitors:
|
|||||||
method: GET
|
method: GET
|
||||||
expectStatus: 403
|
expectStatus: 403
|
||||||
|
|
||||||
- id: 25-google-com
|
|
||||||
name: Bing.com
|
|
||||||
description: Bing homepage
|
|
||||||
url: 'https://www.google.com'
|
|
||||||
method: GET
|
|
||||||
expectStatus: 200
|
|
||||||
|
|
||||||
- id: 25-cf-workers-status-page
|
- id: 25-cf-workers-status-page
|
||||||
name: This Workers Status Page project made public
|
name: This Workers Status Page project made public
|
||||||
description: /shrug
|
description: /shrug
|
||||||
@ -251,12 +226,6 @@ monitors:
|
|||||||
method: GET
|
method: GET
|
||||||
expectStatus: 403
|
expectStatus: 403
|
||||||
|
|
||||||
- id: 25-google-com-2
|
|
||||||
name: Google.com
|
|
||||||
description: Google homepage
|
|
||||||
url: 'https://www.google.com'
|
|
||||||
method: GET
|
|
||||||
expectStatus: 200
|
|
||||||
|
|
||||||
- id: 25-cf-workers-status-page-2
|
- id: 25-cf-workers-status-page-2
|
||||||
name: This Workers Status Page project made public
|
name: This Workers Status Page project made public
|
||||||
@ -294,13 +263,6 @@ monitors:
|
|||||||
method: GET
|
method: GET
|
||||||
expectStatus: 403
|
expectStatus: 403
|
||||||
|
|
||||||
- id: 25-google-com-22
|
|
||||||
name: Google.com
|
|
||||||
description: Google homepage
|
|
||||||
url: 'https://www.google.com'
|
|
||||||
method: GET
|
|
||||||
expectStatus: 200
|
|
||||||
|
|
||||||
- id: 25-cf-workers-status-page-22
|
- id: 25-cf-workers-status-page-22
|
||||||
name: This Workers Status Page project made public
|
name: This Workers Status Page project made public
|
||||||
description: /shrug
|
description: /shrug
|
||||||
@ -336,12 +298,6 @@ monitors:
|
|||||||
method: GET
|
method: GET
|
||||||
expectStatus: 403
|
expectStatus: 403
|
||||||
|
|
||||||
- id: 25-google-com-333
|
|
||||||
name: Google.com
|
|
||||||
description: Google homepage
|
|
||||||
url: 'https://www.google.com'
|
|
||||||
method: GET
|
|
||||||
expectStatus: 200
|
|
||||||
|
|
||||||
- id: 25-cf-workers-status-page-333
|
- id: 25-cf-workers-status-page-333
|
||||||
name: This Workers Status Page project made public
|
name: This Workers Status Page project made public
|
||||||
|
@ -24,6 +24,8 @@ export async function getEdgeProps() {
|
|||||||
if (x.metadata.operational === false) monitorsOperational = false
|
if (x.metadata.operational === false) monitorsOperational = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log(JSON.stringify(kvMonitorsMap))
|
||||||
|
|
||||||
// transform KV list to array of failed days
|
// transform KV list to array of failed days
|
||||||
const kvMonitorsFailedDaysArray = kvMonitorsFailedDays.map(x => {
|
const kvMonitorsFailedDaysArray = kvMonitorsFailedDays.map(x => {
|
||||||
return x.name
|
return x.name
|
||||||
@ -79,9 +81,13 @@ export default function Index({
|
|||||||
? config.settings.allmonitorsOperational
|
? config.settings.allmonitorsOperational
|
||||||
: config.settings.notAllmonitorsOperational}
|
: config.settings.notAllmonitorsOperational}
|
||||||
</div>
|
</div>
|
||||||
|
{typeof window !== 'undefined' ? (
|
||||||
<div className="black-text">
|
<div className="black-text">
|
||||||
checked {Math.round((Date.now() - kvLastUpdate) / 1000)} sec ago
|
checked {Math.round((Date.now() - kvLastUpdate) / 1000)} sec ago
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{config.monitors.map((monitor, key) => {
|
{config.monitors.map((monitor, key) => {
|
||||||
|
@ -15,22 +15,22 @@ export default function MonitorHistogram({
|
|||||||
key={`${monitor.id}-histogram`}
|
key={`${monitor.id}-histogram`}
|
||||||
className="horizontal flex histogram"
|
className="horizontal flex histogram"
|
||||||
>
|
>
|
||||||
{Array.from(Array(config.settings.daysInHistogram + 1).keys()).map(key => {
|
{Array.from(Array(config.settings.daysInHistogram).keys()).map(key => {
|
||||||
date.setDate(date.getDate() + 1)
|
date.setDate(date.getDate() + 1)
|
||||||
const dayInHistory = date.toISOString().split('T')[0]
|
const dayInHistogram = date.toISOString().split('T')[0]
|
||||||
const dayInHistoryKey = 'h_' + monitor.id + '_' + dayInHistory
|
const dayInHistogramKey = 'h_' + monitor.id + '_' + dayInHistogram
|
||||||
|
|
||||||
let bg = ''
|
let bg = ''
|
||||||
let dayInHistoryStatus = 'No data'
|
let dayInHistogramLabel = config.settings.dayInHistogramNoData
|
||||||
|
|
||||||
// filter all dates before first check, check the rest
|
// filter all dates before first check, check the rest
|
||||||
if (kvMonitor && kvMonitor.firstCheck <= dayInHistory) {
|
if (kvMonitor && kvMonitor.firstCheck <= dayInHistogram) {
|
||||||
if (!kvMonitorsFailedDaysArray.includes(dayInHistoryKey)) {
|
if (!kvMonitorsFailedDaysArray.includes(dayInHistogramKey)) {
|
||||||
bg = 'green'
|
bg = 'green'
|
||||||
dayInHistoryStatus = 'No outage recorded'
|
dayInHistogramLabel = config.settings.dayInHistogramOperational
|
||||||
} else {
|
} else {
|
||||||
bg = 'orange'
|
bg = 'orange'
|
||||||
dayInHistoryStatus = 'Some outages'
|
dayInHistogramLabel = config.settings.dayInHistogramNotOperational
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ export default function MonitorHistogram({
|
|||||||
<div key={key} className="hitbox">
|
<div key={key} className="hitbox">
|
||||||
<div
|
<div
|
||||||
className={`${bg} bar`}
|
className={`${bg} bar`}
|
||||||
data-tooltip={`${dayInHistory} - ${dayInHistoryStatus}`}
|
data-tooltip={`${dayInHistogram} - ${dayInHistogramLabel}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import config from '../../config.yaml'
|
||||||
|
|
||||||
export default function MonitorStatusLabel({ kvMonitorsMap, monitor }) {
|
export default function MonitorStatusLabel({ kvMonitorsMap, monitor }) {
|
||||||
let labelColor = 'grey'
|
let labelColor = 'grey'
|
||||||
let labelText = 'No data'
|
let labelText = 'No data'
|
||||||
@ -5,10 +7,10 @@ export default function MonitorStatusLabel({ kvMonitorsMap, monitor }) {
|
|||||||
if (typeof kvMonitorsMap[monitor.id] !== 'undefined') {
|
if (typeof kvMonitorsMap[monitor.id] !== 'undefined') {
|
||||||
if (kvMonitorsMap[monitor.id].operational) {
|
if (kvMonitorsMap[monitor.id].operational) {
|
||||||
labelColor = 'green'
|
labelColor = 'green'
|
||||||
labelText = 'Operational'
|
labelText = config.settings.monitorLabelOperational
|
||||||
} else {
|
} else {
|
||||||
labelColor = 'orange'
|
labelColor = 'orange'
|
||||||
labelText = 'Not great not terrible'
|
labelText = config.settings.monitorLabelNotOperational
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
import config from '../../config.yaml'
|
import config from '../../config.yaml'
|
||||||
|
|
||||||
import { setKV, getKVWithMetadata, gcMonitors, getKV } from './helpers'
|
import {
|
||||||
|
setKV,
|
||||||
|
getKVWithMetadata,
|
||||||
|
gcMonitors,
|
||||||
|
getKV,
|
||||||
|
notifySlack,
|
||||||
|
} from './helpers'
|
||||||
|
|
||||||
function getDate() {
|
function getDate() {
|
||||||
return new Date().toISOString().split('T')[0]
|
return new Date().toISOString().split('T')[0]
|
||||||
@ -14,7 +20,7 @@ export async function processCronTrigger(event) {
|
|||||||
method: monitor.method || 'GET',
|
method: monitor.method || 'GET',
|
||||||
redirect: monitor.followRedirect ? 'follow' : 'manual',
|
redirect: monitor.followRedirect ? 'follow' : 'manual',
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': 'cf-worker-status-page',
|
'User-Agent': config.settings.user_agent || 'cf-worker-status-page',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,22 +34,26 @@ export async function processCronTrigger(event) {
|
|||||||
firstCheck: kvState.metadata ? kvState.metadata.firstCheck : getDate(),
|
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 (
|
||||||
!kvState.metadata ||
|
!kvState.metadata ||
|
||||||
kvState.metadata.operational !== newMetadata.operational
|
kvState.metadata.operational !== newMetadata.operational
|
||||||
) {
|
) {
|
||||||
console.log('Saving changed state..')
|
console.log('Saving changed state..')
|
||||||
|
|
||||||
await setKV('s_' + monitor.id, null, newMetadata)
|
// first try to notify Slack in case fetch() or other limit is reached
|
||||||
|
if (typeof SECRET_SLACK_WEBHOOK_URL !== 'undefined') {
|
||||||
if (typeof SECRET_SLACK_WEBHOOK !== 'undefined') {
|
|
||||||
await notifySlack(monitor, newMetadata)
|
await notifySlack(monitor, newMetadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await setKV('s_' + monitor.id, null, newMetadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write daily status if monitor is not operational
|
||||||
if (!newMetadata.operational) {
|
if (!newMetadata.operational) {
|
||||||
// try to get failed daily status first as KV read is cheaper than write
|
// try to get failed daily status first as KV read is cheaper than write
|
||||||
const kvFailedDayStatusKey = 'h_' + monitor.id + '_' + getDate()
|
const kvFailedDayStatusKey = 'h_' + monitor.id + '_' + getDate()
|
||||||
|
console.log(kvFailedDayStatusKey)
|
||||||
const kvFailedDayStatus = await getKV(kvFailedDayStatusKey)
|
const kvFailedDayStatus = await getKV(kvFailedDayStatusKey)
|
||||||
|
|
||||||
// write if not found
|
// write if not found
|
||||||
@ -52,7 +62,6 @@ export async function processCronTrigger(event) {
|
|||||||
await setKV(kvFailedDayStatusKey, null)
|
await setKV(kvFailedDayStatusKey, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// save last check timestamp
|
// save last check timestamp
|
||||||
await setKV('lastUpdate', Date.now())
|
await setKV('lastUpdate', Date.now())
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import config from '../../config.yaml'
|
||||||
|
|
||||||
export async function getMonitors() {
|
export async function getMonitors() {
|
||||||
const monitors = await listKV('s_')
|
const monitors = await listKV('s_')
|
||||||
return monitors.keys
|
return monitors.keys
|
||||||
@ -73,18 +75,42 @@ export async function gcMonitors(config) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function notifySlack(monitor, metadata) {
|
export async function notifySlack(monitor, newMetadata) {
|
||||||
const blocks = [
|
const payload = {
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
color: newMetadata.operational ? '#36a64f' : '#f2c744',
|
||||||
|
blocks: [
|
||||||
{
|
{
|
||||||
type: 'section',
|
type: 'section',
|
||||||
text: {
|
text: {
|
||||||
type: 'mrkdwn',
|
type: 'mrkdwn',
|
||||||
text: `Some monitor is now in :this: status`,
|
text: `Monitor *${monitor.name}* changed status to *${
|
||||||
|
newMetadata.operational
|
||||||
|
? config.settings.monitorLabelOperational
|
||||||
|
: config.settings.monitorLabelNotOperational
|
||||||
|
}*`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
{
|
||||||
|
type: 'context',
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
type: 'mrkdwn',
|
||||||
|
text: `${
|
||||||
|
newMetadata.operational ? ':white_check_mark:' : ':x:'
|
||||||
|
} \`${monitor.method} ${monitor.url}\` - :eyes: <${
|
||||||
|
config.settings.url
|
||||||
|
}|Status Page>`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
return fetch(SECRET_SLACK_WEBHOOK_URL, {
|
return fetch(SECRET_SLACK_WEBHOOK_URL, {
|
||||||
body: JSON.stringify({ blocks }),
|
body: JSON.stringify(payload),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user