- {numberFormatter(tbLastHourStats?.[0].count || 62000000)}
+ {numberFormatter(tbLastHourStats?.data?.[0]?.count || 0)}
Pings in the last hour
@@ -27,7 +30,7 @@ export async function Stats() {
{/* {numberFormatter(totalActiveMonitors)} */}
- 2400+
+ 3400+
Active monitors
diff --git a/apps/web/src/components/marketing/status-page/tracker-example.tsx b/apps/web/src/components/marketing/status-page/tracker-example.tsx
index d8768d5df4..384abd1c2b 100644
--- a/apps/web/src/components/marketing/status-page/tracker-example.tsx
+++ b/apps/web/src/components/marketing/status-page/tracker-example.tsx
@@ -1,13 +1,10 @@
import Link from "next/link";
import { Suspense } from "react";
-import { OSTinybird } from "@openstatus/tinybird";
import { Button } from "@openstatus/ui/src/components/button";
import { Tracker } from "@/components/tracker/tracker";
-import { env } from "@/env";
-
-const tb = new OSTinybird({ token: env.TINY_BIRD_API_KEY });
+import { prepareStatusByPeriod } from "@/lib/tb";
export async function TrackerExample() {
return (
@@ -29,15 +26,10 @@ function ExampleTrackerFallback() {
}
async function ExampleTracker() {
- const data = await tb.endpointStatusPeriod("45d")(
- {
- monitorId: "1",
- },
- {
- revalidate: 600, // 10 minutes
- },
- );
+ const res = await prepareStatusByPeriod("45d").getData({
+ monitorId: "1",
+ });
- if (!data) return null;
- return
;
+ if (!res.data) return null;
+ return
;
}
diff --git a/apps/web/src/components/monitor-charts/chart-wrapper.tsx b/apps/web/src/components/monitor-charts/chart-wrapper.tsx
index eaa0102beb..cd80626c51 100644
--- a/apps/web/src/components/monitor-charts/chart-wrapper.tsx
+++ b/apps/web/src/components/monitor-charts/chart-wrapper.tsx
@@ -1,6 +1,5 @@
-import type { ResponseGraph } from "@openstatus/tinybird";
-
import type { Period, Quantile } from "@/lib/monitor/utils";
+import type { ResponseGraph } from "@/lib/tb";
import { Chart } from "./chart";
import { groupDataByTimestamp } from "./utils";
diff --git a/apps/web/src/components/monitor-charts/chart.tsx b/apps/web/src/components/monitor-charts/chart.tsx
index ccb3bcefb3..7c596f0e1b 100644
--- a/apps/web/src/components/monitor-charts/chart.tsx
+++ b/apps/web/src/components/monitor-charts/chart.tsx
@@ -4,9 +4,8 @@ import type { CustomTooltipProps, EventProps } from "@tremor/react";
import { LineChart } from "@tremor/react";
import { useState } from "react";
-import type { Region } from "@openstatus/tinybird";
-
import { cn } from "@/lib/utils";
+import type { Region } from "@openstatus/db/src/schema/constants";
import { dataFormatter, regionFormatter } from "./utils";
interface ChartProps {
diff --git a/apps/web/src/components/monitor-charts/combined-chart-wrapper.tsx b/apps/web/src/components/monitor-charts/combined-chart-wrapper.tsx
index 750bfe43b1..9b26667fd6 100644
--- a/apps/web/src/components/monitor-charts/combined-chart-wrapper.tsx
+++ b/apps/web/src/components/monitor-charts/combined-chart-wrapper.tsx
@@ -4,11 +4,7 @@ import { LineChart } from "lucide-react";
import { useMemo } from "react";
import type { Monitor, PublicMonitor } from "@openstatus/db/src/schema";
-import type {
- Region,
- ResponseGraph,
- ResponseTimeMetricsByRegion,
-} from "@openstatus/tinybird";
+
import { Toggle } from "@openstatus/ui";
import { columns } from "@/components/data-table/single-region/columns";
@@ -19,6 +15,8 @@ import { RegionsPreset } from "@/components/monitor-dashboard/region-preset";
import type { Interval, Period, Quantile } from "@/lib/monitor/utils";
import { usePreferredSettings } from "@/lib/preferred-settings/client";
import type { PreferredSettings } from "@/lib/preferred-settings/server";
+import type { ResponseGraph, ResponseTimeMetricsByRegion } from "@/lib/tb";
+import type { Region } from "@openstatus/db/src/schema/constants";
import { Chart } from "./chart";
import { groupDataByTimestamp } from "./utils";
diff --git a/apps/web/src/components/monitor-charts/region-table.tsx b/apps/web/src/components/monitor-charts/region-table.tsx
index 638eb5262b..999a1aff88 100644
--- a/apps/web/src/components/monitor-charts/region-table.tsx
+++ b/apps/web/src/components/monitor-charts/region-table.tsx
@@ -1,4 +1,3 @@
-import type { Region, ResponseTimeMetricsByRegion } from "@openstatus/tinybird";
import {
Table,
TableBody,
@@ -11,6 +10,8 @@ import {
import { flyRegionsDict } from "@openstatus/utils";
import { formatNumber } from "@/components/monitor-dashboard/metrics-card";
+import type { ResponseTimeMetricsByRegion } from "@/lib/tb";
+import type { Region } from "@openstatus/db/src/schema/constants";
import { SimpleChart } from "./simple-chart";
export interface RegionTableProps {
diff --git a/apps/web/src/components/monitor-charts/simple-chart-wrapper.tsx b/apps/web/src/components/monitor-charts/simple-chart-wrapper.tsx
index 271e5b12f7..b62a883c6b 100644
--- a/apps/web/src/components/monitor-charts/simple-chart-wrapper.tsx
+++ b/apps/web/src/components/monitor-charts/simple-chart-wrapper.tsx
@@ -1,6 +1,6 @@
-import type { Region, ResponseGraph } from "@openstatus/tinybird";
-
import type { Period, Quantile } from "@/lib/monitor/utils";
+import type { ResponseGraph } from "@/lib/tb";
+import type { Region } from "@openstatus/db/src/schema/constants";
import { SimpleChart } from "./simple-chart";
import { groupDataByTimestamp } from "./utils";
diff --git a/apps/web/src/components/monitor-charts/utils.tsx b/apps/web/src/components/monitor-charts/utils.tsx
index a7bc5f509e..32b3170dc6 100644
--- a/apps/web/src/components/monitor-charts/utils.tsx
+++ b/apps/web/src/components/monitor-charts/utils.tsx
@@ -1,9 +1,10 @@
import { format } from "date-fns";
-import type { Region, ResponseGraph } from "@openstatus/tinybird";
import { flyRegionsDict } from "@openstatus/utils";
import type { Period, Quantile } from "@/lib/monitor/utils";
+import type { ResponseGraph } from "@/lib/tb";
+import type { Region } from "@openstatus/db/src/schema/constants";
/**
*
diff --git a/apps/web/src/components/monitor-dashboard/metrics.tsx b/apps/web/src/components/monitor-dashboard/metrics.tsx
index d781aa6adb..7cd91cfe26 100644
--- a/apps/web/src/components/monitor-dashboard/metrics.tsx
+++ b/apps/web/src/components/monitor-dashboard/metrics.tsx
@@ -1,10 +1,9 @@
import { formatDistanceToNowStrict } from "date-fns";
import Link from "next/link";
-import type { LatencyMetric, ResponseTimeMetrics } from "@openstatus/tinybird";
-
import { periodFormatter } from "@/lib/monitor/utils";
import type { Period } from "@/lib/monitor/utils";
+import type { ResponseTimeMetrics } from "@/lib/tb";
import { MetricsCard } from "./metrics-card";
const metricsOrder = [
@@ -13,7 +12,7 @@ const metricsOrder = [
"p90Latency",
"p95Latency",
"p99Latency",
-] satisfies LatencyMetric[];
+] as const;
export function Metrics({
metrics,
diff --git a/apps/web/src/components/monitor-dashboard/region-preset.tsx b/apps/web/src/components/monitor-dashboard/region-preset.tsx
index 76ca53ca51..fb2ce9ad4e 100644
--- a/apps/web/src/components/monitor-dashboard/region-preset.tsx
+++ b/apps/web/src/components/monitor-dashboard/region-preset.tsx
@@ -3,7 +3,6 @@
import { Check, ChevronsUpDown, Globe2 } from "lucide-react";
import * as React from "react";
-import type { Region } from "@openstatus/tinybird";
import { Button, type ButtonProps } from "@openstatus/ui/src/components/button";
import {
Command,
@@ -26,7 +25,7 @@ import {
} from "@openstatus/utils";
import { cn } from "@/lib/utils";
-import { flyRegions } from "@openstatus/db/src/schema/constants";
+import { type Region, flyRegions } from "@openstatus/db/src/schema/constants";
import { parseAsArrayOf, parseAsStringLiteral, useQueryState } from "nuqs";
interface RegionsPresetProps extends ButtonProps {
diff --git a/apps/web/src/components/monitor-dashboard/response-details.tsx b/apps/web/src/components/monitor-dashboard/response-details.tsx
index 4bb1406b09..ec2288c886 100644
--- a/apps/web/src/components/monitor-dashboard/response-details.tsx
+++ b/apps/web/src/components/monitor-dashboard/response-details.tsx
@@ -1,8 +1,5 @@
// TODO: move to `ping-response-analysis`
-import { OSTinybird } from "@openstatus/tinybird";
-import type { ResponseDetailsParams } from "@openstatus/tinybird";
-
import {
Tabs,
TabsContent,
@@ -12,16 +9,30 @@ import {
import { RegionInfo } from "@/components/ping-response-analysis/region-info";
import { ResponseHeaderTable } from "@/components/ping-response-analysis/response-header-table";
import { ResponseTimingTable } from "@/components/ping-response-analysis/response-timing-table";
-import { env } from "@/env";
+import { prepareGetByPeriod } from "@/lib/tb";
+import type { Region } from "@openstatus/db/src/schema/constants";
+
+interface ResponseDetailsProps {
+ monitorId: string;
+ url?: string | undefined;
+ region?: Region;
+ cronTimestamp?: number | undefined;
+ type: "http" | "tcp";
+}
-const tb = new OSTinybird({ token: env.TINY_BIRD_API_KEY });
+export async function ResponseDetails({
+ type,
+ ...props
+}: ResponseDetailsProps) {
+ // FIXME: this has to be dynamic
+ const details = await prepareGetByPeriod("30d", type).getData(props);
-export async function ResponseDetails(props: ResponseDetailsParams) {
- const details = await tb.endpointResponseDetails("45d")(props);
+ if (!details.data || details.data.length === 0) return null;
- if (!details || details?.length === 0) return null;
+ const response = details.data[0];
- const response = details[0];
+ // FIXME: return the proper infos regarding TCP - but there are non right now anyways
+ if (response.type === "tcp") return null;
const { timing, headers, message, statusCode } = response;
diff --git a/apps/web/src/components/ping-response-analysis/multi-region-tabs.tsx b/apps/web/src/components/ping-response-analysis/multi-region-tabs.tsx
index d17f98cdde..7e6769bdd6 100644
--- a/apps/web/src/components/ping-response-analysis/multi-region-tabs.tsx
+++ b/apps/web/src/components/ping-response-analysis/multi-region-tabs.tsx
@@ -2,7 +2,7 @@
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@openstatus/ui";
-import type { Region } from "@openstatus/tinybird";
+import type { Region } from "@openstatus/db/src/schema/constants";
import type { Row } from "@tanstack/react-table";
import { RegionsPreset } from "../monitor-dashboard/region-preset";
import { columns } from "./columns";
diff --git a/apps/web/src/components/status-page/monitor.tsx b/apps/web/src/components/status-page/monitor.tsx
index a5a63d5a05..77c41f5c8c 100644
--- a/apps/web/src/components/status-page/monitor.tsx
+++ b/apps/web/src/components/status-page/monitor.tsx
@@ -6,12 +6,9 @@ import type {
PublicMonitor,
selectPublicStatusReportSchemaWithRelation,
} from "@openstatus/db/src/schema";
-import { OSTinybird } from "@openstatus/tinybird";
import { Tracker } from "@/components/tracker/tracker";
-import { env } from "@/env";
-
-const tb = new OSTinybird({ token: env.TINY_BIRD_API_KEY });
+import { prepareStatusByPeriod } from "@/lib/tb";
export const Monitor = async ({
monitor,
@@ -26,17 +23,20 @@ export const Monitor = async ({
maintenances: Maintenance[];
showValues?: boolean;
}) => {
- const data = await tb.endpointStatusPeriod("45d")({
+ const res = await prepareStatusByPeriod(
+ "45d",
+ monitor.jobType as "http" | "tcp",
+ ).getData({
monitorId: String(monitor.id),
});
// TODO: we could handle the `statusReports` here instead of passing it down to the tracker
- if (!data) return
Something went wrong
;
+ if (!res.data) return
Something went wrong
;
return (
([]);
const [active, setActive] = React.useState();
const pathname = usePathname();
+ const [hasCopied, setHasCopied] = React.useState(false);
+
+ React.useEffect(() => {
+ if (hasCopied) {
+ setTimeout(() => {
+ setHasCopied(false);
+ }, 2000);
+ }
+ }, [hasCopied]);
React.useEffect(() => {
if (pathname?.split("/")?.[2] && workspaces.length > 0) {
@@ -63,11 +73,29 @@ export function SelectWorkspace() {
{workspace.slug}
+
{active === workspace.slug ? (
-
+
) : null}
diff --git a/apps/web/src/config/pricing-table.tsx b/apps/web/src/config/pricing-table.tsx
index 2bc3678dc3..9a4e3a4590 100644
--- a/apps/web/src/config/pricing-table.tsx
+++ b/apps/web/src/config/pricing-table.tsx
@@ -12,7 +12,7 @@ function renderChangelogDescription(slug: Changelog["slug"]) {
{changelog?.description}{" "}
Learn more
diff --git a/apps/web/src/lib/monitor/utils.ts b/apps/web/src/lib/monitor/utils.ts
index 40dfae91cd..23bceae658 100644
--- a/apps/web/src/lib/monitor/utils.ts
+++ b/apps/web/src/lib/monitor/utils.ts
@@ -9,7 +9,7 @@ import {
import type { MonitorPeriodicity } from "@openstatus/db/src/schema";
-export const periods = ["1h", "1d", "3d", "7d", "14d"] as const; // If neeeded (e.g. Pro plans), "7d", "30d"
+export const periods = ["1d", "7d", "14d"] as const; // If neeeded (e.g. Pro plans), "7d", "30d"
export const quantiles = ["p99", "p95", "p90", "p75", "p50"] as const;
export const intervals = ["1m", "10m", "30m", "1h"] as const;
export const triggers = ["cron", "api"] as const;
@@ -21,21 +21,11 @@ export type Trigger = (typeof triggers)[number];
export function getDateByPeriod(period: Period) {
switch (period) {
- case "1h":
- return {
- from: subHours(startOfHour(new Date()), 1),
- to: endOfHour(new Date()),
- };
case "1d":
return {
from: subDays(startOfHour(new Date()), 1),
to: endOfDay(new Date()),
};
- case "3d":
- return {
- from: subDays(startOfDay(new Date()), 3),
- to: endOfDay(new Date()),
- };
case "7d":
return {
from: subDays(startOfDay(new Date()), 7),
@@ -55,12 +45,8 @@ export function getDateByPeriod(period: Period) {
export function getHoursByPeriod(period: Period) {
switch (period) {
- case "1h":
- return 1;
case "1d":
return 24;
- case "3d":
- return 72;
case "7d":
return 168;
case "14d":
@@ -74,12 +60,8 @@ export function getHoursByPeriod(period: Period) {
export function periodFormatter(period: Period) {
switch (period) {
- case "1h":
- return "Last hour";
case "1d":
return "Last day";
- case "3d":
- return "Last 3 days";
case "7d":
return "Last 7 days";
case "14d":
diff --git a/apps/web/src/lib/tb.ts b/apps/web/src/lib/tb.ts
index e45c3d9e74..b2d1e34224 100644
--- a/apps/web/src/lib/tb.ts
+++ b/apps/web/src/lib/tb.ts
@@ -1,17 +1,219 @@
-import type { HomeStatsParams } from "@openstatus/tinybird";
-import { Tinybird, getHomeStats } from "@openstatus/tinybird";
+import { OSTinybird } from "@openstatus/tinybird";
import { env } from "@/env";
-// @depreciated in favor to use the OSTinybird client directly
-const tb = new Tinybird({ token: env.TINY_BIRD_API_KEY });
+const tb = new OSTinybird(env.TINY_BIRD_API_KEY);
-export async function getHomeStatsData(props: Partial) {
- try {
- const res = await getHomeStats(tb)(props);
- return res.data;
- } catch (e) {
- console.error(e);
+// REMINDER: we could extend the limits (WorkspacePlan) by
+// knowing which plan the user is on and disable some periods
+const periods = ["1d", "7d", "14d"] as const;
+const types = ["http", "tcp"] as const;
+
+// FIXME: check we we can also use Period from elswhere
+type Period = (typeof periods)[number];
+// FIMXE: use JobType instead!
+type Type = (typeof types)[number];
+
+// REMINDER: extend if needed
+export function prepareListByPeriod(period: Period, type: Type = "http") {
+ switch (period) {
+ case "1d": {
+ const getData = {
+ http: tb.httpListDaily,
+ tcp: tb.tcpListDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "7d": {
+ const getData = {
+ http: tb.httpListWeekly,
+ tcp: tb.tcpListWeekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "14d": {
+ const getData = {
+ http: tb.httpListBiweekly,
+ tcp: tb.tcpListBiweekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ default: {
+ const getData = {
+ http: tb.httpListDaily,
+ tcp: tb.tcpListDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
+ }
+}
+
+export function prepareMetricsByPeriod(period: Period, type: Type = "http") {
+ switch (period) {
+ case "1d": {
+ const getData = {
+ http: tb.httpMetricsDaily,
+ tcp: tb.tcpMetricsDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "7d": {
+ const getData = {
+ http: tb.httpMetricsWeekly,
+ tcp: tb.tcpMetricsWeekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "14d": {
+ const getData = {
+ http: tb.httpMetricsBiweekly,
+ tcp: tb.tcpMetricsBiweekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ default: {
+ const getData = {
+ http: tb.httpMetricsDaily,
+ tcp: tb.tcpMetricsDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
+ }
+}
+
+export function prepareMetricByRegionByPeriod(
+ period: Period,
+ type: Type = "http",
+) {
+ switch (period) {
+ case "1d": {
+ const getData = {
+ http: tb.httpMetricsByRegionDaily,
+ tcp: tb.tcpMetricsByRegionDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "7d": {
+ const getData = {
+ http: tb.httpMetricsByRegionWeekly,
+ tcp: tb.tcpMetricsByRegionWeekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "14d": {
+ const getData = {
+ http: tb.httpMetricsByRegionBiweekly,
+ tcp: tb.tcpMetricsByRegionBiweekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ default: {
+ const getData = {
+ http: tb.httpMetricsByRegionDaily,
+ tcp: tb.tcpMetricsByRegionDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
+ }
+}
+
+export function prepareMetricByIntervalByPeriod(
+ period: Period,
+ type: Type = "http",
+) {
+ switch (period) {
+ case "1d": {
+ const getData = {
+ http: tb.httpMetricsByIntervalDaily,
+ tcp: tb.tcpMetricsByIntervalDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "7d": {
+ const getData = {
+ http: tb.httpMetricsByIntervalWeekly,
+ tcp: tb.tcpMetricsByIntervalWeekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "14d": {
+ const getData = {
+ http: tb.httpMetricsByIntervalBiweekly,
+ tcp: tb.tcpMetricsByIntervalBiweekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ default: {
+ const getData = {
+ http: tb.httpMetricsByIntervalDaily,
+ tcp: tb.tcpMetricsByIntervalDaily,
+ } as const;
+ return { getData: getData[type] };
+ }
}
- return;
}
+
+export function prepareStatusByPeriod(
+ period: "7d" | "45d",
+ type: Type = "http",
+) {
+ switch (period) {
+ case "7d": {
+ const getData = {
+ http: tb.httpStatusWeekly,
+ tcp: tb.tcpStatusWeekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ case "45d": {
+ const getData = {
+ http: tb.httpStatus45d,
+ tcp: tb.tcpStatus45d,
+ } as const;
+ return { getData: getData[type] };
+ }
+ default: {
+ const getData = {
+ http: tb.httpStatusWeekly,
+ tcp: tb.tcpStatusWeekly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ }
+}
+
+export function prepareGetByPeriod(period: "30d", type: Type = "http") {
+ switch (period) {
+ case "30d": {
+ const getData = {
+ http: tb.httpGetMonthly,
+ tcp: tb.tcpGetMonthly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ default: {
+ const getData = {
+ http: tb.httpGetMonthly,
+ tcp: tb.tcpGetMonthly,
+ } as const;
+ return { getData: getData[type] };
+ }
+ }
+}
+
+// FOR MIGRATION
+export type ResponseTimeMetrics = Awaited<
+ ReturnType
+>["data"][number];
+
+export type ResponseTimeMetricsByRegion = Awaited<
+ ReturnType
+>["data"][number];
+
+export type ResponseGraph = Awaited<
+ ReturnType
+>["data"][number];
+
+export type ResponseStatusTracker = Awaited<
+ ReturnType
+>["data"][number];
diff --git a/apps/web/src/trpc/rq-server.ts b/apps/web/src/trpc/rq-server.ts
index 9021f52974..6bd68a472d 100644
--- a/apps/web/src/trpc/rq-server.ts
+++ b/apps/web/src/trpc/rq-server.ts
@@ -9,7 +9,7 @@ import { cache } from "react";
import { makeQueryClient } from "./query-client";
const createContextCached = cache(
- async (...args: unknown[]): Promise => {
+ async (..._args: unknown[]): Promise => {
const session = await auth();
return {
diff --git a/packages/api/src/router/tinybird/index.ts b/packages/api/src/router/tinybird/index.ts
index 59a8a7c0b6..beefabfd09 100644
--- a/packages/api/src/router/tinybird/index.ts
+++ b/packages/api/src/router/tinybird/index.ts
@@ -6,66 +6,20 @@ import { flyRegions } from "@openstatus/db/src/schema/constants";
import { env } from "../../env";
import { createTRPCRouter, protectedProcedure } from "../../trpc";
-const tb = new OSTinybird({ token: env.TINY_BIRD_API_KEY });
+const tb = new OSTinybird(env.TINY_BIRD_API_KEY);
// WORK IN PROGRESS - we can create a tb router to call it via TRPC server and client
export const tinybirdRouter = createTRPCRouter({
- lastCronTimestamp: protectedProcedure.query(async (opts) => {
- const workspaceId = String(opts.ctx.workspace.id);
- return await tb.endpointLastCronTimestamp("workspace")({ workspaceId });
- }),
-
- monitorMetricsFromWorkspace: protectedProcedure
- .input(z.object({ period: z.string() }))
- .query(async (opts) => {
- const _workspaceId = String(opts.ctx.workspace.id);
- }),
-
- responseDetails: protectedProcedure
+ httpGetMonthly: protectedProcedure
.input(
z.object({
- monitorId: z.string().default("").optional(),
- url: z.string().url().optional(),
+ monitorId: z.string(),
region: z.enum(flyRegions).optional(),
cronTimestamp: z.number().int().optional(),
}),
)
.query(async (opts) => {
- return await tb.endpointResponseDetails("7d")(opts.input);
- }),
-
- totalRumMetricsForApplication: protectedProcedure
- .input(z.object({ dsn: z.string(), period: z.enum(["24h", "7d", "30d"]) }))
- .query(async (opts) => {
- return await tb.applicationRUMMetrics()(opts.input);
- }),
- rumMetricsForApplicationPerPage: protectedProcedure
- .input(z.object({ dsn: z.string(), period: z.enum(["24h", "7d", "30d"]) }))
- .query(async (opts) => {
- return await tb.applicationRUMMetricsPerPage()(opts.input);
- }),
-
- rumMetricsForPath: protectedProcedure
- .input(
- z.object({
- dsn: z.string(),
- path: z.string(),
- period: z.enum(["24h", "7d", "30d"]),
- }),
- )
- .query(async (opts) => {
- return await tb.applicationRUMMetricsForPath()(opts.input);
- }),
- sessionRumMetricsForPath: protectedProcedure
- .input(
- z.object({
- dsn: z.string(),
- path: z.string(),
- period: z.enum(["24h", "7d", "30d"]),
- }),
- )
- .query(async (opts) => {
- return await tb.applicationSessionMetricsPerPath()(opts.input);
+ return await tb.httpGetMonthly(opts.input);
}),
});
diff --git a/packages/db/src/schema/constants.ts b/packages/db/src/schema/constants.ts
index a3b8370036..be335a7b82 100644
--- a/packages/db/src/schema/constants.ts
+++ b/packages/db/src/schema/constants.ts
@@ -52,4 +52,6 @@ export const monitorRegions = [...flyRegions] as const;
export const monitorPeriodicitySchema = z.enum(monitorPeriodicity);
export const monitorRegionSchema = z.enum(monitorRegions);
export const monitorFlyRegionSchema = z.enum(flyRegions);
+
export type MonitorFlyRegion = z.infer;
+export type Region = z.infer;
diff --git a/packages/tinybird/README.md b/packages/tinybird/README.md
index 00a23b0797..d0a7b63209 100644
--- a/packages/tinybird/README.md
+++ b/packages/tinybird/README.md
@@ -33,3 +33,20 @@ tb pipe rm tb_datasource_union.pipe --yes
Link to the [issue](https://github.com/openstatusHQ/openstatus/issues/278) from
Gonzalo as reference.
+
+
+
+
+```bash
+python3 -m venv .venv
+source .venv/bin/activate
+pip install tinybird-cli
+tb auth -i
+```
+
+```bash
+tb pull
+tb push aggregate_*.pipe --populate
+tb push endpoint_*.pipe
+...
+```
\ No newline at end of file
diff --git a/packages/tinybird/pipes/aggregate__http_14d.pipe b/packages/tinybird/pipes/aggregate__http_14d.pipe
new file mode 100644
index 0000000000..e546109c7d
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__http_14d.pipe
@@ -0,0 +1,28 @@
+VERSION 0
+
+TAGS http
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ statusCode,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM ping_response__v8
+
+TYPE materialized
+DATASOURCE mv__http_14d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(14)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__http_1d.pipe b/packages/tinybird/pipes/aggregate__http_1d.pipe
new file mode 100644
index 0000000000..cfb10ba85f
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__http_1d.pipe
@@ -0,0 +1,28 @@
+VERSION 0
+
+TAGS http
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ statusCode,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM ping_response__v8
+
+TYPE materialized
+DATASOURCE mv__http_1d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(1)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__http_30d.pipe b/packages/tinybird/pipes/aggregate__http_30d.pipe
new file mode 100644
index 0000000000..47e0f8fe2f
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__http_30d.pipe
@@ -0,0 +1,28 @@
+VERSION 0
+
+TAGS http
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ statusCode,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM ping_response__v8
+
+TYPE materialized
+DATASOURCE mv__http_30d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(30)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__http_7d.pipe b/packages/tinybird/pipes/aggregate__http_7d.pipe
new file mode 100644
index 0000000000..d28c19f4d3
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__http_7d.pipe
@@ -0,0 +1,28 @@
+VERSION 0
+
+TAGS http
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ statusCode,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM ping_response__v8
+
+TYPE materialized
+DATASOURCE mv__http_7d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(7)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__http_full_30d.pipe b/packages/tinybird/pipes/aggregate__http_full_30d.pipe
new file mode 100644
index 0000000000..02bb4c0662
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__http_full_30d.pipe
@@ -0,0 +1,23 @@
+VERSION 0
+DESCRIPTION >
+ Stores all the data from the http_response table for the last 30 days, mainly used for accessing the data details.
+
+
+TAGS http, full
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ *
+ FROM ping_response__v8
+
+TYPE materialized
+DATASOURCE mv__http_full_30d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(30)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__http_status_45d.pipe b/packages/tinybird/pipes/aggregate__http_status_45d.pipe
new file mode 100644
index 0000000000..8471609584
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__http_status_45d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS http, statuspage
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toStartOfDay(toTimeZone(fromUnixTimestamp64Milli(cronTimestamp), 'UTC')) AS time,
+ monitorId,
+ countState() AS count,
+ countState(if(error = 0, 1, NULL)) AS ok
+ FROM ping_response__v8
+ GROUP BY
+ time,
+ monitorId
+
+TYPE materialized
+DATASOURCE mv__http_status_45d__v0
+ENGINE "AggregatingMergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(45)"
+
diff --git a/packages/tinybird/pipes/aggregate__http_status_7d.pipe b/packages/tinybird/pipes/aggregate__http_status_7d.pipe
new file mode 100644
index 0000000000..e405385863
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__http_status_7d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS http, statuspage
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toStartOfDay(toTimeZone(fromUnixTimestamp64Milli(cronTimestamp), 'UTC')) AS time,
+ monitorId,
+ countState() AS count,
+ countState(if(error = 0, 1, NULL)) AS ok
+ FROM ping_response__v8
+ GROUP BY
+ time,
+ monitorId
+
+TYPE materialized
+DATASOURCE mv__http_status_7d__v0
+ENGINE "AggregatingMergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(7)"
+
diff --git a/packages/tinybird/pipes/aggregate__tcp_14d.pipe b/packages/tinybird/pipes/aggregate__tcp_14d.pipe
new file mode 100644
index 0000000000..8ca2e6107d
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__tcp_14d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS tcp
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM tcp_response__v0
+
+TYPE materialized
+DATASOURCE mv__tcp_14d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(14)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__tcp_1d.pipe b/packages/tinybird/pipes/aggregate__tcp_1d.pipe
new file mode 100644
index 0000000000..d8ab99284e
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__tcp_1d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS tcp
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM tcp_response__v0
+
+TYPE materialized
+DATASOURCE mv__tcp_1d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(1)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__tcp_30d.pipe b/packages/tinybird/pipes/aggregate__tcp_30d.pipe
new file mode 100644
index 0000000000..b7dd911c6b
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__tcp_30d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS tcp
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM tcp_response__v0
+
+TYPE materialized
+DATASOURCE mv__tcp_30d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(30)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__tcp_7d.pipe b/packages/tinybird/pipes/aggregate__tcp_7d.pipe
new file mode 100644
index 0000000000..659d2be498
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__tcp_7d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS tcp
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ latency,
+ error,
+ region,
+ trigger,
+ timestamp,
+ cronTimestamp,
+ monitorId,
+ workspaceId
+ FROM tcp_response__v0
+
+TYPE materialized
+DATASOURCE mv__tcp_7d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(7)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__tcp_full_30d.pipe b/packages/tinybird/pipes/aggregate__tcp_full_30d.pipe
new file mode 100644
index 0000000000..c89b654104
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__tcp_full_30d.pipe
@@ -0,0 +1,23 @@
+VERSION 0
+DESCRIPTION >
+ Stores all the data from the http_response table for the last 30 days, mainly used for accessing the data details.
+
+
+TAGS tcp, full
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toDateTime(fromUnixTimestamp64Milli(cronTimestamp)) AS time,
+ *
+ FROM tcp_response__v0
+
+TYPE materialized
+DATASOURCE mv__tcp_full_30d__v0
+ENGINE "MergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(30)"
+
+
diff --git a/packages/tinybird/pipes/aggregate__tcp_status_45d.pipe b/packages/tinybird/pipes/aggregate__tcp_status_45d.pipe
new file mode 100644
index 0000000000..b6159db046
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__tcp_status_45d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS tcp, statuspage
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toStartOfDay(toTimeZone(fromUnixTimestamp64Milli(cronTimestamp), 'UTC')) AS time,
+ monitorId,
+ countState() AS count,
+ countState(if(error = 0, 1, NULL)) AS ok
+ FROM tcp_response__v0
+ GROUP BY
+ time,
+ monitorId
+
+TYPE materialized
+DATASOURCE mv__tcp_status_45d__v0
+ENGINE "AggregatingMergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(45)"
+
diff --git a/packages/tinybird/pipes/aggregate__tcp_status_7d.pipe b/packages/tinybird/pipes/aggregate__tcp_status_7d.pipe
new file mode 100644
index 0000000000..bd16b1867e
--- /dev/null
+++ b/packages/tinybird/pipes/aggregate__tcp_status_7d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS tcp, statuspage
+
+NODE aggregate
+SQL >
+
+ SELECT
+ toStartOfDay(toTimeZone(fromUnixTimestamp64Milli(cronTimestamp), 'UTC')) AS time,
+ monitorId,
+ countState() AS count,
+ countState(if(error = 0, 1, NULL)) AS ok
+ FROM tcp_response__v0
+ GROUP BY
+ time,
+ monitorId
+
+TYPE materialized
+DATASOURCE mv__tcp_status_7d__v0
+ENGINE "AggregatingMergeTree"
+ENGINE_PARTITION_KEY "toYYYYMM(time)"
+ENGINE_SORTING_KEY "monitorId, time"
+ENGINE_TTL "time + toIntervalDay(7)"
+
diff --git a/packages/tinybird/pipes/dashboard_request.pipe b/packages/tinybird/pipes/dashboard_request.pipe
deleted file mode 100644
index 4319686453..0000000000
--- a/packages/tinybird/pipes/dashboard_request.pipe
+++ /dev/null
@@ -1,17 +0,0 @@
-VERSION 0
-NODE dashboard_request_0
-SQL >
-
- %
- SELECT * FROM monitor_request_count_7d_mv
- WHERE monitorId = {{ String(monitorId, '1') }}
- {% if defined(url) %} AND url = {{ String(url) }} {% end %}
-
-
-
-NODE dashboard_request_1
-SQL >
-
- SELECT * FROM dashboard_request_0
-
-
diff --git a/packages/tinybird/pipes/endpoint__http_get_30d.pipe b/packages/tinybird/pipes/endpoint__http_get_30d.pipe
new file mode 100644
index 0000000000..b9405fb0ee
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_get_30d.pipe
@@ -0,0 +1,18 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT *
+ FROM mv__http_full_30d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND cronTimestamp = {{ Int64(cronTimestamp, 1709477432205, required=True) }}
+ AND region = {{ String(region, 'ams', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_list_14d.pipe b/packages/tinybird/pipes/endpoint__http_list_14d.pipe
new file mode 100644
index 0000000000..21f6d74fa0
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_list_14d.pipe
@@ -0,0 +1,14 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT * FROM mv__http_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_list_1d.pipe b/packages/tinybird/pipes/endpoint__http_list_1d.pipe
new file mode 100644
index 0000000000..396ae8bd20
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_list_1d.pipe
@@ -0,0 +1,14 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT * FROM mv__http_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_list_7d.pipe b/packages/tinybird/pipes/endpoint__http_list_7d.pipe
new file mode 100644
index 0000000000..6df42e3411
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_list_7d.pipe
@@ -0,0 +1,14 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT * FROM mv__http_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_14d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_14d.pipe
new file mode 100644
index 0000000000..b2526a18fc
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_14d.pipe
@@ -0,0 +1,38 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ max(cronTimestamp) AS lastTimestamp
+ FROM mv__http_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 14 DAY, 3)
+ UNION ALL
+ SELECT
+ round(quantile(0.50)(latency)) AS p50Latency,
+ round(quantile(0.75)(latency)) AS p75Latency,
+ round(quantile(0.90)(latency)) AS p90Latency,
+ round(quantile(0.95)(latency)) AS p95Latency,
+ round(quantile(0.99)(latency)) AS p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ NULL as lastTimestamp -- no need to query the `lastTimestamp` as not relevant
+ FROM mv__http_30d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 28 DAY, 3)
+ AND time < toDateTime64(now() - INTERVAL 14 DAY, 3)
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_1d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_1d.pipe
new file mode 100644
index 0000000000..299302e995
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_1d.pipe
@@ -0,0 +1,38 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ max(cronTimestamp) AS lastTimestamp
+ FROM mv__http_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 1 DAY, 3)
+ UNION ALL
+ SELECT
+ round(quantile(0.50)(latency)) AS p50Latency,
+ round(quantile(0.75)(latency)) AS p75Latency,
+ round(quantile(0.90)(latency)) AS p90Latency,
+ round(quantile(0.95)(latency)) AS p95Latency,
+ round(quantile(0.99)(latency)) AS p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ NULL as lastTimestamp -- no need to query the `lastTimestamp` as not relevant
+ FROM mv__http_7d__v0 -- REMINDER: this will increase the processed data compared to 3d
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 2 DAY, 3)
+ AND time < toDateTime64(now() - INTERVAL 1 DAY, 3)
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_7d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_7d.pipe
new file mode 100644
index 0000000000..482638b114
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_7d.pipe
@@ -0,0 +1,38 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ max(cronTimestamp) AS lastTimestamp
+ FROM mv__http_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 7 DAY, 3)
+ UNION ALL
+ SELECT
+ round(quantile(0.50)(latency)) AS p50Latency,
+ round(quantile(0.75)(latency)) AS p75Latency,
+ round(quantile(0.90)(latency)) AS p90Latency,
+ round(quantile(0.95)(latency)) AS p95Latency,
+ round(quantile(0.99)(latency)) AS p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ NULL as lastTimestamp -- no need to query the `lastTimestamp` as not relevant
+ FROM mv__http_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 14 DAY, 3)
+ AND time < toDateTime64(now() - INTERVAL 7 DAY, 3)
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_by_interval_14d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_by_interval_14d.pipe
new file mode 100644
index 0000000000..19288eefa7
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_by_interval_14d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ toStartOfInterval(
+ toDateTime(cronTimestamp / 1000),
+ INTERVAL {{ Int64(interval, 30) }} MINUTE -- use 2880 (2d) in case you want the 1d summary for the regions
+ ) as h,
+ toUnixTimestamp64Milli(toDateTime64(h, 3)) as timestamp,
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency
+ FROM mv__http_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY h, region
+ ORDER BY h DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_by_interval_1d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_by_interval_1d.pipe
new file mode 100644
index 0000000000..f92d9fd606
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_by_interval_1d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ toStartOfInterval(
+ toDateTime(cronTimestamp / 1000),
+ INTERVAL {{ Int64(interval, 30) }} MINUTE -- use 2880 (2d) in case you want the 1d summary for the regions
+ ) as h,
+ toUnixTimestamp64Milli(toDateTime64(h, 3)) as timestamp,
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency
+ FROM mv__http_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY h, region
+ ORDER BY h DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_by_interval_7d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_by_interval_7d.pipe
new file mode 100644
index 0000000000..e8daaf42a3
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_by_interval_7d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ toStartOfInterval(
+ toDateTime(cronTimestamp / 1000),
+ INTERVAL {{ Int64(interval, 30) }} MINUTE -- use 2880 (2d) in case you want the 1d summary for the regions
+ ) as h,
+ toUnixTimestamp64Milli(toDateTime64(h, 3)) as timestamp,
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency
+ FROM mv__http_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY h, region
+ ORDER BY h DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_by_region_14d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_by_region_14d.pipe
new file mode 100644
index 0000000000..e4451473b3
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_by_region_14d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ round(quantile(0.5)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.9)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok
+ FROM mv__http_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY region
+
+
+
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_by_region_1d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_by_region_1d.pipe
new file mode 100644
index 0000000000..1390411b0b
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_by_region_1d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ round(quantile(0.5)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.9)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok
+ FROM mv__http_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY region
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_metrics_by_region_7d.pipe b/packages/tinybird/pipes/endpoint__http_metrics_by_region_7d.pipe
new file mode 100644
index 0000000000..2ea818314d
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_metrics_by_region_7d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ round(quantile(0.5)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.9)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok
+ FROM mv__http_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY region
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_status_45d.pipe b/packages/tinybird/pipes/endpoint__http_status_45d.pipe
new file mode 100644
index 0000000000..2ceece2aa4
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_status_45d.pipe
@@ -0,0 +1,22 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT time as day, countMerge(count) as count, countMerge(ok) as ok
+ FROM mv__http_status_45d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY day
+ ORDER BY day DESC
+ WITH FILL
+ FROM
+ toStartOfDay(toStartOfDay(toTimeZone(now(), 'UTC')))
+ TO toStartOfDay(
+ date_sub(DAY, 45, now())
+ ) STEP INTERVAL -1 DAY
+
+
diff --git a/packages/tinybird/pipes/endpoint__http_status_7d.pipe b/packages/tinybird/pipes/endpoint__http_status_7d.pipe
new file mode 100644
index 0000000000..9a01ad6a32
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__http_status_7d.pipe
@@ -0,0 +1,22 @@
+VERSION 0
+
+TAGS http
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT time as day, countMerge(count) as count, countMerge(ok) as ok
+ FROM mv__http_status_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY day
+ ORDER BY day DESC
+ WITH FILL
+ FROM
+ toStartOfDay(toStartOfDay(toTimeZone(now(), 'UTC')))
+ TO toStartOfDay(
+ date_sub(DAY, 7, now())
+ ) STEP INTERVAL -1 DAY
+
+
diff --git a/packages/tinybird/pipes/endpoint__stats_global.pipe b/packages/tinybird/pipes/endpoint__stats_global.pipe
new file mode 100644
index 0000000000..37a270a837
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__stats_global.pipe
@@ -0,0 +1,18 @@
+VERSION 0
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT COUNT(*) as count
+ FROM ping_response__v8
+ {% if defined(period) %}
+ {% if String(period) == "1h" %}
+ WHERE cronTimestamp > toUnixTimestamp(now() - INTERVAL 1 HOUR) * 1000
+ {% elif String(period) == "10m" %}
+ WHERE cronTimestamp > toUnixTimestamp(now() - INTERVAL 10 MINUTE) * 1000
+ {% else %}
+ WHERE cronTimestamp > 0
+ {% end %}
+ {% end %}
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_get_30d.pipe b/packages/tinybird/pipes/endpoint__tcp_get_30d.pipe
new file mode 100644
index 0000000000..b4b1e59dd8
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_get_30d.pipe
@@ -0,0 +1,18 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT *
+ FROM mv__tcp_full_30d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND cronTimestamp = {{ Int64(cronTimestamp, 1709477432205, required=True) }}
+ AND region = {{ String(region, 'ams', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_list_14d.pipe b/packages/tinybird/pipes/endpoint__tcp_list_14d.pipe
new file mode 100644
index 0000000000..490123de05
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_list_14d.pipe
@@ -0,0 +1,14 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT * FROM mv__tcp_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_list_1d.pipe b/packages/tinybird/pipes/endpoint__tcp_list_1d.pipe
new file mode 100644
index 0000000000..4f63aa1a96
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_list_1d.pipe
@@ -0,0 +1,14 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT * FROM mv__tcp_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_list_7d.pipe b/packages/tinybird/pipes/endpoint__tcp_list_7d.pipe
new file mode 100644
index 0000000000..88e0437957
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_list_7d.pipe
@@ -0,0 +1,14 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT * FROM mv__tcp_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ ORDER BY cronTimestamp DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_14d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_14d.pipe
new file mode 100644
index 0000000000..9fdf8db5cf
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_14d.pipe
@@ -0,0 +1,41 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ max(cronTimestamp) AS lastTimestamp
+ FROM mv__tcp_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ -- FIXME: we can reduce the data processed by using removing it entirely
+ -- because the query is useless as we are in the 14d context
+ -- TODO: check where we can reduce the data processed
+ AND time >= toDateTime64(now() - INTERVAL 14 DAY, 3)
+ UNION ALL
+ SELECT
+ round(quantile(0.50)(latency)) AS p50Latency,
+ round(quantile(0.75)(latency)) AS p75Latency,
+ round(quantile(0.90)(latency)) AS p90Latency,
+ round(quantile(0.95)(latency)) AS p95Latency,
+ round(quantile(0.99)(latency)) AS p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ NULL as lastTimestamp -- no need to query the `lastTimestamp` as not relevant
+ FROM mv__tcp_30d__v0 -- REMINDER: this will increase the processed data compared to 3d
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 28 DAY, 3)
+ AND time < toDateTime64(now() - INTERVAL 14 DAY, 3)
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_1d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_1d.pipe
new file mode 100644
index 0000000000..a1e600433a
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_1d.pipe
@@ -0,0 +1,38 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ max(cronTimestamp) AS lastTimestamp
+ FROM mv__tcp_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 1 DAY, 3)
+ UNION ALL
+ SELECT
+ round(quantile(0.50)(latency)) AS p50Latency,
+ round(quantile(0.75)(latency)) AS p75Latency,
+ round(quantile(0.90)(latency)) AS p90Latency,
+ round(quantile(0.95)(latency)) AS p95Latency,
+ round(quantile(0.99)(latency)) AS p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ NULL as lastTimestamp -- no need to query the `lastTimestamp` as not relevant
+ FROM mv__tcp_7d__v0 -- REMINDER: this will increase the processed data compared to 3d
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 2 DAY, 3)
+ AND time < toDateTime64(now() - INTERVAL 1 DAY, 3)
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_7d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_7d.pipe
new file mode 100644
index 0000000000..3a009c1dea
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_7d.pipe
@@ -0,0 +1,38 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ max(cronTimestamp) AS lastTimestamp
+ FROM mv__tcp_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 7 DAY, 3)
+ UNION ALL
+ SELECT
+ round(quantile(0.50)(latency)) AS p50Latency,
+ round(quantile(0.75)(latency)) AS p75Latency,
+ round(quantile(0.90)(latency)) AS p90Latency,
+ round(quantile(0.95)(latency)) AS p95Latency,
+ round(quantile(0.99)(latency)) AS p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok,
+ NULL as lastTimestamp -- no need to query the `lastTimestamp` as not relevant
+ FROM mv__tcp_14d__v0 -- REMINDER: this will increase the processed data compared to 3d
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ AND time >= toDateTime64(now() - INTERVAL 14 DAY, 3)
+ AND time < toDateTime64(now() - INTERVAL 7 DAY, 3)
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_14d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_14d.pipe
new file mode 100644
index 0000000000..590acbc138
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_14d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ toStartOfInterval(
+ toDateTime(cronTimestamp / 1000),
+ INTERVAL {{ Int64(interval, 30) }} MINUTE -- use 2880 (2d) in case you want the 1d summary for the regions
+ ) as h,
+ toUnixTimestamp64Milli(toDateTime64(h, 3)) as timestamp,
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency
+ FROM mv__tcp_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY h, region
+ ORDER BY h DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_1d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_1d.pipe
new file mode 100644
index 0000000000..6ce0802044
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_1d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ toStartOfInterval(
+ toDateTime(cronTimestamp / 1000),
+ INTERVAL {{ Int64(interval, 30) }} MINUTE -- use 2880 (2d) in case you want the 1d summary for the regions
+ ) as h,
+ toUnixTimestamp64Milli(toDateTime64(h, 3)) as timestamp,
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency
+ FROM mv__tcp_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY h, region
+ ORDER BY h DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_7d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_7d.pipe
new file mode 100644
index 0000000000..1436219738
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_by_interval_7d.pipe
@@ -0,0 +1,27 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ toStartOfInterval(
+ toDateTime(cronTimestamp / 1000),
+ INTERVAL {{ Int64(interval, 30) }} MINUTE -- use 2880 (2d) in case you want the 1d summary for the regions
+ ) as h,
+ toUnixTimestamp64Milli(toDateTime64(h, 3)) as timestamp,
+ round(quantile(0.50)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.90)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency
+ FROM mv__tcp_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY h, region
+ ORDER BY h DESC
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_14d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_14d.pipe
new file mode 100644
index 0000000000..dda3021d8a
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_14d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ round(quantile(0.5)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.9)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok
+ FROM mv__tcp_14d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY region
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_1d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_1d.pipe
new file mode 100644
index 0000000000..44b93ca14a
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_1d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ round(quantile(0.5)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.9)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok
+ FROM mv__tcp_1d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY region
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_7d.pipe b/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_7d.pipe
new file mode 100644
index 0000000000..b0f59a2de6
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_metrics_by_region_7d.pipe
@@ -0,0 +1,24 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT
+ region,
+ round(quantile(0.5)(latency)) as p50Latency,
+ round(quantile(0.75)(latency)) as p75Latency,
+ round(quantile(0.9)(latency)) as p90Latency,
+ round(quantile(0.95)(latency)) as p95Latency,
+ round(quantile(0.99)(latency)) as p99Latency,
+ count() as count,
+ count(if(error = 0, 1, NULL)) AS ok
+ FROM mv__tcp_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY region
+
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_status_45d.pipe b/packages/tinybird/pipes/endpoint__tcp_status_45d.pipe
new file mode 100644
index 0000000000..63d8707f74
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_status_45d.pipe
@@ -0,0 +1,22 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT time as day, countMerge(count) as count, countMerge(ok) as ok
+ FROM mv__tcp_status_45d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY day
+ ORDER BY day DESC
+ WITH FILL
+ FROM
+ toStartOfDay(toStartOfDay(toTimeZone(now(), 'UTC')))
+ TO toStartOfDay(
+ date_sub(DAY, 45, now())
+ ) STEP INTERVAL -1 DAY
+
+
diff --git a/packages/tinybird/pipes/endpoint__tcp_status_7d.pipe b/packages/tinybird/pipes/endpoint__tcp_status_7d.pipe
new file mode 100644
index 0000000000..f5fc07d99c
--- /dev/null
+++ b/packages/tinybird/pipes/endpoint__tcp_status_7d.pipe
@@ -0,0 +1,22 @@
+VERSION 0
+
+TAGS tcp
+
+NODE endpoint
+SQL >
+
+ %
+ SELECT time as day, countMerge(count) as count, countMerge(ok) as ok
+ FROM mv__tcp_status_7d__v0
+ WHERE
+ monitorId = {{ String(monitorId, '1', required=True) }}
+ GROUP BY day
+ ORDER BY day DESC
+ WITH FILL
+ FROM
+ toStartOfDay(toStartOfDay(toTimeZone(now(), 'UTC')))
+ TO toStartOfDay(
+ date_sub(DAY, 7, now())
+ ) STEP INTERVAL -1 DAY
+
+
diff --git a/packages/tinybird/pipes/home_stats.pipe b/packages/tinybird/pipes/home_stats.pipe
index f9e48c15d2..bdf885305b 100644
--- a/packages/tinybird/pipes/home_stats.pipe
+++ b/packages/tinybird/pipes/home_stats.pipe
@@ -5,7 +5,7 @@ SQL >
%
SELECT COUNT(*) as count
- FROM ping_response__v7
+ FROM ping_response__v8
{% if defined(period) %}
{% if String(period) == "1h" %}
WHERE cronTimestamp > toUnixTimestamp(now() - INTERVAL 1 HOUR) * 1000
diff --git a/packages/tinybird/src/client.ts b/packages/tinybird/src/client.ts
index 1b00ca3bc7..b6a41e7c8b 100644
--- a/packages/tinybird/src/client.ts
+++ b/packages/tinybird/src/client.ts
@@ -1,60 +1,682 @@
-import { Tinybird } from "@chronark/zod-bird";
-
-import {
- tbBuildHomeStats,
- tbBuildMonitorList,
- tbBuildPublicStatus,
- tbIngestPingResponse,
- tbParameterHomeStats,
- tbParameterMonitorList,
- tbParameterPublicStatus,
-} from "./validation";
-
-// REMINDER:
-const tb = new Tinybird({ token: process.env.TINY_BIRD_API_KEY || "" });
-
-export const publishPingResponse = tb.buildIngestEndpoint({
- datasource: "ping_response__v6",
- event: tbIngestPingResponse,
-});
-
-/**
- * @deprecated but still used in server - please use OSTinybird.endpointStatusPeriod
- */
-export function getMonitorList(tb: Tinybird) {
- return tb.buildPipe({
- pipe: "status_timezone__v1",
- parameters: tbParameterMonitorList,
- data: tbBuildMonitorList,
- opts: {
- // cache: "no-store",
- next: {
- revalidate: 600, // 10 min cache
- },
- },
- });
-}
+import { Tinybird as Client, NoopTinybird } from "@chronark/zod-bird";
+import { z } from "zod";
+import { flyRegions } from "../../db/src/schema/constants";
+import { headersSchema, timingSchema, triggers } from "./schema";
+
+export class OSTinybird {
+ private readonly tb: Client;
-/**
- * Homepage stats used for our marketing page
- */
-export function getHomeStats(tb: Tinybird) {
- return tb.buildPipe({
- pipe: "home_stats__v0",
- parameters: tbParameterHomeStats,
- data: tbBuildHomeStats,
- opts: {
- next: {
- revalidate: 43200, // 60 * 60 * 24 = 86400s = 12h
+ constructor(token: string) {
+ // if (process.env.NODE_ENV === "development") {
+ // this.tb = new NoopTinybird();
+ // } else {
+ this.tb = new Client({ token });
+ // }
+ }
+
+ public get homeStats() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__stats_global__v0",
+ parameters: z.object({
+ cronTimestamp: z.number().int().optional(),
+ period: z.enum(["total", "1h", "10m"]).optional(),
+ }),
+ data: z.object({
+ count: z.number().int(),
+ }),
+ opts: {
+ next: {
+ revalidate: 43200, // 60 * 60 * 24 = 86400s = 12h
+ },
},
- },
- });
-}
+ });
+ }
+
+ public get httpListDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_list_1d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ type: z.literal("http").default("http"),
+ latency: z.number().int(),
+ statusCode: z.number().int().nullable(),
+ monitorId: z.string(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpListWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_list_7d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ type: z.literal("http").default("http"),
+ latency: z.number().int(),
+ statusCode: z.number().int().nullable(),
+ monitorId: z.string(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpListBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_list_14d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ type: z.literal("http").default("http"),
+ latency: z.number().int(),
+ statusCode: z.number().int().nullable(),
+ monitorId: z.string(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_1d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ count: z.number().int(),
+ ok: z.number().int(),
+ lastTimestamp: z.number().int().nullable(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_7d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ count: z.number().int(),
+ ok: z.number().int(),
+ lastTimestamp: z.number().int().nullable(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_14d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ count: z.number().int(),
+ ok: z.number().int(),
+ lastTimestamp: z.number().int().nullable(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsByIntervalDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_by_interval_1d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ timestamp: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsByIntervalWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_by_interval_7d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ timestamp: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsByIntervalBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_by_interval_14d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ timestamp: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsByRegionDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_by_region_1d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ count: z.number().int(),
+ ok: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsByRegionWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_by_region_7d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ count: z.number().int(),
+ ok: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpMetricsByRegionBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_metrics_by_region_14d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ count: z.number().int(),
+ ok: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpStatusWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_status_7d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ day: z.string().transform((val) => {
+ // That's a hack because clickhouse return the date in UTC but in shitty format (2021-09-01 00:00:00)
+ return new Date(`${val} GMT`).toISOString();
+ }),
+ count: z.number().default(0),
+ ok: z.number().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpStatus45d() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_status_45d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ day: z.string().transform((val) => {
+ // That's a hack because clickhouse return the date in UTC but in shitty format (2021-09-01 00:00:00)
+ return new Date(`${val} GMT`).toISOString();
+ }),
+ count: z.number().default(0),
+ ok: z.number().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get httpGetMonthly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__http_get_30d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ region: z.enum(flyRegions).optional(),
+ cronTimestamp: z.number().int().optional(),
+ }),
+ data: z.object({
+ type: z.literal("http").default("http"),
+ latency: z.number().int(),
+ statusCode: z.number().int().nullable(),
+ monitorId: z.string(),
+ url: z.string().url(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ message: z.string().nullable(),
+ headers: headersSchema,
+ timing: timingSchema,
+ assertions: z.string().nullable(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ // FIXME: rename to same convension
+ public get getResultForOnDemandCheckHttp() {
+ return this.tb.buildPipe({
+ pipe: "get_result_for_on_demand_check_http",
+ parameters: z.object({
+ monitorId: z.number().int(),
+ timestamp: z.number(),
+ url: z.string(),
+ }),
+ data: z.object({
+ latency: z.number().int(), // in ms
+ statusCode: z.number().int().nullable().default(null),
+ monitorId: z.string().default(""),
+ url: z.string().url().optional(),
+ error: z
+ .number()
+ .default(0)
+ .transform((val) => val !== 0),
+ region: z.enum(flyRegions),
+ timestamp: z.number().int().optional(),
+ message: z.string().nullable().optional(),
+ timing: timingSchema,
+ // TODO: make sure to include all data!
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+ // TODO: add tcpChartDaily, tcpChartWeekly
+
+ public get tcpListDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_list_1d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ type: z.literal("tcp").default("tcp"),
+ latency: z.number().int(),
+ monitorId: z.coerce.string(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.coerce.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpListWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_list_7d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ type: z.literal("tcp").default("tcp"),
+ latency: z.number().int(),
+ monitorId: z.coerce.string(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.coerce.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpListBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_list_14d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ type: z.literal("tcp").default("tcp"),
+ latency: z.number().int(),
+ monitorId: z.coerce.string(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.coerce.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_1d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ count: z.number().int(),
+ ok: z.number().int(),
+ lastTimestamp: z.number().int().nullable(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_7d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ count: z.number().int(),
+ ok: z.number().int(),
+ lastTimestamp: z.number().int().nullable(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_14d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ count: z.number().int(),
+ ok: z.number().int(),
+ lastTimestamp: z.number().int().nullable(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsByIntervalDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_by_interval_1d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ timestamp: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsByIntervalWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_by_interval_7d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ timestamp: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsByIntervalBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_by_interval_14d__v0",
+ parameters: z.object({
+ interval: z.number().int().optional(),
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ timestamp: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsByRegionDaily() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_by_region_1d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ count: z.number().int(),
+ ok: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsByRegionWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_by_region_7d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ count: z.number().int(),
+ ok: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpMetricsByRegionBiweekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_metrics_by_region_14d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ region: z.enum(flyRegions),
+ count: z.number().int(),
+ ok: z.number().int(),
+ p50Latency: z.number().nullable().default(0),
+ p75Latency: z.number().nullable().default(0),
+ p90Latency: z.number().nullable().default(0),
+ p95Latency: z.number().nullable().default(0),
+ p99Latency: z.number().nullable().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpStatusWeekly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_status_7d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ day: z.string().transform((val) => {
+ // That's a hack because clickhouse return the date in UTC but in shitty format (2021-09-01 00:00:00)
+ return new Date(`${val} GMT`).toISOString();
+ }),
+ count: z.number().default(0),
+ ok: z.number().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
+
+ public get tcpStatus45d() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_status_45d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ }),
+ data: z.object({
+ day: z.string().transform((val) => {
+ // That's a hack because clickhouse return the date in UTC but in shitty format (2021-09-01 00:00:00)
+ return new Date(`${val} GMT`).toISOString();
+ }),
+ count: z.number().default(0),
+ ok: z.number().default(0),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
-export function getPublicStatus(tb: Tinybird) {
- return tb.buildPipe({
- pipe: "public_status__v0",
- parameters: tbParameterPublicStatus,
- data: tbBuildPublicStatus,
- });
+ public get tcpGetMonthly() {
+ return this.tb.buildPipe({
+ pipe: "endpoint__tcp_get_30d__v0",
+ parameters: z.object({
+ monitorId: z.string(),
+ region: z.enum(flyRegions).optional(),
+ cronTimestamp: z.number().int().optional(),
+ }),
+ data: z.object({
+ type: z.literal("tcp").default("tcp"),
+ latency: z.number().int(),
+ monitorId: z.string(),
+ error: z.coerce.boolean(),
+ region: z.enum(flyRegions),
+ cronTimestamp: z.number().int(),
+ trigger: z.enum(triggers).nullable().default("cron"),
+ timestamp: z.number(),
+ workspaceId: z.string(),
+ }),
+ opts: { cache: "no-store" },
+ });
+ }
}
diff --git a/packages/tinybird/src/index.ts b/packages/tinybird/src/index.ts
index d00db50676..9991ce7fa3 100644
--- a/packages/tinybird/src/index.ts
+++ b/packages/tinybird/src/index.ts
@@ -1,7 +1,3 @@
export * from "./client";
-export * from "./validation";
export * from "./audit-log";
export * from "@chronark/zod-bird";
-
-// OSTinybird: for specific pipes
-export * from "./os-client";
diff --git a/packages/tinybird/src/os-client.ts b/packages/tinybird/src/os-client.ts
deleted file mode 100644
index e21dc3005f..0000000000
--- a/packages/tinybird/src/os-client.ts
+++ /dev/null
@@ -1,514 +0,0 @@
-import { NoopTinybird, Tinybird } from "@chronark/zod-bird";
-import { z } from "zod";
-
-import { flyRegions } from "../../db/src/schema/constants";
-
-import type { tbIngestWebVitalsArray } from "./validation";
-import {
- responseRumPageQuery,
- sessionRumPageQuery,
- tbIngestWebVitals,
-} from "./validation";
-
-const isProd = process.env.NODE_ENV === "production";
-
-const DEV_CACHE = 3_600; // 1h
-
-const MIN_CACHE = isProd ? 60 : DEV_CACHE; // 60s
-const DEFAULT_CACHE = isProd ? 120 : DEV_CACHE; // 2min
-const _MAX_CACHE = 86_400; // 1d
-
-const VERSION = "v1";
-
-export const latencySchema = z.object({
- p50Latency: z.number().int().nullable(),
- p75Latency: z.number().int().nullable(),
- p90Latency: z.number().int().nullable(),
- p95Latency: z.number().int().nullable(),
- p99Latency: z.number().int().nullable(),
-});
-
-export const timingSchema = z.object({
- dnsStart: z.number(),
- dnsDone: z.number(),
- connectStart: z.number(),
- connectDone: z.number(),
- tlsHandshakeStart: z.number(),
- tlsHandshakeDone: z.number(),
- firstByteStart: z.number(),
- firstByteDone: z.number(),
- transferStart: z.number(),
- transferDone: z.number(),
-});
-
-export class OSTinybird {
- private tb: Tinybird;
-
- // FIXME: use Tinybird instead with super(args) maybe
- // how about passing here the `opts: {revalidate}` to access it within the functions?
- constructor(private args: { token: string; baseUrl?: string | undefined }) {
- if (process.env.NODE_ENV === "development") {
- this.tb = new NoopTinybird();
- } else {
- this.tb = new Tinybird(args);
- }
- }
-
- endpointChart(period: "1h" | "1d" | "3d" | "7d" | "14d") {
- const parameters = z.object({
- interval: z.number().int().optional(),
- monitorId: z.string(),
- });
-
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_${period}_chart_get__${VERSION}`,
- parameters,
- data: z
- .object({
- region: z.enum(flyRegions),
- timestamp: z.number().int(),
- })
- .merge(latencySchema),
- opts: {
- cache: "no-store",
- // next: {
- // revalidate: DEFAULT_CACHE,
- // },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- endpointChartAllRegions(period: "7d" | "14d") {
- const parameters = z.object({
- monitorId: z.string(),
- });
-
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_${period}_chart_all_regions_get__${VERSION}`, // TODO: add pipe to @openstatus/tinybird
- parameters,
- data: z.object({ timestamp: z.number().int() }).merge(latencySchema),
- opts: {
- cache: "no-store",
- // next: {
- // revalidate: DEFAULT_CACHE,
- // },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- endpointMetrics(period: "1h" | "1d" | "3d" | "7d" | "14d") {
- const parameters = z.object({ monitorId: z.string() });
-
- return async (
- props: z.infer,
- opts?: {
- cache?: RequestCache | undefined;
- revalidate: number | undefined;
- }, // RETHINK: not the best way to handle it
- ) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_${period}_metrics_get__${VERSION}`,
- parameters,
- data: z
- .object({
- region: z.enum(flyRegions).default("ams"), // FIXME: default
- count: z.number().default(0),
- ok: z.number().default(0),
- lastTimestamp: z.number().int().nullable(),
- })
- .merge(latencySchema),
- opts: {
- cache: opts?.cache,
- next: {
- revalidate: opts?.revalidate || DEFAULT_CACHE,
- },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- endpointMetricsByRegion(period: "1h" | "1d" | "3d" | "7d" | "14d") {
- const parameters = z.object({ monitorId: z.string() });
-
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_${period}_metrics_get_by_region__${VERSION}`,
- parameters,
- data: z
- .object({
- region: z.enum(flyRegions),
- count: z.number().default(0),
- ok: z.number().default(0),
- lastTimestamp: z.number().int().optional(), // FIXME: optional
- })
- .merge(latencySchema),
- opts: {
- cache: "no-store",
- // next: {
- // revalidate: DEFAULT_CACHE,
- // },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- endpointStatusPeriod(
- period: "7d" | "45d",
- timezone: "UTC" = "UTC", // "EST" | "PST" | "CET"
- ) {
- const parameters = z.object({ monitorId: z.string() });
-
- return async (
- props: z.infer,
- opts?: {
- cache?: RequestCache | undefined;
- revalidate: number | undefined;
- }, // RETHINK: not the best way to handle it
- ) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_${period}_count_${timezone.toLowerCase()}_get__${VERSION}`,
- parameters,
- data: z.object({
- day: z.string().transform((val) => {
- // That's a hack because clickhouse return the date in UTC but in shitty format (2021-09-01 00:00:00)
- return new Date(`${val} GMT`).toISOString();
- }),
- count: z.number().default(0),
- ok: z.number().default(0),
- }),
- opts: {
- cache: opts?.cache,
- next: {
- revalidate: opts?.revalidate || DEFAULT_CACHE,
- },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- endpointList(period: "1h" | "1d" | "3d" | "7d") {
- const parameters = z.object({
- monitorId: z.string(),
- });
-
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_${period}_list_get__${VERSION}`,
- parameters,
- data: z.object({
- latency: z.number().int(), // in ms
- monitorId: z.string(),
- region: z.enum(flyRegions),
- error: z
- .number()
- .default(0)
- .transform((val) => val !== 0),
- statusCode: z.number().int().nullable().default(null),
- timestamp: z.number().int(),
- url: z.string().url(),
- workspaceId: z.string(),
- cronTimestamp: z.number().int().nullable().default(Date.now()),
- assertions: z.string().nullable().optional(),
- trigger: z
- .enum(["cron", "api"])
- .optional()
- .nullable()
- .default("cron"),
- }),
- opts: {
- cache: "no-store",
- // next: {
- // revalidate: DEFAULT_CACHE,
- // },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- // FEATURE: include a simple Widget for the user to refresh the page or display on the top of the page
- // type: "workspace" | "monitor"
- endpointLastCronTimestamp(type: "workspace") {
- const parameters = z.object({ workspaceId: z.string() });
-
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_1h_last_timestamp_${type}_get__${VERSION}`,
- parameters,
- data: z.object({ cronTimestamp: z.number().int() }),
- opts: {
- next: {
- revalidate: MIN_CACHE,
- },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- endpointResponseDetails(period: "7d" | "45d") {
- const parameters = z.object({
- monitorId: z.string().default("").optional(),
- region: z.enum(flyRegions).optional(),
- cronTimestamp: z.number().int().optional(),
- });
-
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: `__ttl_${period}_all_details_get__${VERSION}`,
- parameters,
- data: z.object({
- latency: z.number().int(), // in ms
- statusCode: z.number().int().nullable().default(null),
- monitorId: z.string().default(""),
- url: z.string().url().optional(),
- error: z
- .number()
- .default(0)
- .transform((val) => val !== 0),
- region: z.enum(flyRegions),
- cronTimestamp: z.number().int().optional(),
- message: z.string().nullable().optional(),
- headers: z
- .string()
- .nullable()
- .optional()
- .transform((val) => {
- if (!val) return null;
- const value = z
- .record(z.string(), z.string())
- .safeParse(JSON.parse(val));
- if (value.success) return value.data;
- return null;
- }),
- timing: z
- .string()
- .nullable()
- .optional()
- .transform((val) => {
- if (!val) return null;
- const value = timingSchema.safeParse(JSON.parse(val));
- if (value.success) return value.data;
- return null;
- }),
- assertions: z.string().nullable().optional(), // REMINDER: maybe include Assertions.serialize here
- }),
- opts: {
- cache: "no-store",
- // next: {
- // revalidate: MAX_CACHE,
- // },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
- ingestWebVitals(data: z.infer) {
- return this.tb.buildIngestEndpoint({
- datasource: "web_vitals__v0",
- event: tbIngestWebVitals,
- })(data);
- }
-
- applicationRUMMetrics() {
- const parameters = z.object({
- dsn: z.string(),
- period: z.enum(["24h", "7d", "30d"]),
- });
-
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: "rum_total_query",
- parameters,
- data: z.object({
- cls: z.number(),
- fcp: z.number(),
- // fid: z.number(),
- lcp: z.number(),
- inp: z.number(),
- ttfb: z.number(),
- }),
- opts: {
- next: {
- revalidate: MIN_CACHE,
- },
- },
- })(props);
- return res.data[0];
- } catch (e) {
- console.error(e);
- }
- };
- }
- applicationRUMMetricsPerPage() {
- const parameters = z.object({
- dsn: z.string(),
- period: z.enum(["24h", "7d", "30d"]),
- });
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: "rum_page_query",
- parameters,
- data: responseRumPageQuery,
- opts: {
- next: {
- revalidate: MIN_CACHE,
- },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
- applicationSessionMetricsPerPath() {
- const parameters = z.object({
- dsn: z.string(),
- period: z.enum(["24h", "7d", "30d"]),
- path: z.string(),
- });
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: "rum_page_query_per_path",
- parameters,
- data: sessionRumPageQuery,
- opts: {
- next: {
- revalidate: MIN_CACHE,
- },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
- applicationRUMMetricsForPath() {
- const parameters = z.object({
- dsn: z.string(),
- path: z.string(),
- period: z.enum(["24h", "7d", "30d"]),
- });
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: "rum_total_query_per_path",
- parameters,
- data: z.object({
- cls: z.number(),
- fcp: z.number(),
- // fid: z.number(),
- lcp: z.number(),
- inp: z.number(),
- ttfb: z.number(),
- }),
- opts: {
- next: {
- revalidate: MIN_CACHE,
- },
- },
- })(props);
- return res.data[0];
- } catch (e) {
- console.error(e);
- }
- };
- }
-
- getResultForOnDemandCheckHttp() {
- const parameters = z.object({
- monitorId: z.number().int(),
- timestamp: z.number(),
- url: z.string(),
- });
- return async (props: z.infer) => {
- try {
- const res = await this.tb.buildPipe({
- pipe: "get_result_for_on_demand_check_http",
- parameters,
- data: z.object({
- latency: z.number().int(), // in ms
- statusCode: z.number().int().nullable().default(null),
- monitorId: z.string().default(""),
- url: z.string().url().optional(),
- error: z
- .number()
- .default(0)
- .transform((val) => val !== 0),
- region: z.enum(flyRegions),
- timestamp: z.number().int().optional(),
- message: z.string().nullable().optional(),
- timing: z
- .string()
- .nullable()
- .optional()
- .transform((val) => {
- if (!val) return null;
- const value = timingSchema.safeParse(JSON.parse(val));
- if (value.success) return value.data;
- return null;
- }),
- }),
- opts: {
- next: {
- revalidate: MIN_CACHE,
- },
- },
- })(props);
- return res.data;
- } catch (e) {
- console.error(e);
- }
- };
- }
-}
-
-/**
- * TODO: if it would be possible to...
- */
diff --git a/packages/tinybird/src/schema.ts b/packages/tinybird/src/schema.ts
new file mode 100644
index 0000000000..9fd895bdaf
--- /dev/null
+++ b/packages/tinybird/src/schema.ts
@@ -0,0 +1,48 @@
+import { z } from "zod";
+
+export const jobTypes = ["http", "tcp", "imcp", "udp", "dns", "ssl"] as const;
+export const jobTypeEnum = z.enum(jobTypes);
+export type JobType = z.infer;
+
+export const periods = ["1h", "1d", "3d", "7d", "14d", "45d"] as const;
+export const periodEnum = z.enum(periods);
+export type Period = z.infer;
+
+export const triggers = ["cron", "api"] as const;
+export const triggerEnum = z.enum(triggers);
+export type Trigger = z.infer;
+
+export const headersSchema = z
+ .string()
+ .nullable()
+ .optional()
+ .transform((val) => {
+ if (!val) return null;
+ const value = z.record(z.string(), z.string()).safeParse(JSON.parse(val));
+ if (value.success) return value.data;
+ return null;
+ });
+
+export const httpTimingSchema = z.object({
+ dnsStart: z.number(),
+ dnsDone: z.number(),
+ connectStart: z.number(),
+ connectDone: z.number(),
+ tlsHandshakeStart: z.number(),
+ tlsHandshakeDone: z.number(),
+ firstByteStart: z.number(),
+ firstByteDone: z.number(),
+ transferStart: z.number(),
+ transferDone: z.number(),
+});
+
+export const timingSchema = z
+ .string()
+ .nullable()
+ .optional()
+ .transform((val) => {
+ if (!val) return null;
+ const value = httpTimingSchema.safeParse(JSON.parse(val));
+ if (value.success) return value.data;
+ return null;
+ });
diff --git a/packages/tinybird/src/validation.ts b/packages/tinybird/src/validation.ts
deleted file mode 100644
index e769212f80..0000000000
--- a/packages/tinybird/src/validation.ts
+++ /dev/null
@@ -1,308 +0,0 @@
-import * as z from "zod";
-import { monitorFlyRegionSchema } from "../../db/src/schema/constants";
-import type { flyRegions } from "../../db/src/schema/constants";
-
-export const tbIngestWebVitals = z.object({
- dsn: z.string(),
- href: z.string(),
- speed: z.string(),
- path: z.string(),
- screen: z.string(),
- name: z.string(),
- rating: z.string().optional(),
- value: z.number(),
- id: z.string(),
- session_id: z.string(),
- browser: z.string().default(""),
- city: z.string().default(""),
- country: z.string().default(""),
- continent: z.string().default(""),
- device: z.string().default(""),
- region_code: z.string().default(""),
- timezone: z.string().default(""),
- os: z.string(),
- timestamp: z.number().int(),
-});
-
-export const responseRumPageQuery = z.object({
- path: z.string(),
- totalSession: z.number(),
- cls: z.number(),
- fcp: z.number(),
- // fid: z.number(),
- inp: z.number(),
- lcp: z.number(),
- ttfb: z.number(),
-});
-
-export const sessionRumPageQuery = z.object({
- session_id: z.string(),
- cls: z.number(),
- fcp: z.number(),
- // fid: z.number(),
- inp: z.number(),
- lcp: z.number(),
- ttfb: z.number(),
-});
-
-export const tbIngestWebVitalsArray = z.array(tbIngestWebVitals);
-/**
- * Values for the datasource ping_response
- */
-export const tbIngestPingResponse = z.object({
- workspaceId: z.string(),
- monitorId: z.string(),
- timestamp: z.number().int(),
- statusCode: z.number().int().nullable().optional(),
- latency: z.number(), // in ms
- cronTimestamp: z.number().int().optional().nullable().default(Date.now()),
- url: z.string().url(),
- region: z.string().min(3).max(4), // REMINDER: won't work on fy
- message: z.string().nullable().optional(),
- headers: z.record(z.string(), z.string()).nullable().optional(),
- timing: z
- .object({
- dnsStart: z.number().int(),
- dnsDone: z.number().int(),
- connectStart: z.number().int(),
- connectDone: z.number().int(),
- tlsHandshakeStart: z.number().int(),
- tlsHandshakeDone: z.number().int(),
- firstByteStart: z.number().int(),
- firstByteDone: z.number().int(),
- transferStart: z.number().int(),
- transferDone: z.number().int(),
- })
- .nullable()
- .optional(),
-});
-
-/**
- * Values from the pipe response_list
- */
-export const tbBuildResponseList = z.object({
- workspaceId: z.string(),
- monitorId: z.string(),
- timestamp: z.number().int(),
- error: z
- .number()
- .default(0)
- .transform((val) => val !== 0),
- statusCode: z.number().int().nullable().default(null),
- latency: z.number().int(), // in ms
- cronTimestamp: z.number().int().nullable().default(Date.now()),
- url: z.string().url(),
- region: monitorFlyRegionSchema,
- message: z.string().nullable().optional(),
- assertions: z.string().nullable().optional(),
- trigger: z.enum(["cron", "api"]).optional().nullable().default("cron"),
-});
-
-/**
- * Params for pipe response_list
- */
-export const tbParameterResponseList = z.object({
- monitorId: z.string().default(""), // REMINDER: remove default once alpha
- url: z.string().url().optional(),
- fromDate: z.number().int().default(0), // always start from a date
- toDate: z.number().int().optional(),
- limit: z.number().int().optional().default(7500), // one day has 2448 pings (17 (regions) * 6 (per hour) * 24) * 3 days for historical data
- region: monitorFlyRegionSchema.optional(),
- cronTimestamp: z.number().int().optional(),
-});
-
-/**
- * Params for pipe response_details
- */
-export const tbParameterResponseDetails = tbParameterResponseList.pick({
- monitorId: true,
- url: true,
- cronTimestamp: true,
- region: true,
-});
-
-export const responseHeadersSchema = z.record(z.string(), z.string());
-export const responseTimingSchema = z.object({
- dnsStart: z.number(),
- dnsDone: z.number(),
- connectStart: z.number(),
- connectDone: z.number(),
- tlsHandshakeStart: z.number(),
- tlsHandshakeDone: z.number(),
- firstByteStart: z.number(),
- firstByteDone: z.number(),
- transferStart: z.number(),
- transferDone: z.number(),
-});
-
-/**
- * Values from the pipe response_details
- */
-export const tbBuildResponseDetails = tbBuildResponseList.extend({
- message: z.string().nullable().optional(),
- headers: z
- .string()
- .nullable()
- .optional()
- .transform((val) => {
- if (!val) return null;
- const value = responseHeadersSchema.safeParse(JSON.parse(val));
- if (value.success) return value.data;
- return null;
- }),
- timing: z
- .string()
- .nullable()
- .optional()
- .transform((val) => {
- if (!val) return null;
- const value = responseTimingSchema.safeParse(JSON.parse(val));
- if (value.success) return value.data;
- return null;
- }),
-});
-
-export const latencyMetrics = z.object({
- p50Latency: z.number().int().nullable(),
- p75Latency: z.number().int().nullable(),
- p90Latency: z.number().int().nullable(),
- p95Latency: z.number().int().nullable(),
- p99Latency: z.number().int().nullable(),
-});
-
-/**
- * Values from pipe response_graph
- */
-export const tbBuildResponseGraph = z
- .object({
- region: monitorFlyRegionSchema,
- timestamp: z.number().int(),
- })
- .merge(latencyMetrics);
-
-/**
- * Params for pipe response_graph
- */
-export const tbParameterResponseGraph = z.object({
- monitorId: z.string().default(""),
- url: z.string().url().optional(),
- interval: z.number().int().default(10),
- fromDate: z.number().int().default(0),
- toDate: z.number().int().optional(),
-});
-
-/**
- * Params for pipe status_timezone
- */
-export const tbParameterMonitorList = z.object({
- monitorId: z.string(),
- url: z.string().url().optional(),
- timezone: z.string().optional(),
- limit: z.number().int().default(46).optional(), // 46 days
-});
-
-/**
- * Values from the pipe status_timezone
- */
-export const tbBuildMonitorList = z.object({
- count: z.number().int(),
- ok: z.number().int(),
- day: z.string().transform((val) => {
- // That's a hack because clickhouse return the date in UTC but in shitty format (2021-09-01 00:00:00)
- return new Date(`${val} GMT`).toISOString();
- }),
-});
-
-/**
- * Params for pipe home_stats
- */
-export const tbParameterHomeStats = z.object({
- cronTimestamp: z.number().int().optional(),
- period: z.enum(["total", "1h", "10m"]).optional(),
-});
-
-/**
- * Values from the pipe home_stats
- */
-export const tbBuildHomeStats = z.object({
- count: z.number().int(),
-});
-
-/**
- * Params for pipe public_status (used for our API /public/status/[slug])
- */
-export const tbParameterPublicStatus = z.object({
- monitorId: z.string(),
- url: z.string().url().optional(),
- limit: z.number().int().default(5).optional(), // 5 last cronTimestamps
-});
-
-/**
- * Values from the pipe public_status (used for our API /public/status/[slug])
- */
-export const tbBuildPublicStatus = z.object({
- ok: z.number().int(),
- count: z.number().int(),
- cronTimestamp: z.number().int(),
-});
-
-/**
- * Params for pipe response_time_metrics
- */
-export const tbParameterResponseTimeMetrics = z.object({
- monitorId: z.string(),
- url: z.string().url().optional(),
- interval: z.number().int().default(24), // 24 hours
-});
-
-/**
- * Values from the pipe response_time_metrics
- */
-export const tbBuildResponseTimeMetrics = z
- .object({
- count: z.number().int(),
- ok: z.number().int(),
- lastTimestamp: z.number().int().nullable().optional(),
- })
- .merge(latencyMetrics);
-
-/**
- * Params for pipe response_time_metrics_by_region
- */
-export const tbParameterResponseTimeMetricsByRegion = z.object({
- monitorId: z.string(),
- url: z.string().url().optional(),
- interval: z.number().int().default(24), // 24 hours
-});
-
-/**
- * Values from the pipe response_time_metrics_by_region
- */
-export const tbBuildResponseTimeMetricsByRegion = z
- .object({
- region: monitorFlyRegionSchema,
- })
- .merge(latencyMetrics);
-
-export type Ping = z.infer;
-export type Region = (typeof flyRegions)[number]; // TODO: rename type AvailabeRegion
-export type Monitor = z.infer;
-export type HomeStats = z.infer;
-export type ResponseGraph = z.infer; // TODO: rename to ResponseQuantileChart
-export type ResponseListParams = z.infer;
-export type ResponseGraphParams = z.infer;
-export type MonitorListParams = z.infer;
-export type HomeStatsParams = z.infer;
-export type ResponseDetails = z.infer;
-export type ResponseDetailsParams = z.infer;
-export type LatencyMetric = keyof z.infer;
-export type ResponseTimeMetrics = z.infer;
-export type ResponseTimeMetricsParams = z.infer<
- typeof tbParameterResponseTimeMetrics
->;
-export type ResponseTimeMetricsByRegion = z.infer<
- typeof tbBuildResponseTimeMetricsByRegion
->;
-export type ResponseTimeMetricsByRegionParams = z.infer<
- typeof tbParameterResponseTimeMetricsByRegion
->;
diff --git a/packages/tracker/src/tracker.ts b/packages/tracker/src/tracker.ts
index 6384bd7f7f..e96bec6fcf 100644
--- a/packages/tracker/src/tracker.ts
+++ b/packages/tracker/src/tracker.ts
@@ -4,7 +4,6 @@ import type {
StatusReport,
StatusReportUpdate,
} from "@openstatus/db/src/schema";
-import type { Monitor } from "@openstatus/tinybird";
import { isInBlacklist } from "./blacklist";
import { classNames, statusDetails } from "./config";
@@ -12,7 +11,11 @@ import type { StatusDetails, StatusVariant } from "./types";
import { Status } from "./types";
import { endOfDay, isSameDay, startOfDay } from "./utils";
-type Monitors = Monitor[];
+type Monitor = {
+ count: number;
+ ok: number;
+ day: string;
+};
type StatusReports = (StatusReport & {
statusReportUpdates?: StatusReportUpdate[];
})[];
@@ -26,13 +29,13 @@ type Maintenances = Maintenance[];
* StatusPage with multiple Monitors.
*/
export class Tracker {
- private data: Monitors = [];
+ private data: Monitor[] = [];
private statusReports: StatusReports = [];
private incidents: Incidents = [];
private maintenances: Maintenances = [];
constructor(arg: {
- data?: Monitors;
+ data?: Monitor[];
statusReports?: StatusReports;
incidents?: Incidents;
maintenances?: Maintenance[];