Openstatus www.openstatus.dev
at 4c0f4c00a38753a5d0dfd7e7b7b7706dec6f1503 425 lines 11 kB view raw
1import { createClient } from "@libsql/client"; 2import { drizzle } from "drizzle-orm/libsql"; 3 4import { env } from "../env.mjs"; 5import { 6 incidentTable, 7 maintenance, 8 maintenancesToMonitors, 9 monitor, 10 monitorsToPages, 11 monitorsToStatusReport, 12 notification, 13 notificationsToMonitors, 14 page, 15 privateLocation, 16 privateLocationToMonitors, 17 statusReport, 18 statusReportUpdate, 19 user, 20 usersToWorkspaces, 21 workspace, 22} from "./schema"; 23 24async function main() { 25 const db = drizzle( 26 createClient({ url: env.DATABASE_URL, authToken: env.DATABASE_AUTH_TOKEN }), 27 ); 28 console.log("Seeding database "); 29 await db 30 .insert(workspace) 31 .values([ 32 { 33 id: 1, 34 slug: "love-openstatus", 35 stripeId: "stripeId1", 36 name: "test", 37 subscriptionId: "subscriptionId", 38 plan: "team", 39 endsAt: null, 40 paidUntil: null, 41 limits: 42 '{"monitors":50,"synthetic-checks":150000,"periodicity":["30s","1m","5m","10m","30m","1h"],"multi-region":true,"max-regions":35,"data-retention":"24 months","status-pages":20,"maintenance":true,"status-subscribers":true,"custom-domain":true,"password-protection":true,"white-label":true,"notifications":true,"sms":true,"pagerduty":true,"notification-channels":50,"members":"Unlimited","audit-log":true,"regions":["ams","arn","atl","bog","bom","bos","cdg","den","dfw","ewr","eze","fra","gdl","gig","gru","hkg","iad","jnb","lax","lhr","mad","mia","nrt","ord","otp","phx","qro","scl","sea","sin","sjc","syd","waw","yul","yyz"]}', 43 }, 44 { 45 id: 2, 46 slug: "test2", 47 stripeId: "stripeId2", 48 name: "test2", 49 subscriptionId: "subscriptionId2", 50 plan: "free", 51 endsAt: null, 52 paidUntil: null, 53 }, 54 { 55 id: 3, 56 slug: "test3", 57 stripeId: "stripeId3", 58 name: "test3", 59 subscriptionId: "subscriptionId3", 60 plan: "team", 61 endsAt: null, 62 paidUntil: null, 63 }, 64 ]) 65 .onConflictDoNothing() 66 .run(); 67 68 await db 69 .insert(monitor) 70 .values([ 71 { 72 id: 1, 73 workspaceId: 1, 74 active: true, 75 url: "https://www.openstatus.dev", 76 name: "OpenStatus", 77 description: "OpenStatus website", 78 method: "POST", 79 periodicity: "1m", 80 regions: "ams", 81 headers: '[{"key":"key", "value":"value"}]', 82 body: '{"hello":"world"}', 83 }, 84 { 85 id: 2, 86 active: false, 87 workspaceId: 1, 88 periodicity: "10m", 89 url: "https://www.google.com", 90 method: "GET", 91 regions: "gru", 92 public: true, 93 }, 94 { 95 id: 3, 96 workspaceId: 1, 97 active: true, 98 url: "https://www.openstatus.dev", 99 name: "OpenStatus", 100 description: "OpenStatus website", 101 method: "GET", 102 periodicity: "1m", 103 regions: "ams", 104 headers: '[{"key":"key", "value":"value"}]', 105 body: '{"hello":"world"}', 106 }, 107 { 108 id: 4, 109 active: true, 110 workspaceId: 1, 111 periodicity: "10m", 112 url: "https://www.google.com", 113 method: "GET", 114 regions: "gru", 115 public: true, 116 otelEndpoint: "https://otel.com:4337", 117 otelHeaders: '[{"key":"Authorization","value":"Basic"}]', 118 }, 119 { 120 id: 5, 121 active: true, 122 workspaceId: 3, 123 periodicity: "10m", 124 url: "https://openstat.us", 125 method: "GET", 126 regions: "ams", 127 public: true, 128 }, 129 ]) 130 .onConflictDoNothing() 131 .run(); 132 133 await db 134 .insert(page) 135 .values({ 136 id: 1, 137 workspaceId: 1, 138 title: "Acme Inc.", 139 description: "Get informed about our services.", 140 icon: "https://www.openstatus.dev/favicon.ico", 141 slug: "status", 142 customDomain: "", 143 published: true, 144 }) 145 .onConflictDoNothing() 146 .run(); 147 148 await db 149 .insert(user) 150 .values({ 151 id: 1, 152 tenantId: "1", 153 firstName: "Speed", 154 lastName: "Matters", 155 email: "ping@openstatus.dev", 156 photoUrl: "", 157 }) 158 .onConflictDoNothing() 159 .run(); 160 await db 161 .insert(usersToWorkspaces) 162 .values({ workspaceId: 1, userId: 1 }) 163 .onConflictDoNothing() 164 .run(); 165 166 await db 167 .insert(monitorsToPages) 168 .values({ monitorId: 1, pageId: 1 }) 169 .onConflictDoNothing() 170 .run(); 171 await db 172 .insert(notification) 173 .values({ 174 id: 1, 175 provider: "email", 176 name: "sample test notification", 177 data: '{"email":"ping@openstatus.dev"}', 178 workspaceId: 1, 179 }) 180 .onConflictDoNothing() 181 .run(); 182 183 await db 184 .insert(notificationsToMonitors) 185 .values({ monitorId: 1, notificationId: 1 }) 186 .onConflictDoNothing() 187 .run(); 188 189 // Status Report 1 - Resolved incident from 7 days ago 190 const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); 191 const sevenDaysAgoPlus30Min = new Date( 192 sevenDaysAgo.getTime() + 30 * 60 * 1000, 193 ); 194 const sevenDaysAgoPlus90Min = new Date( 195 sevenDaysAgo.getTime() + 90 * 60 * 1000, 196 ); 197 const sevenDaysAgoPlus120Min = new Date( 198 sevenDaysAgo.getTime() + 120 * 60 * 1000, 199 ); 200 201 await db 202 .insert(statusReport) 203 .values({ 204 id: 1, 205 workspaceId: 1, 206 pageId: 1, 207 title: "API Gateway Degraded Performance", 208 status: "resolved", 209 updatedAt: sevenDaysAgoPlus120Min, 210 }) 211 .onConflictDoNothing() 212 .run(); 213 214 await db 215 .insert(statusReportUpdate) 216 .values([ 217 { 218 id: 1, 219 statusReportId: 1, 220 status: "investigating", 221 message: 222 "We are investigating reports of slow API response times affecting some customers.", 223 date: sevenDaysAgo, 224 }, 225 { 226 id: 2, 227 statusReportId: 1, 228 status: "identified", 229 message: 230 "We have identified the issue as a database connection pool exhaustion and are working on a fix.", 231 date: sevenDaysAgoPlus30Min, 232 }, 233 { 234 id: 3, 235 statusReportId: 1, 236 status: "monitoring", 237 message: 238 "A fix has been deployed and we are monitoring the system. Response times are returning to normal.", 239 date: sevenDaysAgoPlus90Min, 240 }, 241 { 242 id: 4, 243 statusReportId: 1, 244 status: "resolved", 245 message: 246 "All systems are operating normally. The issue has been fully resolved.", 247 date: sevenDaysAgoPlus120Min, 248 }, 249 ]) 250 .onConflictDoNothing() 251 .run(); 252 253 // Status Report 2 - Ongoing incident from 2 hours ago 254 const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000); 255 const oneHourAgo = new Date(Date.now() - 1 * 60 * 60 * 1000); 256 const twentyMinutesAgo = new Date(Date.now() - 20 * 60 * 1000); 257 258 await db 259 .insert(statusReport) 260 .values({ 261 id: 2, 262 workspaceId: 1, 263 pageId: 1, 264 title: "Increased Error Rates on Monitoring Checks", 265 status: "resolved", 266 updatedAt: oneHourAgo, 267 }) 268 .onConflictDoNothing() 269 .run(); 270 271 await db 272 .insert(statusReportUpdate) 273 .values([ 274 { 275 id: 5, 276 statusReportId: 2, 277 status: "investigating", 278 message: 279 "We are seeing elevated error rates on some monitoring checks and are investigating the root cause.", 280 date: twoHoursAgo, 281 }, 282 { 283 id: 6, 284 statusReportId: 2, 285 status: "monitoring", 286 message: 287 "We have applied a fix and are monitoring the situation. Error rates are decreasing.", 288 date: oneHourAgo, 289 }, 290 { 291 id: 7, 292 statusReportId: 2, 293 status: "resolved", 294 message: 295 "Everything is under control, we continue to monitor the situation.", 296 date: twentyMinutesAgo, 297 }, 298 ]) 299 .onConflictDoNothing() 300 .run(); 301 302 // Maintenance windows spread across 30 days 303 const twentyDaysAgo = new Date(Date.now() - 20 * 24 * 60 * 60 * 1000); 304 const twentyDaysAgoPlus2Hours = new Date( 305 twentyDaysAgo.getTime() + 2 * 60 * 60 * 1000, 306 ); 307 308 const fiveDaysFromNow = new Date(Date.now() + 5 * 24 * 60 * 60 * 1000); 309 const fiveDaysFromNowPlus4Hours = new Date( 310 fiveDaysFromNow.getTime() + 4 * 60 * 60 * 1000, 311 ); 312 313 await db 314 .insert(maintenance) 315 .values([ 316 { 317 id: 1, 318 workspaceId: 1, 319 title: "Database Migration and Optimization", 320 message: 321 "We will be performing database maintenance to improve performance. Some queries may be slower during this window.", 322 from: twentyDaysAgo, 323 to: twentyDaysAgoPlus2Hours, 324 pageId: 1, 325 }, 326 { 327 id: 2, 328 workspaceId: 1, 329 title: "Infrastructure Upgrade", 330 message: 331 "We will be upgrading our monitoring infrastructure to the latest version. Expect brief interruptions in data collection.", 332 from: fiveDaysFromNow, 333 to: fiveDaysFromNowPlus4Hours, 334 pageId: 1, 335 }, 336 ]) 337 .onConflictDoNothing() 338 .run(); 339 340 await db 341 .insert(maintenancesToMonitors) 342 .values([ 343 { 344 maintenanceId: 1, 345 monitorId: 1, 346 }, 347 ]) 348 .onConflictDoNothing() 349 .run(); 350 351 await db 352 .insert(monitorsToStatusReport) 353 .values([ 354 { 355 monitorId: 1, 356 statusReportId: 2, 357 }, 358 ]) 359 .onConflictDoNothing() 360 .run(); 361 362 // Incidents - realistic past incidents that were resolved 363 const fifteenDaysAgo = new Date(Date.now() - 15 * 24 * 60 * 60 * 1000); 364 const fifteenDaysAgoPlus2Hours = new Date( 365 fifteenDaysAgo.getTime() + 2 * 60 * 60 * 1000, 366 ); 367 368 const threeDaysAgo = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000); 369 const threeDaysAgoPlus20Min = new Date( 370 threeDaysAgo.getTime() + 20 * 60 * 1000, 371 ); 372 373 await db 374 .insert(incidentTable) 375 .values([ 376 { 377 id: 1, 378 workspaceId: 1, 379 monitorId: 1, 380 createdAt: fifteenDaysAgo, 381 startedAt: fifteenDaysAgo, 382 acknowledgedAt: new Date(fifteenDaysAgo.getTime() + 5 * 60 * 1000), 383 resolvedAt: fifteenDaysAgoPlus2Hours, 384 }, 385 { 386 id: 2, 387 workspaceId: 1, 388 monitorId: 1, 389 createdAt: threeDaysAgo, 390 startedAt: threeDaysAgo, 391 acknowledgedAt: new Date(threeDaysAgo.getTime() + 2 * 60 * 1000), 392 resolvedAt: threeDaysAgoPlus20Min, 393 }, 394 ]) 395 .onConflictDoNothing() 396 .run(); 397 398 await db 399 .insert(privateLocation) 400 .values({ 401 id: 1, 402 name: "My Home", 403 token: "my-secret-key", 404 workspaceId: 3, 405 createdAt: new Date(), 406 }) 407 .onConflictDoNothing() 408 .run(); 409 await db 410 .insert(privateLocationToMonitors) 411 .values({ 412 privateLocationId: 1, 413 monitorId: 5, 414 createdAt: new Date(), 415 }) 416 .onConflictDoNothing() 417 .run(); 418 process.exit(0); 419} 420 421main().catch((e) => { 422 console.error("Seed failed"); 423 console.error(e); 424 process.exit(1); 425});