lastIncident logic improve & index error msg

pull/5/head
lyc8503 2023-10-20 02:08:56 +08:00
parent a0fb157ae1
commit 93c069c419
5 changed files with 42 additions and 18 deletions

View File

@ -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

View File

@ -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>

View File

@ -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&apos;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 } }
}

View File

@ -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] || {

View File

@ -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]