diff --git a/apps/checker/README.md b/apps/checker/README.md index 61674c22c5..135f8a8f39 100644 --- a/apps/checker/README.md +++ b/apps/checker/README.md @@ -28,3 +28,9 @@ docker run -p 8080:8080 checker ```bash fly deploy ``` + +## Deploy to all region + +```bash +fly scale count 35 --region ams,arn,atl,bog,bom,bos,cdg,den,dfw,ewr,eze,fra,gdl,gig,gru,hkg,iad,jnb,lax,lhr,mad,mia,nrt,ord,otp,phx,qro,scl,sjc,sea,sin,syd,waw,yul,yyz +``` diff --git a/apps/server/src/env.ts b/apps/server/src/env.ts index 255e074c12..fc2dc20c7c 100644 --- a/apps/server/src/env.ts +++ b/apps/server/src/env.ts @@ -1,7 +1,7 @@ import { createEnv } from "@t3-oss/env-core"; import { z } from "zod"; -import { flyRegions } from "@openstatus/utils"; +import { flyRegions } from "@openstatus/db/src/schema"; export const env = createEnv({ server: { diff --git a/apps/server/src/v1/monitors/post.ts b/apps/server/src/v1/monitors/post.ts index 2a8ac1bb4a..32acc4e7cd 100644 --- a/apps/server/src/v1/monitors/post.ts +++ b/apps/server/src/v1/monitors/post.ts @@ -70,6 +70,12 @@ export function registerPostMonitor(api: typeof monitorsApi) { throw new HTTPException(403, { message: "Forbidden" }); } + for (const region of input.regions) { + if (!workspacePlan.limits.regions.includes(region)) { + throw new HTTPException(403, { message: "Upgrade for more region" }); + } + } + const { headers, regions, assertions, ...rest } = input; const assert = assertions ? getAssertions(assertions) : []; diff --git a/apps/server/src/v1/monitors/put.ts b/apps/server/src/v1/monitors/put.ts index da563b7584..5dbd22c271 100644 --- a/apps/server/src/v1/monitors/put.ts +++ b/apps/server/src/v1/monitors/put.ts @@ -50,6 +50,11 @@ export function registerPutMonitor(api: typeof monitorsApi) { throw new HTTPException(403, { message: "Forbidden" }); } + for (const region of input.regions) { + if (!workspacePlan.limits.regions.includes(region)) { + throw new HTTPException(403, { message: "Upgrade for more region" }); + } + } const _monitor = await db .select() .from(monitor) diff --git a/apps/web/public/assets/changelog/more-regions.png b/apps/web/public/assets/changelog/more-regions.png new file mode 100644 index 0000000000..c0457f80d3 Binary files /dev/null and b/apps/web/public/assets/changelog/more-regions.png differ diff --git a/apps/web/src/app/api/checker/cron/_cron.ts b/apps/web/src/app/api/checker/cron/_cron.ts index 5952eb4636..7e75e9762d 100644 --- a/apps/web/src/app/api/checker/cron/_cron.ts +++ b/apps/web/src/app/api/checker/cron/_cron.ts @@ -45,7 +45,7 @@ export const cron = async ({ const parent = client.queuePath( env.GCP_PROJECT_ID, env.GCP_LOCATION, - periodicity, + periodicity ); const timestamp = Date.now(); @@ -54,7 +54,7 @@ export const cron = async ({ .select({ id: maintenance.id }) .from(maintenance) .where( - and(lte(maintenance.from, new Date()), gte(maintenance.to, new Date())), + and(lte(maintenance.from, new Date()), gte(maintenance.to, new Date())) ) .as("currentMaintenance"); @@ -63,7 +63,7 @@ export const cron = async ({ .from(maintenancesToMonitors) .innerJoin( currentMaintenance, - eq(maintenancesToMonitors.maintenanceId, currentMaintenance.id), + eq(maintenancesToMonitors.maintenanceId, currentMaintenance.id) ); const result = await db @@ -73,8 +73,8 @@ export const cron = async ({ and( eq(monitor.periodicity, periodicity), eq(monitor.active, true), - notInArray(monitor.id, currentMaintenanceMonitors), - ), + notInArray(monitor.id, currentMaintenanceMonitors) + ) ) .all(); @@ -84,7 +84,7 @@ export const cron = async ({ const allResult = []; for (const row of monitors) { - const selectedRegions = row.regions.length > 0 ? row.regions : ["auto"]; + const selectedRegions = row.regions.length > 0 ? row.regions : ["ams"]; const result = await db .select() @@ -127,7 +127,7 @@ export const cron = async ({ const failed = allRequests.filter((r) => r.status === "rejected").length; console.log( - `End cron for ${periodicity} with ${allResult.length} jobs with ${success} success and ${failed} failed`, + `End cron for ${periodicity} with ${allResult.length} jobs with ${success} success and ${failed} failed` ); }; // timestamp needs to be in ms diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/data/_components/data-table-wrapper.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/data/_components/data-table-wrapper.tsx index 5cbc10105c..c01963f511 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/data/_components/data-table-wrapper.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/data/_components/data-table-wrapper.tsx @@ -19,6 +19,8 @@ import { DataTable } from "@/components/data-table/data-table"; import { LoadingAnimation } from "@/components/loading-animation"; import { ResponseDetailTabs } from "@/components/ping-response-analysis/response-detail-tabs"; import { api } from "@/trpc/client"; +import type { z } from "zod"; +import type { monitorFlyRegionSchema } from "@openstatus/db/src/schema"; // EXAMPLE: get the type of the response of the endpoint // biome-ignore lint/correctness/noUnusedVariables: @@ -29,7 +31,7 @@ export type Monitor = { monitorId: string; url: string; latency: number; - region: "ams" | "iad" | "hkg" | "jnb" | "syd" | "gru"; + region: z.infer; statusCode: number | null; timestamp: number; workspaceId: string; @@ -80,7 +82,7 @@ function Details({ row }: { row: Row }) { url: row.original.url, region: row.original.region, cronTimestamp: row.original.cronTimestamp || undefined, - }), + }) ); if (!data || data.length === 0) return

Something went wrong

; diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/details/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/details/page.tsx index fad1aee193..940cd9d7a2 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/details/page.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/details/page.tsx @@ -2,12 +2,11 @@ import Link from "next/link"; import * as z from "zod"; import { Button } from "@openstatus/ui"; -import { flyRegions } from "@openstatus/utils"; import { EmptyState } from "@/components/dashboard/empty-state"; import { ResponseDetails } from "@/components/monitor-dashboard/response-details"; import { api } from "@/trpc/server"; - +import { monitorFlyRegionSchema } from "@openstatus/db/src/schema"; // /** @@ -16,7 +15,7 @@ import { api } from "@/trpc/server"; const searchParamsSchema = z.object({ monitorId: z.string(), url: z.string(), - region: z.enum(flyRegions).optional(), + region: monitorFlyRegionSchema.optional(), cronTimestamp: z.coerce.number(), }); diff --git a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/overview/page.tsx b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/overview/page.tsx index 7933cd5a9e..7807bf13b7 100644 --- a/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/overview/page.tsx +++ b/apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/overview/page.tsx @@ -44,7 +44,7 @@ const searchParamsSchema = z.object({ value ?.trim() ?.split(",") - .filter((i) => flyRegions.includes(i as Region)) ?? flyRegions, + .filter((i) => flyRegions.includes(i as Region)) ?? [] ), }); @@ -117,7 +117,7 @@ export default async function Page({ period={period} quantile={quantile} interval={interval} - regions={regions as Region[]} // FIXME: not properly reseted after filtered + regions={regions.length ? (regions as Region[]) : monitor.regions} // FIXME: not properly reseted after filtered monitor={monitor} isQuantileDisabled={isQuantileDisabled} metricsByRegion={metricsByRegion} diff --git a/apps/web/src/components/data-table/columns.tsx b/apps/web/src/components/data-table/columns.tsx index 10f825c261..b39e875b94 100644 --- a/apps/web/src/components/data-table/columns.tsx +++ b/apps/web/src/components/data-table/columns.tsx @@ -11,7 +11,7 @@ import { TooltipProvider, TooltipTrigger, } from "@openstatus/ui"; -import { regionsDict } from "@openstatus/utils"; +import { flyRegionsDict } from "@openstatus/utils"; import { DataTableColumnHeader } from "./data-table-column-header"; import { DataTableStatusBadge } from "./data-table-status-badge"; @@ -98,7 +98,7 @@ export const columns: ColumnDef[] = [
{String(row.getValue("region"))} - {regionsDict[row.original.region]?.location} + {flyRegionsDict[row.original.region]?.location}
); diff --git a/apps/web/src/components/forms/monitor-form.tsx b/apps/web/src/components/forms/monitor-form.tsx index c37971b573..5e195582db 100644 --- a/apps/web/src/components/forms/monitor-form.tsx +++ b/apps/web/src/components/forms/monitor-form.tsx @@ -17,6 +17,7 @@ import { monitorMethods, monitorMethodsSchema, monitorPeriodicitySchema, + workspacePlans, } from "@openstatus/db/src/schema"; import { getLimit } from "@openstatus/plans"; import { @@ -103,8 +104,7 @@ export function MonitorForm({ periodicity: defaultValues?.periodicity || "30m", active: defaultValues?.active ?? true, id: defaultValues?.id || 0, - regions: - defaultValues?.regions || (flyRegions as Writeable), + regions: defaultValues?.regions || getLimit("free", "regions"), headers: defaultValues?.headers?.length ? defaultValues?.headers : [{ key: "", value: "" }], @@ -441,7 +441,7 @@ export function MonitorForm({