Openstatus www.openstatus.dev
6
fork

Configure Feed

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

๐Ÿš‘ fly was fun (#389)

* ๐Ÿš‘ fly was fun

* ๐Ÿ“ format

authored by

Thibault Le Ouay and committed by
GitHub
79f9a1d6 d6b756be

+49 -62
+1
apps/server/src/checker/alerting.ts
··· 19 19 } 20 20 21 21 export const triggerAlerting = async ({ monitorId }: { monitorId: string }) => { 22 + console.log(`triggerAlerting for ${monitorId}`); 22 23 const notifications = await db 23 24 .select() 24 25 .from(schema.notificationsToMonitors)
+12 -10
apps/server/src/checker/checker.ts
··· 19 19 }) => { 20 20 const { monitorId, cronTimestamp, url, workspaceId } = monitorInfo; 21 21 22 + console.log( 23 + `publishing ping response for ${url} with status ${statusCode} and latency ${latency} and monitorId ${monitorId} `, 24 + ); 22 25 await publishPingResponse({ 23 26 id: nanoid(), // TBD: we don't need it 24 27 timestamp: Date.now(), ··· 37 40 const res = await ping(data); 38 41 const endTime = Date.now(); 39 42 const latency = endTime - startTime; 40 - await monitor({ monitorInfo: data, latency, statusCode: res.status }); 41 - if (res.ok && !res.redirected) { 43 + if (res.ok) { 44 + await monitor({ monitorInfo: data, latency, statusCode: res.status }); 42 45 if (data?.status === "error") { 43 46 await updateMonitorStatus({ 44 47 monitorId: data.monitorId, 45 48 status: "active", 46 49 }); 47 50 } 48 - 49 - if (!res.ok || (res.ok && !res.redirected)) { 50 - if (data?.status === "active") { 51 - await updateMonitorStatus({ 52 - monitorId: data.monitorId, 53 - status: "error", 54 - }); 55 - } 51 + } else { 52 + console.log(`error for ${data.url} with status ${res.status}`); 53 + if (data?.status === "active") { 54 + await updateMonitorStatus({ 55 + monitorId: data.monitorId, 56 + status: "error", 57 + }); 56 58 } 57 59 } 58 60 };
+33 -5
apps/server/src/checker/index.ts
··· 1 + import { Receiver } from "@upstash/qstash"; 1 2 import { Hono } from "hono"; 2 3 4 + import { env } from "../env"; 5 + import { catchTooManyRetry } from "./alerting"; 3 6 import { checker } from "./checker"; 4 - import { middleware } from "./middleware"; 7 + import { payloadSchema } from "./schema"; 5 8 import type { Payload } from "./schema"; 6 9 7 10 export type Variables = { 8 11 payload: Payload; 9 12 }; 13 + 14 + const r = new Receiver({ 15 + currentSigningKey: env.QSTASH_CURRENT_SIGNING_KEY, 16 + nextSigningKey: env.QSTASH_NEXT_SIGNING_KEY, 17 + }); 10 18 11 19 export const checkerRoute = new Hono<{ Variables: Variables }>(); 12 20 13 - checkerRoute.use("/*", middleware); 14 - 15 21 // TODO: only use checkerRoute.post("/checker", checker); 16 22 checkerRoute.post("/checker", async (c) => { 17 - const payload = c.get("payload"); 23 + const json = await c.req.json(); 24 + 25 + const result = payloadSchema.safeParse(json); 26 + 27 + if (!result.success) { 28 + console.error(result.error); 29 + return c.text("Unprocessable Entity", 422); 30 + } 31 + 32 + if (Number(c.req.header("Upstash-Retried") || 0) >= 2) { 33 + console.log( 34 + `catchTooManyRetry for ${result.data.url} with retry nb ${c.req.header( 35 + "Upstash-Retried", 36 + )}`, 37 + ); 38 + catchTooManyRetry(result.data); 39 + return c.text("Ok", 200); // needs to be 200, otherwise qstash will retry 40 + } 41 + 18 42 try { 19 - checker(payload); 43 + console.log(`start checker for ${result.data.url}`); 44 + checker(result.data); 45 + console.log(`end checker for ${result.data.url}`); 46 + return c.text("Ok", 200); 20 47 } catch (e) { 21 48 console.error(e); 49 + return c.text("Internal Server Error", 500); 22 50 } 23 51 });
-46
apps/server/src/checker/middleware.ts
··· 1 - import { Receiver } from "@upstash/qstash"; 2 - import type { Context, Next } from "hono"; 3 - 4 - import { env } from "../env"; 5 - import { catchTooManyRetry } from "./alerting"; 6 - import type { Variables } from "./index"; 7 - import { payloadSchema } from "./schema"; 8 - 9 - const r = new Receiver({ 10 - currentSigningKey: env.QSTASH_CURRENT_SIGNING_KEY, 11 - nextSigningKey: env.QSTASH_NEXT_SIGNING_KEY, 12 - }); 13 - 14 - export async function middleware( 15 - c: Context<{ Variables: Variables }, "/*", {}>, 16 - next: Next, 17 - ) { 18 - const json = await c.req.json(); 19 - 20 - const isValid = r.verify({ 21 - signature: c.req.header("Upstash-Signature") || "", 22 - body: JSON.stringify(json), 23 - }); 24 - 25 - if (!isValid) { 26 - return c.text("Unauthorized", 401); 27 - } 28 - 29 - const result = payloadSchema.safeParse(json); 30 - 31 - if (!result.success) { 32 - console.error(result.error); 33 - return c.text("Unprocessable Entity", 422); 34 - } 35 - 36 - /** 37 - * Alert user after third retry, on forth try 38 - */ 39 - if (c.req.header("Upstash-Retried") === "3") { 40 - catchTooManyRetry(result.data); 41 - return c.text("", 200); // needs to be 200, otherwise qstash will retry 42 - } 43 - 44 - c.set("payload", result.data); 45 - await next(); 46 - }
+2
apps/server/src/index.ts
··· 1 1 import { Hono } from "hono"; 2 2 3 + import { checkerRoute } from "./checker"; 3 4 import { env } from "./env"; 4 5 import { publicRoute } from "./public"; 5 6 import { api } from "./v1"; ··· 27 28 */ 28 29 app.route("/v1", api); 29 30 31 + app.route("/", checkerRoute); 30 32 if (process.env.NODE_ENV === "development") { 31 33 app.showRoutes(); 32 34 }
+1 -1
packages/tinybird/src/validation.ts
··· 37 37 latency: z.number(), // in ms 38 38 cronTimestamp: z.number().int().optional().nullable().default(Date.now()), 39 39 url: z.string().url(), 40 - region: z.string().min(4).max(4), // REMINDER: won't work on fy 40 + region: z.string().min(3).max(4), // REMINDER: won't work on fy 41 41 }); 42 42 43 43 /**