Openstatus
www.openstatus.dev
1import fs from "node:fs";
2import type { RegionMetricsChartTable } from "@/data/content";
3import { type Region, regionDict } from "@openstatus/regions";
4import { SimpleChart } from "./simple-chart";
5
6export interface LatencyChartTableProps {
7 staticFile: string;
8 caption?: string;
9}
10
11interface LatencyChartTableData {
12 regions: Region[];
13 data: {
14 regions: Region[];
15 data: (Partial<Record<Region, number>> & { timestamp: string })[];
16 };
17 metricsByRegion: RegionMetricsChartTable[];
18}
19
20export function LatencyChartTable({
21 staticFile,
22 caption = "A list of all the selected regions.",
23}: LatencyChartTableProps) {
24 const data = JSON.parse(
25 fs.readFileSync(`${process.cwd()}/public${staticFile}`, "utf8"),
26 ) as LatencyChartTableData;
27 const { regions, data: chartData, metricsByRegion } = data;
28
29 return (
30 <div className="table-wrapper">
31 <table>
32 <caption>{caption}</caption>
33 <thead>
34 <tr>
35 <th className="w-[100px]">Region</th>
36 <th>Trend</th>
37 <th className="w-[50px]">P75</th>
38 <th className="w-[50px]">P95</th>
39 <th className="w-[50px]">P99</th>
40 </tr>
41 </thead>
42 <tbody>
43 {regions
44 .filter((region) => regions.includes(region))
45 .map((region) => {
46 const regionConfig = regionDict[region as Region];
47 const flag = regionConfig.flag;
48 const code = regionConfig.code;
49 const metrics = metricsByRegion.find((m) => m.region === region);
50 return (
51 <tr key={region}>
52 <td>
53 {flag} {code}
54 </td>
55 <td>
56 <SimpleChart
57 data={chartData.data.map((d) => ({
58 timestamp: d.timestamp,
59 latency: d[region],
60 }))}
61 />
62 </td>
63 <td>
64 {metrics?.p75Latency}
65 ms
66 </td>
67 <td>
68 {metrics?.p95Latency}
69 ms
70 </td>
71 <td>
72 {metrics?.p99Latency}
73 ms
74 </td>
75 </tr>
76 );
77 })}
78 </tbody>
79 </table>
80 </div>
81 );
82}