Openstatus www.openstatus.dev
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: tinybird improvements (#62)

* fix: tinybird improvements

* fix: use monitorId

* chore: venv tinybird

authored by

Thibault Le Ouay and committed by
GitHub
d303e2fe af407f4d

+42 -26
+1 -1
.gitignore
··· 34 34 35 35 # vercel 36 36 .vercel 37 - 37 + .venv 38 38 # packages 39 39 dist 40 40 packages/emails/.react-email
+1
apps/web/package.json
··· 43 43 "date-fns": "^2.30.0", 44 44 "lucide-react": "^0.244.0", 45 45 "micro": "10.0.1", 46 + "nanoid": "^4.0.2", 46 47 "next": "13.4.8", 47 48 "next-plausible": "3.7.2", 48 49 "react": "18.2.0",
+2 -1
apps/web/src/app/api/checker/regions/_checker.ts
··· 1 1 import { Receiver } from "@upstash/qstash/cloudflare"; 2 + import { nanoid } from "nanoid"; 2 3 import { z } from "zod"; 3 4 4 5 import { ··· 26 27 }: { latency: number; url: string; region: string; cronTimestamp: number }, 27 28 ) => { 28 29 await publishPingResponse(tb)({ 29 - id: "openstatus", 30 + id: nanoid(), 30 31 workspaceId: "openstatus", 31 32 pageId: "openstatus", 32 33 monitorId: "openstatusPing",
+2 -2
apps/web/src/app/monitor/[id]/page.tsx
··· 28 28 }) { 29 29 const search = searchParamsSchema.safeParse(searchParams); 30 30 const data = search.success 31 - ? await getResponseListData({ siteId: params.id, ...search.data }) 32 - : await getResponseListData({ siteId: params.id }); 31 + ? await getResponseListData({ monitorId: params.id, ...search.data }) 32 + : await getResponseListData({ monitorId: params.id }); 33 33 if (!data || !search.success) return <div>Something went wrong</div>; 34 34 return <DataTable columns={columns} data={data} />; 35 35 }
+2 -2
apps/web/src/app/page.tsx
··· 8 8 import { HeroForm } from "./_components/hero-form"; 9 9 10 10 export default async function Page() { 11 - const data = await getMonitorListData({ siteId: "openstatus" }); 11 + const data = await getMonitorListData({ monitorId: "openstatusPing" }); 12 12 13 13 return ( 14 14 <main className="flex min-h-screen w-full flex-col space-y-6 p-4 md:p-8"> ··· 47 47 {data && ( 48 48 <Tracker 49 49 data={data} 50 - id="openstatus" 50 + id="openstatusPing" 51 51 name="Ping" 52 52 url="https://openstatus.dev/api/ping" 53 53 />
+2 -2
apps/web/src/app/play/@modal/(..)monitor/[id]/page.tsx
··· 29 29 }) { 30 30 const search = searchParamsSchema.safeParse(searchParams); 31 31 const data = search.success 32 - ? await getResponseListData({ siteId: params.id, ...search.data }) 33 - : await getResponseListData({ siteId: params.id }); 32 + ? await getResponseListData({ monitorId: params.id, ...search.data }) 33 + : await getResponseListData({ monitorId: params.id }); 34 34 35 35 if (!data) return <div>Something went wrong</div>; 36 36
+4 -3
apps/web/src/app/play/page.tsx
··· 22 22 const params = search.success ? search.data : undefined; 23 23 24 24 const data = search.success 25 - ? await getMonitorListData({ siteId: "openstatus", ...params }) 26 - : await getMonitorListData({ siteId: "openstatus" }); 25 + ? await getMonitorListData({ monitorId: "openstatusPing", ...params }) 26 + : await getMonitorListData({ monitorId: "openstatusPing" }); 27 27 28 28 return ( 29 29 <div className="relative flex flex-col items-center justify-center gap-4"> ··· 32 32 </div> 33 33 <p className="font-cal mb-2 text-3xl">Status</p> 34 34 <p className="text-lg font-light">Learn more on how to build your own.</p> 35 + 35 36 {data && ( 36 37 <Tracker 37 38 data={data} 38 - id="openstatus" 39 + id="openstatusPing" 39 40 name="Ping" 40 41 url="https://openstatus.dev/api/ping" 41 42 />
+1 -1
apps/web/src/components/tracker.tsx
··· 164 164 </p> 165 165 {context === "play" ? ( 166 166 <Link 167 - href={`/monitor/openstatus?fromDate=${cronTimestamp}&toDate=${toDate}`} 167 + href={`/monitor/openstatusPing?fromDate=${cronTimestamp}&toDate=${toDate}`} 168 168 className="text-muted-foreground hover:text-foreground" 169 169 > 170 170 <Eye className="h-4 w-4" />
+4 -1
apps/web/src/lib/tb.ts
··· 15 15 // TODO: add security layer 16 16 export async function getResponseListData( 17 17 props: Partial< 18 - Pick<ResponseListParams, "siteId" | "region" | "cronTimestamp" | "limit"> 18 + Pick< 19 + ResponseListParams, 20 + "siteId" | "region" | "cronTimestamp" | "limit" | "monitorId" 21 + > 19 22 >, 20 23 ) { 21 24 try {
+5 -5
packages/tinybird/pipes/monitor_list.pipe
··· 1 - VERSION 0 1 + VERSION 1 2 2 3 3 TOKEN "monitor_list__v0_endpoint_read_0539" READ 4 4 5 - NODE monitor_list__v0_0 5 + NODE monitor_list__v1_0 6 6 SQL > 7 7 8 8 % 9 - SELECT 10 - {% if defined(groupBy) and groupBy == "day" %} 9 + SELECT 10 + {% if defined(groupBy) and groupBy == "day" %} 11 11 toUnixTimestamp64Milli(toDateTime64(DATE(cronTimestamp / 1000), 3)) 12 12 {% else %} 13 13 cronTimestamp 14 14 {% end %} 15 15 AS cronTimestamp, ROUND(AVG(latency)) as avgLatency, COUNT(*) as count, COUNT(CASE WHEN statusCode BETWEEN 200 AND 299 THEN 1 ELSE NULL END) as ok 16 16 FROM ping_response__v2 17 - WHERE id = {{ String(siteId, 'openstatus') }} AND cronTimestamp IS NOT NULL 17 + WHERE monitorId = {{ String(monitorId, 'openstatusPing') }} AND cronTimestamp IS NOT NULL 18 18 GROUP BY cronTimestamp 19 19 ORDER BY cronTimestamp DESC 20 20 LIMIT {{Int32(limit, 1000)}}
+4 -4
packages/tinybird/pipes/response_list.pipe
··· 1 - VERSION 1 1 + VERSION 2 2 2 3 - NODE response_list__v1_0 3 + NODE response_list__v2_0 4 4 SQL > 5 5 6 6 % 7 7 SELECT * 8 8 FROM ping_response__v2 9 - WHERE id = {{ String(siteId, 'openstatus') }} 9 + WHERE monitorId = {{ String(monitorId, 'openstatusPing') }} 10 10 {% if defined(region) %} 11 11 AND region = {{ String(region) }} 12 12 {% end %} ··· 20 20 AND cronTimestamp <= {{ Int64(toDate) }} 21 21 {% end %} 22 22 ORDER BY timestamp DESC 23 - LIMIT {{Int32(limit, 100)}} 23 + LIMIT {{Int32(limit, 100)}}
+2 -2
packages/tinybird/src/client.ts
··· 22 22 23 23 export function getResponseList(tb: Tinybird) { 24 24 return tb.buildPipe({ 25 - pipe: "response_list__v1", 25 + pipe: "response_list__v2", 26 26 parameters: tbParameterResponseList, 27 27 data: tbBuildResponseList, 28 28 opts: { ··· 33 33 34 34 export function getMonitorList(tb: Tinybird) { 35 35 return tb.buildPipe({ 36 - pipe: "monitor_list__v0", 36 + pipe: "monitor_list__v1", 37 37 parameters: tbParameterMonitorList, 38 38 data: tbBuildMonitorList, 39 39 opts: {
+3 -2
packages/tinybird/src/validation.ts
··· 68 68 * Params for pipe response_list__v1 69 69 */ 70 70 export const tbParameterResponseList = z.object({ 71 - siteId: z.string().optional().default("openstatus"), // REMINDER: remove default once alpha 72 - monitorId: z.string().optional().default("openstatus"), // REMINDER: remove default once alpha 71 + siteId: z.string().optional().default(""), // REMINDER: remove default once alpha 72 + monitorId: z.string().default(""), // REMINDER: remove default once alpha 73 73 fromDate: z.number().int().default(0), // always start from a date 74 74 toDate: z.number().int().optional(), 75 75 limit: z.number().int().optional().default(2500), // one day has 2448 pings (17 (regions) * 6 (per hour) * 24) ··· 89 89 */ 90 90 export const tbParameterMonitorList = z.object({ 91 91 siteId: z.string().optional().default("openstatus"), // REMINDER: remove default once alpha 92 + monitorId: z.string().optional().default(""), // REMINDER: remove default once alpha 92 93 limit: z.number().int().optional().default(2500), // one day has 2448 pings (17 (regions) * 6 (per hour) * 24) 93 94 cronTimestamp: z.number().int().optional(), 94 95 groupBy: z.enum(groupByRange).optional(), // TODO: rename to frequency: z.enum(["1d", "auto"]) - where "auto" the default periodicity setup
+9
pnpm-lock.yaml
··· 137 137 micro: 138 138 specifier: 10.0.1 139 139 version: 10.0.1 140 + nanoid: 141 + specifier: ^4.0.2 142 + version: 4.0.2 140 143 next: 141 144 specifier: 13.4.8 142 145 version: 13.4.8(@babel/core@7.22.5)(react-dom@18.2.0)(react@18.2.0) ··· 6604 6607 resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} 6605 6608 engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 6606 6609 hasBin: true 6610 + 6611 + /nanoid@4.0.2: 6612 + resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} 6613 + engines: {node: ^14 || ^16 || >=18} 6614 + hasBin: true 6615 + dev: false 6607 6616 6608 6617 /natural-compare-lite@1.4.0: 6609 6618 resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}