diff --git a/server/lib/statusHistory.ts b/server/lib/statusHistory.ts index b0ef0c927..3a9b1f6ef 100644 --- a/server/lib/statusHistory.ts +++ b/server/lib/statusHistory.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { db, statusHistory } from "@server/db"; +import { db, logsDb, statusHistory } from "@server/db"; import { and, eq, gte, asc } from "drizzle-orm"; import cache from "@server/lib/cache"; @@ -27,7 +27,7 @@ export async function getCachedStatusHistory( const nowSec = Math.floor(Date.now() / 1000); const startSec = nowSec - days * 86400; - const events = await db + const events = await logsDb .select() .from(statusHistory) .where( @@ -74,11 +74,11 @@ export const statusHistoryQuerySchema = z days: z .string() .optional() - .transform((v) => (v ? parseInt(v, 10) : 90)), + .transform((v) => (v ? parseInt(v, 10) : 90)) }) .pipe( z.object({ - days: z.number().int().min(1).max(365), + days: z.number().int().min(1).max(365) }) ); @@ -99,7 +99,14 @@ export interface StatusHistoryResponse { } export function computeBuckets( - events: { entityType: string; entityId: number; orgId: string; status: string; timestamp: number; id: number }[], + events: { + entityType: string; + entityId: number; + orgId: string; + status: string; + timestamp: number; + id: number; + }[], days: number ): { buckets: StatusHistoryDayBucket[]; totalDowntime: number } { const nowSec = Math.floor(Date.now() / 1000); @@ -121,7 +128,8 @@ export function computeBuckets( const currentStatus = lastBeforeDay?.status ?? null; - const windows: { start: number; end: number | null; status: string }[] = []; + const windows: { start: number; end: number | null; status: string }[] = + []; let dayDowntime = 0; let dayDegradedTime = 0; @@ -132,22 +140,21 @@ export function computeBuckets( if (windowStatus !== null && windowStatus !== evt.status) { const windowEnd = evt.timestamp; const isDown = - windowStatus === "offline" || - windowStatus === "unhealthy"; + windowStatus === "offline" || windowStatus === "unhealthy"; const isDegraded = windowStatus === "degraded"; if (isDown) { dayDowntime += windowEnd - windowStart; windows.push({ start: windowStart, end: windowEnd, - status: windowStatus, + status: windowStatus }); } else if (isDegraded) { dayDegradedTime += windowEnd - windowStart; windows.push({ start: windowStart, end: windowEnd, - status: windowStatus, + status: windowStatus }); } } @@ -159,22 +166,21 @@ export function computeBuckets( if (windowStatus !== null) { const finalEnd = Math.min(dayEndSec, nowSec); const isDown = - windowStatus === "offline" || - windowStatus === "unhealthy"; + windowStatus === "offline" || windowStatus === "unhealthy"; const isDegraded = windowStatus === "degraded"; if (isDown && finalEnd > windowStart) { dayDowntime += finalEnd - windowStart; windows.push({ start: windowStart, end: finalEnd, - status: windowStatus, + status: windowStatus }); } else if (isDegraded && finalEnd > windowStart) { dayDegradedTime += finalEnd - windowStart; windows.push({ start: windowStart, end: finalEnd, - status: windowStatus, + status: windowStatus }); } } @@ -225,7 +231,7 @@ export function computeBuckets( uptimePercent: Math.round(uptimePct * 100) / 100, totalDowntimeSeconds: dayDowntime, downtimeWindows: windows, - status, + status }); } diff --git a/server/private/lib/alerts/events/healthCheckEvents.ts b/server/private/lib/alerts/events/healthCheckEvents.ts index abb1e4c2b..ae9f1f05b 100644 --- a/server/private/lib/alerts/events/healthCheckEvents.ts +++ b/server/private/lib/alerts/events/healthCheckEvents.ts @@ -19,7 +19,8 @@ import { targetHealthCheck, targets, resources, - Transaction + Transaction, + logsDb } from "@server/db"; import { eq } from "drizzle-orm"; import { invalidateStatusHistoryCache } from "@server/lib/statusHistory"; @@ -52,10 +53,10 @@ export async function fireHealthCheckHealthyAlert( healthCheckTargetId?: number | null, extra?: Record, send: boolean = true, - trx: Transaction | typeof db = db, + trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "health_check", entityId: healthCheckId, orgId: orgId, @@ -119,7 +120,7 @@ export async function fireHealthCheckUnhealthyAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "health_check", entityId: healthCheckId, orgId: orgId, @@ -172,7 +173,7 @@ export async function fireHealthCheckUnknownAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "health_check", entityId: healthCheckId, orgId: orgId, @@ -194,7 +195,12 @@ export async function fireHealthCheckUnknownAlert( } } -async function handleResource(orgId: string, healthCheckTargetId?: number | null, send: boolean = true, trx: Transaction | typeof db = db) { +async function handleResource( + orgId: string, + healthCheckTargetId?: number | null, + send: boolean = true, + trx: Transaction | typeof db = db +) { if (!healthCheckTargetId) { return; } @@ -222,7 +228,10 @@ async function handleResource(orgId: string, healthCheckTargetId?: number | null const otherTargets = await trx .select({ hcHealth: targetHealthCheck.hcHealth }) .from(targets) - .innerJoin(targetHealthCheck, eq(targetHealthCheck.targetId, targets.targetId)) + .innerJoin( + targetHealthCheck, + eq(targetHealthCheck.targetId, targets.targetId) + ) .where(eq(targets.resourceId, resource.resourceId)); let health = "healthy"; diff --git a/server/private/lib/alerts/events/resourceEvents.ts b/server/private/lib/alerts/events/resourceEvents.ts index 006c8f622..54b40b80d 100644 --- a/server/private/lib/alerts/events/resourceEvents.ts +++ b/server/private/lib/alerts/events/resourceEvents.ts @@ -13,7 +13,7 @@ import logger from "@server/logger"; import { processAlerts } from "../processAlerts"; -import { db, statusHistory, Transaction } from "@server/db"; +import { db, logsDb, statusHistory, Transaction } from "@server/db"; import { invalidateStatusHistoryCache } from "@server/lib/statusHistory"; // --------------------------------------------------------------------------- @@ -40,7 +40,7 @@ export async function fireResourceHealthyAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "resource", entityId: resourceId, orgId: orgId, @@ -101,7 +101,7 @@ export async function fireResourceUnhealthyAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "resource", entityId: resourceId, orgId: orgId, @@ -162,7 +162,7 @@ export async function fireResourceDegradedAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "resource", entityId: resourceId, orgId: orgId, @@ -223,7 +223,7 @@ export async function fireResourceUnknownAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "resource", entityId: resourceId, orgId: orgId, diff --git a/server/private/lib/alerts/events/siteEvents.ts b/server/private/lib/alerts/events/siteEvents.ts index afb53f25f..e1871dc85 100644 --- a/server/private/lib/alerts/events/siteEvents.ts +++ b/server/private/lib/alerts/events/siteEvents.ts @@ -13,7 +13,13 @@ import logger from "@server/logger"; import { processAlerts } from "../processAlerts"; -import { db, sites, statusHistory, targetHealthCheck, Transaction } from "@server/db"; +import { + db, + logsDb, + statusHistory, + targetHealthCheck, + Transaction +} from "@server/db"; import { invalidateStatusHistoryCache } from "@server/lib/statusHistory"; import { and, eq, inArray } from "drizzle-orm"; import { fireHealthCheckUnhealthyAlert } from "./healthCheckEvents"; @@ -41,7 +47,7 @@ export async function fireSiteOnlineAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "site", entityId: siteId, orgId: orgId, @@ -97,7 +103,7 @@ export async function fireSiteOfflineAlert( trx: Transaction | typeof db = db ): Promise { try { - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "site", entityId: siteId, orgId: orgId, diff --git a/server/routers/newt/registerNewt.ts b/server/routers/newt/registerNewt.ts index 440a62198..6a9ba7565 100644 --- a/server/routers/newt/registerNewt.ts +++ b/server/routers/newt/registerNewt.ts @@ -84,7 +84,7 @@ export async function registerNewt( maxBatchSize: siteProvisioningKeys.maxBatchSize, numUsed: siteProvisioningKeys.numUsed, validUntil: siteProvisioningKeys.validUntil, - approveNewSites: siteProvisioningKeys.approveNewSites, + approveNewSites: siteProvisioningKeys.approveNewSites }) .from(siteProvisioningKeys) .innerJoin( @@ -125,7 +125,10 @@ export async function registerNewt( ); } - if (keyRecord.maxBatchSize && keyRecord.numUsed >= keyRecord.maxBatchSize) { + if ( + keyRecord.maxBatchSize && + keyRecord.numUsed >= keyRecord.maxBatchSize + ) { return next( createHttpError( HttpCode.UNAUTHORIZED, @@ -134,7 +137,10 @@ export async function registerNewt( ); } - if (keyRecord.validUntil && new Date(keyRecord.validUntil) < new Date()) { + if ( + keyRecord.validUntil && + new Date(keyRecord.validUntil) < new Date() + ) { return next( createHttpError( HttpCode.UNAUTHORIZED, @@ -154,7 +160,10 @@ export async function registerNewt( } if (!org.subnet) { return next( - createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "Organization subnet not found") + createHttpError( + HttpCode.INTERNAL_SERVER_ERROR, + "Organization subnet not found" + ) ); } @@ -195,7 +204,6 @@ export async function registerNewt( let newSiteId: number | undefined; await db.transaction(async (trx) => { - const newClientAddress = await getNextAvailableClientSubnet(orgId); if (!newClientAddress) { return next( @@ -219,11 +227,11 @@ export async function registerNewt( address: clientAddress, type: "newt", dockerSocketEnabled: true, - status: keyRecord.approveNewSites ? "approved" : "pending", + status: keyRecord.approveNewSites ? "approved" : "pending" }) .returning(); - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "site", entityId: newSite.siteId, orgId: orgId, diff --git a/server/routers/site/createSite.ts b/server/routers/site/createSite.ts index 0ac0de3d7..251ddc3e4 100644 --- a/server/routers/site/createSite.ts +++ b/server/routers/site/createSite.ts @@ -351,7 +351,7 @@ export async function createSite( }) .returning(); - await trx.insert(statusHistory).values({ + await logsDb.insert(statusHistory).values({ entityType: "site", entityId: newSite.siteId, orgId: orgId,