mirror of
				https://github.com/tormachris/cf-workers-status-page.git
				synced 2025-11-04 04:46:24 +01:00 
			
		
		
		
	feat: collect avg response time by default
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/deploy.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/deploy.yml
									
									
									
									
										vendored
									
									
								
							@@ -5,6 +5,8 @@ on:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
  repository_dispatch:
 | 
			
		||||
  schedule:
 | 
			
		||||
    - cron: '0 0 1 * *'
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  deploy:
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ settings:
 | 
			
		||||
  url: 'https://status-page.eidam.dev' # used for Slack messages
 | 
			
		||||
  logo: logo-192x192.png # image in ./public/ folder
 | 
			
		||||
  daysInHistogram: 90 # number of days you want to display in histogram
 | 
			
		||||
  collectResponseTimes: false # experimental feature, enable only for <5 monitors or on paid plans
 | 
			
		||||
  collectResponseTimes: true # collects avg response times from CRON locations
 | 
			
		||||
 | 
			
		||||
  allmonitorsOperational: 'All Systems Operational'
 | 
			
		||||
  notAllmonitorsOperational: 'Not All Systems Operational'
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ const accountId = process.env.CF_ACCOUNT_ID
 | 
			
		||||
const namespaceId = process.env.KV_NAMESPACE_ID
 | 
			
		||||
const apiToken = process.env.CF_API_TOKEN
 | 
			
		||||
 | 
			
		||||
const kvPrefix = 's_'
 | 
			
		||||
const kvMonitorsKey = 'monitors_data_v1_1'
 | 
			
		||||
 | 
			
		||||
if (!accountId || !namespaceId || !apiToken) {
 | 
			
		||||
  console.error(
 | 
			
		||||
@@ -15,7 +15,7 @@ if (!accountId || !namespaceId || !apiToken) {
 | 
			
		||||
  process.exit(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getKvMonitors(kvPrefix) {
 | 
			
		||||
async function getKvMonitors(kvMonitorsKey) {
 | 
			
		||||
  const init = {
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
@@ -24,27 +24,29 @@ async function getKvMonitors(kvPrefix) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const res = await fetch(
 | 
			
		||||
    `https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/keys?limit=100&prefix=${kvPrefix}`,
 | 
			
		||||
    `https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${kvMonitorsKey}`,
 | 
			
		||||
    init,
 | 
			
		||||
  )
 | 
			
		||||
  const json = await res.json()
 | 
			
		||||
  return json.result
 | 
			
		||||
  return json
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function deleteKvBulk(keys) {
 | 
			
		||||
async function saveKVMonitors(kvMonitorsKey, data) {
 | 
			
		||||
  const init = {
 | 
			
		||||
    method: 'PUT',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
      Authorization: `Bearer ${apiToken}`,
 | 
			
		||||
    },
 | 
			
		||||
    method: 'DELETE',
 | 
			
		||||
    body: JSON.stringify(keys),
 | 
			
		||||
    body: JSON.stringify(data),
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return await fetch(
 | 
			
		||||
    `https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/bulk`,
 | 
			
		||||
  const res = await fetch(
 | 
			
		||||
    `https://api.cloudflare.com/client/v4/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${kvMonitorsKey}`,
 | 
			
		||||
    init,
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadConfig() {
 | 
			
		||||
@@ -53,26 +55,37 @@ function loadConfig() {
 | 
			
		||||
  return JSON.parse(config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
getKvMonitors(kvPrefix)
 | 
			
		||||
getKvMonitors(kvMonitorsKey)
 | 
			
		||||
  .then(async (kvMonitors) => {
 | 
			
		||||
    let stateMonitors = kvMonitors
 | 
			
		||||
 | 
			
		||||
    const config = loadConfig()
 | 
			
		||||
    const monitors = config.monitors.map((key) => {
 | 
			
		||||
    const configMonitors = config.monitors.map((key) => {
 | 
			
		||||
      return key.id
 | 
			
		||||
    })
 | 
			
		||||
    const kvState = kvMonitors.map((key) => {
 | 
			
		||||
      return key.name
 | 
			
		||||
    })
 | 
			
		||||
    const keysForRemoval = kvState.filter(
 | 
			
		||||
      (x) => !monitors.includes(x.replace(kvPrefix, '')),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    if (keysForRemoval.length > 0) {
 | 
			
		||||
      console.log(
 | 
			
		||||
        `Removing following keys from KV storage as they are no longer in the config: ${keysForRemoval.join(
 | 
			
		||||
          ', ',
 | 
			
		||||
        )}`,
 | 
			
		||||
      )
 | 
			
		||||
      await deleteKvBulk(keysForRemoval)
 | 
			
		||||
    Object.keys(stateMonitors.monitors).map((monitor) => {
 | 
			
		||||
      // remove monitor data from state if missing in config
 | 
			
		||||
      if (!configMonitors.includes(monitor)) {
 | 
			
		||||
        delete stateMonitors.monitors[monitor]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // delete dates older than config.settings.daysInHistogram
 | 
			
		||||
      let date = new Date()
 | 
			
		||||
      date.setDate(date.getDate() - config.settings.daysInHistogram)
 | 
			
		||||
      date.toISOString().split('T')[0]
 | 
			
		||||
      const cleanUpDate = date.toISOString().split('T')[0]
 | 
			
		||||
 | 
			
		||||
      Object.keys(stateMonitors.monitors[monitor].checks).map((checkDay) => {
 | 
			
		||||
        if (checkDay < cleanUpDate) {
 | 
			
		||||
          delete stateMonitors.monitors[monitor].checks[checkDay]
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // sanity check + if good save the KV
 | 
			
		||||
    if (configMonitors.length === Object.keys(stateMonitors.monitors).length) {
 | 
			
		||||
      await saveKVMonitors(kvMonitorsKey, stateMonitors)
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
  .catch((e) => console.log(e))
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,9 @@ export default function MonitorCard({ key, monitor, data }) {
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          )}
 | 
			
		||||
          <a href={monitor.url} target="_blank"><div className="text-xl">{monitor.name}</div></a>
 | 
			
		||||
          <a href={monitor.url} target="_blank">
 | 
			
		||||
            <div className="text-xl">{monitor.name}</div>
 | 
			
		||||
          </a>
 | 
			
		||||
        </div>
 | 
			
		||||
        <MonitorStatusLabel kvMonitor={data} />
 | 
			
		||||
      </div>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								src/components/monitorDayAverage.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/components/monitorDayAverage.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
const locations = {
 | 
			
		||||
  WAW: 'Warsaw',
 | 
			
		||||
  SCL: 'Santiago de Chile',
 | 
			
		||||
  MEL: 'Melbourne',
 | 
			
		||||
  SIN: 'Singapore',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function MonitorDayAverage({ location, avg }) {
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <br />
 | 
			
		||||
      <small>
 | 
			
		||||
        {locations[location] || location}: {avg}ms
 | 
			
		||||
      </small>
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
import React from 'react'
 | 
			
		||||
import config from '../../config.yaml'
 | 
			
		||||
import MonitorDayAverage from './monitorDayAverage'
 | 
			
		||||
 | 
			
		||||
export default function MonitorHistogram({ monitorId, kvMonitor }) {
 | 
			
		||||
  // create date and set date - daysInHistogram for the first day of the histogram
 | 
			
		||||
@@ -43,10 +45,10 @@ export default function MonitorHistogram({ monitorId, kvMonitor }) {
 | 
			
		||||
                kvMonitor.checks.hasOwnProperty(dayInHistogram) &&
 | 
			
		||||
                Object.keys(kvMonitor.checks[dayInHistogram].res).map((key) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <>
 | 
			
		||||
                      <br />
 | 
			
		||||
                      {key}: {kvMonitor.checks[dayInHistogram].res[key].a}ms
 | 
			
		||||
                    </>
 | 
			
		||||
                    <MonitorDayAverage
 | 
			
		||||
                      location={key}
 | 
			
		||||
                      avg={kvMonitor.checks[dayInHistogram].res[key].a}
 | 
			
		||||
                    />
 | 
			
		||||
                  )
 | 
			
		||||
                })}
 | 
			
		||||
            </div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user