Openstatus
www.openstatus.dev
1import { relations, sql } from "drizzle-orm";
2import {
3 integer,
4 primaryKey,
5 sqliteTable,
6 text,
7} from "drizzle-orm/sqlite-core";
8
9import { monitorPeriodicity } from "../constants";
10import { incidentTable } from "../incidents/incident";
11import { maintenancesToMonitors } from "../maintenances";
12import { monitorGroup } from "../monitor_groups";
13import { monitorStatusTable } from "../monitor_status/monitor_status";
14import { monitorTagsToMonitors } from "../monitor_tags";
15import { notificationsToMonitors } from "../notifications";
16import { page } from "../pages";
17import { privateLocationToMonitors } from "../private_locations";
18import { monitorsToStatusReport } from "../status_reports";
19import { workspace } from "../workspaces/workspace";
20import { monitorJobTypes, monitorMethods, monitorStatus } from "./constants";
21
22export const monitor = sqliteTable("monitor", {
23 id: integer("id").primaryKey(),
24 jobType: text("job_type", { enum: monitorJobTypes })
25 .default("http")
26 .notNull(),
27 periodicity: text("periodicity", { enum: monitorPeriodicity })
28 .default("other")
29 .notNull(),
30 status: text("status", { enum: monitorStatus }).default("active").notNull(),
31 active: integer("active", { mode: "boolean" }).default(false),
32
33 regions: text("regions").default("").notNull(),
34
35 url: text("url", { length: 2048 }).notNull(), // URI
36
37 name: text("name", { length: 256 }).default("").notNull(),
38 externalName: text("external_name"),
39 description: text("description").default("").notNull(),
40
41 headers: text("headers").default(""),
42 body: text("body").default(""),
43 method: text("method", { enum: monitorMethods }).default("GET"),
44 workspaceId: integer("workspace_id").references(() => workspace.id),
45
46 // Custom timeout for this monitor
47 timeout: integer("timeout").notNull().default(45000), // in milliseconds
48
49 // Threshold for the monitor to be considered degraded
50 degradedAfter: integer("degraded_after"), // in millisecond
51
52 assertions: text("assertions"),
53
54 otelEndpoint: text("otel_endpoint"),
55
56 otelHeaders: text("otel_headers"),
57
58 public: integer("public", { mode: "boolean" }).default(false),
59
60 retry: integer("retry").default(3),
61
62 followRedirects: integer("follow_redirects", { mode: "boolean" }).default(
63 true,
64 ),
65
66 createdAt: integer("created_at", { mode: "timestamp" }).default(
67 sql`(strftime('%s', 'now'))`,
68 ),
69 updatedAt: integer("updated_at", { mode: "timestamp" }).default(
70 sql`(strftime('%s', 'now'))`,
71 ),
72
73 deletedAt: integer("deleted_at", { mode: "timestamp" }),
74});
75
76export const monitorRelation = relations(monitor, ({ one, many }) => ({
77 monitorsToPages: many(monitorsToPages),
78 monitorsToStatusReports: many(monitorsToStatusReport),
79 monitorTagsToMonitors: many(monitorTagsToMonitors),
80 workspace: one(workspace, {
81 fields: [monitor.workspaceId],
82 references: [workspace.id],
83 }),
84 monitorsToNotifications: many(notificationsToMonitors),
85 maintenancesToMonitors: many(maintenancesToMonitors),
86 incidents: many(incidentTable),
87 monitorStatus: many(monitorStatusTable),
88 privateLocationToMonitors: many(privateLocationToMonitors),
89}));
90
91export const monitorsToPages = sqliteTable(
92 "monitors_to_pages",
93 {
94 monitorId: integer("monitor_id")
95 .notNull()
96 .references(() => monitor.id, { onDelete: "cascade" }),
97 pageId: integer("page_id")
98 .notNull()
99 .references(() => page.id, { onDelete: "cascade" }),
100 createdAt: integer("created_at", { mode: "timestamp" }).default(
101 sql`(strftime('%s', 'now'))`,
102 ),
103 order: integer("order").default(0),
104
105 monitorGroupId: integer("monitor_group_id").references(
106 () => monitorGroup.id,
107 { onDelete: "cascade" },
108 ),
109 groupOrder: integer("group_order").default(0),
110 },
111 (t) => ({
112 pk: primaryKey({ columns: [t.monitorId, t.pageId] }),
113 }),
114);
115
116export const monitorsToPagesRelation = relations(
117 monitorsToPages,
118 ({ one }) => ({
119 monitor: one(monitor, {
120 fields: [monitorsToPages.monitorId],
121 references: [monitor.id],
122 }),
123 page: one(page, {
124 fields: [monitorsToPages.pageId],
125 references: [page.id],
126 }),
127 monitorGroup: one(monitorGroup, {
128 fields: [monitorsToPages.monitorGroupId],
129 references: [monitorGroup.id],
130 }),
131 }),
132);