iata added, todo fix location
parent
1d431a649f
commit
aef4dedabe
29
README.md
29
README.md
|
|
@ -2,30 +2,35 @@
|
||||||
Another **serverless (and free!)** uptime monitoring & status page on Cloudflare Workers with more advanced features and nice UI.
|
Another **serverless (and free!)** uptime monitoring & status page on Cloudflare Workers with more advanced features and nice UI.
|
||||||
|
|
||||||
## ⭐Features
|
## ⭐Features
|
||||||
|
|
||||||
- **Opensource** & Easy to deploy (in 10 minutes without local tools) & Free
|
- **Opensource** & Easy to deploy (in 10 minutes without local tools) & Free
|
||||||
- Up to 50 **2-minute** interval check on free plan (Up to unlimited 1-min on paid Workers plan)
|
|
||||||
|
#### Monitoring
|
||||||
|
- Up to 50 **2-minute** interval check on free plan (Up to unlimited 1-min check on paid Workers plan)
|
||||||
- Monitoring for **HTTP/HTTPS/TCP port**
|
- Monitoring for **HTTP/HTTPS/TCP port**
|
||||||
- Show 90-day uptime history and uptime percentage
|
- Up to 90-day uptime history and uptime percentage
|
||||||
- Show all incident history & detailed timeline
|
|
||||||
- **Interactive ping(response time) chart** for all type of monitors
|
|
||||||
- Custom request method & headers & body for HTTP(s)
|
- Custom request method & headers & body for HTTP(s)
|
||||||
- Custom status code & keyword check for HTTP(s)
|
- Custom status code & keyword check for HTTP(s)
|
||||||
- Email Notifications & Customizable Webhook
|
- Email Notifications & Customizable Webhook
|
||||||
- Customizable status page
|
|
||||||
- use your own domain with CNAME
|
|
||||||
|
|
||||||
TODO:
|
#### Status page
|
||||||
- SSL?
|
- **Interactive ping(response time) chart** for all type of monitors
|
||||||
- Slack / Telegram
|
- Responsive UI & Follow system theme
|
||||||
|
- Customizable status page
|
||||||
|
- Use your own domain with CNAME
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
My status page (Online demo):
|
My status page (Online demo): https://uptimeflare.pages.dev/
|
||||||
|
|
||||||
Some screenshots:
|
Some screenshots: TODO
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
|
||||||
|
|
||||||
## More documentation
|
## More documentation
|
||||||
|
|
||||||
|
|
||||||
|
## TODOs
|
||||||
|
- SSL?
|
||||||
|
- Slack / Telegram
|
||||||
|
- Incident timeline
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { MonitorState, MonitorTarget } from "@/uptime.types";
|
||||||
|
import { Tooltip } from "@mantine/core";
|
||||||
|
|
||||||
|
|
||||||
|
export default function DetailBar({ monitor, state }: { monitor: MonitorTarget, state: MonitorState }) {
|
||||||
|
// const day = new Date()
|
||||||
|
// day.setHours(0, 0, 0, 0)
|
||||||
|
// const dayStart = day.getTime()
|
||||||
|
|
||||||
|
const overlapLen = (x1: number, x2: number, y1: number, y2: number) => {
|
||||||
|
return Math.max(0, Math.min(x2, y2) - Math.max(x1, y1) + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const uptimePercentBars = []
|
||||||
|
|
||||||
|
for (let i = 89; i > 0; i--) {
|
||||||
|
|
||||||
|
let dayDownTime = 0
|
||||||
|
let dayTotalTime = 0
|
||||||
|
|
||||||
|
// if (state.incident[monitor.id][0].end)
|
||||||
|
|
||||||
|
uptimePercentBars.push(
|
||||||
|
<Tooltip key={i} label="Tooltip">
|
||||||
|
<div style={{ height: '20px', width: '0.8%', background: 'green', borderRadius: '2px', marginLeft: '0.155%', marginRight: '0.155%' }}/>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ display: 'flex', flexWrap: 'nowrap', marginTop: '10px', marginBottom: '5px' }}>
|
||||||
|
{uptimePercentBars}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
import { Text, Tooltip } from "@mantine/core"
|
import { Text } from "@mantine/core"
|
||||||
import { MonitorState, MonitorTarget } from "@/uptime.types";
|
import { MonitorState, MonitorTarget } from "@/uptime.types"
|
||||||
import { IconAlertCircle, IconCircleCheck } from "@tabler/icons-react";
|
import { IconAlertCircle, IconCircleCheck } from "@tabler/icons-react"
|
||||||
import DetailChart from "./DetailChart";
|
import DetailChart from "./DetailChart"
|
||||||
import NoSsr from "./NoSsr";
|
import DetailBar from "./DetailBar"
|
||||||
|
|
||||||
function getColor(percent: number | string, darker: boolean): string {
|
function getColor(percent: number | string, darker: boolean): string {
|
||||||
percent = Number(percent)
|
percent = Number(percent)
|
||||||
|
|
@ -18,7 +18,6 @@ function getColor(percent: number | string, darker: boolean): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function MonitorDetail({ monitor, state }: { monitor: MonitorTarget, state: MonitorState }) {
|
export default function MonitorDetail({ monitor, state }: { monitor: MonitorTarget, state: MonitorState }) {
|
||||||
|
|
||||||
if (!state.latency[monitor.id]) return (
|
if (!state.latency[monitor.id]) return (
|
||||||
|
|
@ -40,26 +39,6 @@ export default function MonitorDetail({ monitor, state }: { monitor: MonitorTarg
|
||||||
console.log(downTime)
|
console.log(downTime)
|
||||||
const uptimePercent = ((totalTime - downTime) / totalTime * 100).toPrecision(4)
|
const uptimePercent = ((totalTime - downTime) / totalTime * 100).toPrecision(4)
|
||||||
|
|
||||||
const uptimePercentBars = []
|
|
||||||
|
|
||||||
// const day = new Date()
|
|
||||||
// day.setHours(0, 0, 0, 0)
|
|
||||||
// const dayStart = day.getTime()
|
|
||||||
|
|
||||||
for (let i = 0; i < 90; i++) {
|
|
||||||
|
|
||||||
let dayDownTime = 0
|
|
||||||
let dayTotalTime = 0
|
|
||||||
|
|
||||||
// if (state.incident[monitor.id][0].end)
|
|
||||||
|
|
||||||
uptimePercentBars.push(
|
|
||||||
<Tooltip key={i} label="Tooltip">
|
|
||||||
<div style={{ height: '20px', width: '0.8%', background: 'green', borderRadius: '2px', marginLeft: '0.155%', marginRight: '0.155%' }}/>
|
|
||||||
</Tooltip>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
|
|
@ -67,10 +46,7 @@ export default function MonitorDetail({ monitor, state }: { monitor: MonitorTarg
|
||||||
<Text mt='sm' fw={700} style={{ display: 'inline', color: getColor(uptimePercent, true) }}>Overall: {uptimePercent}%</Text>
|
<Text mt='sm' fw={700} style={{ display: 'inline', color: getColor(uptimePercent, true) }}>Overall: {uptimePercent}%</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'flex', flexWrap: 'nowrap', marginTop: '10px', marginBottom: '5px' }}>
|
<DetailBar monitor={monitor} state={state} />
|
||||||
{uptimePercentBars}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DetailChart monitor={monitor} state={state} />
|
<DetailChart monitor={monitor} state={state} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -2,10 +2,8 @@ async function getWorkerLocation() {
|
||||||
const res = await fetch('https://cloudflare.com/cdn-cgi/trace')
|
const res = await fetch('https://cloudflare.com/cdn-cgi/trace')
|
||||||
const text = await res.text()
|
const text = await res.text()
|
||||||
|
|
||||||
const loc = /^loc=(.*)$/m.exec(text)?.[1]
|
|
||||||
const colo = /^colo=(.*)$/m.exec(text)?.[1]
|
const colo = /^colo=(.*)$/m.exec(text)?.[1]
|
||||||
|
return colo
|
||||||
return loc + '/' + colo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchTimeout = (url: string, ms: number, { signal, ...options }: RequestInit<RequestInitCfProperties> | undefined = {}): Promise<Response> => {
|
const fetchTimeout = (url: string, ms: number, { signal, ...options }: RequestInit<RequestInitCfProperties> | undefined = {}): Promise<Response> => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue