lastIncident logic improve & index error msg
parent
a0fb157ae1
commit
93c069c419
|
|
@ -4,7 +4,7 @@ Another **serverless (and free!)** uptime monitoring & status page on Cloudflare
|
|||
## ⭐Features
|
||||
|
||||
- **Opensource** & Easy to deploy (in 10 minutes without local tools) & Free
|
||||
- Up to **2-minute** interval check on free plan (Up to 1-min on paid Workers plan)
|
||||
- Up to 50 **2-minute** interval check on free plan (Up to unlimited 1-min on paid Workers plan)
|
||||
- Monitoring for **HTTP/HTTPS/TCP port**
|
||||
- Show 90-day uptime history and uptime percentage
|
||||
- Show all incident history & detailed timeline
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { useState } from 'react';
|
||||
import { Container, Group, Burger } from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { MantineLogo } from '@mantine/ds';
|
||||
import { Container, Group, Text } from '@mantine/core';
|
||||
import classes from '@/styles/Header.module.css';
|
||||
|
||||
const links = [
|
||||
|
|
@ -12,7 +10,6 @@ const links = [
|
|||
];
|
||||
|
||||
export default function Header() {
|
||||
const [opened, { toggle }] = useDisclosure(false);
|
||||
const [active, setActive] = useState(links[0].link);
|
||||
|
||||
const items = links.map((link) => (
|
||||
|
|
@ -33,7 +30,12 @@ export default function Header() {
|
|||
return (
|
||||
<header className={classes.header}>
|
||||
<Container size="md" className={classes.inner}>
|
||||
<MantineLogo size={28} />
|
||||
<div>
|
||||
<a href='https://github.com/lyc8503/UptimeFlare' target='_blank'>
|
||||
<Text size='xl' span>🕒</Text>
|
||||
<Text size='xl' span fw={700} variant="gradient" gradient={{ from: 'blue', to: 'cyan', deg: 90 }}>UptimeFlare</Text>
|
||||
</a>
|
||||
</div>
|
||||
<Group gap={5}>
|
||||
{items}
|
||||
</Group>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import config from '@/uptime.config'
|
|||
import OverallStatus from '@/components/OverallStatus'
|
||||
import Header from '@/components/Header'
|
||||
import MonitorList from '@/components/MonitorList'
|
||||
import { Center, Text } from '@mantine/core'
|
||||
|
||||
export const runtime = 'experimental-edge'
|
||||
const inter = Inter({ subsets: ['latin'] })
|
||||
|
|
@ -23,9 +24,23 @@ export default function Home({ state }: { state: MonitorState }) {
|
|||
|
||||
<main className={inter.className}>
|
||||
<Header />
|
||||
<OverallStatus state={state} />
|
||||
<MonitorList config={config} state={state} />
|
||||
{/* <p>{JSON.stringify(state)}</p> */}
|
||||
|
||||
{
|
||||
state === undefined ?
|
||||
(
|
||||
<Center>
|
||||
<Text fw={700}>
|
||||
Monitor State is not defined now, please check your worker's status and KV binding!
|
||||
</Text>
|
||||
</Center>
|
||||
) :
|
||||
(
|
||||
<div>
|
||||
<OverallStatus state={state} />
|
||||
<MonitorList config={config} state={state} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
|
|
@ -34,7 +49,7 @@ export default function Home({ state }: { state: MonitorState }) {
|
|||
|
||||
export async function getServerSideProps() {
|
||||
const { UPTIMEFLARE_STATE } = process.env as unknown as { UPTIMEFLARE_STATE: KVNamespace }
|
||||
const state = await UPTIMEFLARE_STATE.get('state', 'json') as unknown as MonitorState
|
||||
const state = await UPTIMEFLARE_STATE?.get('state', 'json') as unknown as MonitorState
|
||||
|
||||
return { props: { state } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,12 +23,11 @@ async function getStatus(monitor: MonitorTarget): Promise<{ ping: number; up: bo
|
|||
try {
|
||||
const [hostname, port] = monitor.target.split(":")
|
||||
|
||||
// Write "PING" and read response
|
||||
// Write "PING\n"
|
||||
const socket = connect({ hostname: hostname, port: Number(port) })
|
||||
const reader = socket.readable.getReader()
|
||||
const writer = socket.writable.getWriter()
|
||||
await writer.write(new TextEncoder().encode("PING\n"))
|
||||
await reader.read() // The read here is necessary to actually test the connection, however it may hang if the server doesn't respond
|
||||
await socket.close()
|
||||
|
||||
// TODO: should throw an error here but it doesn't?
|
||||
|
|
@ -109,35 +108,43 @@ export default {
|
|||
status.up ? state.overallUp++ : state.overallDown++
|
||||
|
||||
// Update incidents
|
||||
let incidentList = state.incident[monitor.id] || []
|
||||
|
||||
// Create a dummy incident to store the start time of the monitoring and simplify logic
|
||||
state.incident[monitor.id] = state.incident[monitor.id] || [
|
||||
{
|
||||
start: [currentTimeSecond],
|
||||
end: currentTimeSecond,
|
||||
error: ['dummy']
|
||||
}
|
||||
]
|
||||
// Then lastIncident here must not be undefined
|
||||
const lastIncident = incidentList.slice(-1)[0]
|
||||
const timeString = new Date().toLocaleString(config.dateLocale, { timeZone: config.timezone })
|
||||
|
||||
if (status.up) {
|
||||
// Current status is up
|
||||
// close existing incident if any
|
||||
if (lastIncident && lastIncident.end === undefined) {
|
||||
if (lastIncident.end === undefined) {
|
||||
lastIncident.end = currentTimeSecond
|
||||
await config.callback(`✔️${monitor.name} came back up at ${timeString} after ${Math.round((lastIncident.end - lastIncident.start.slice(-1)[0]) / 60)} minutes of downtime`)
|
||||
}
|
||||
} else {
|
||||
// Current status is down
|
||||
// open new incident if not already open
|
||||
if (lastIncident === undefined || lastIncident?.end !== undefined) {
|
||||
if (lastIncident.end !== undefined) {
|
||||
incidentList.push({
|
||||
start: [currentTimeSecond],
|
||||
end: undefined,
|
||||
error: [status.err]
|
||||
})
|
||||
await config.callback(`❌${monitor.name} went down at ${timeString} with error ${status.err}`)
|
||||
} else if (lastIncident && lastIncident.end === undefined && lastIncident.error.slice(-1)[0] !== status.err) {
|
||||
} else if (lastIncident.end === undefined && lastIncident.error.slice(-1)[0] !== status.err) {
|
||||
// append if the error message changes
|
||||
lastIncident.start.push(currentTimeSecond)
|
||||
lastIncident.error.push(status.err)
|
||||
await config.callback(`❌${monitor.name} is still down at ${timeString} with error ${status.err}`)
|
||||
}
|
||||
}
|
||||
state.incident[monitor.id] = incidentList
|
||||
|
||||
// append to latency data
|
||||
let latencyLists = state.latency[monitor.id] || {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ main = "src/index.ts"
|
|||
compatibility_date = "2023-05-15"
|
||||
|
||||
kv_namespaces = [
|
||||
{ binding = "UPTIMEFLARE_STATE", id = "30a3733511a246e395ab99ee6a8dceb7" }
|
||||
{ binding = "UPTIMEFLARE_STATE", id = "ff7ab44866d746aaa19f2225e464ad3e" }
|
||||
]
|
||||
|
||||
[triggers]
|
||||
|
|
|
|||
Loading…
Reference in New Issue