From 943ef9205370b015e8ae1ca72dbd35529e2b0213 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Wed, 11 Mar 2026 01:31:05 -0400 Subject: [PATCH 1/2] fix: rename "breached" status to "exceeded" for clarity The word "breached" in infrastructure monitoring was confusing users as it implied a security breach. Renamed to "exceeded" which better describes threshold violations (e.g. "threshold exceeded"). ## Changes - Renamed monitor status value from "breached" to "exceeded" across server types, status service, queue helper, notification builder, email subject lines, and MongoDB aggregation queries - Renamed client types, status box/label components, translation key, and infrastructure page props to match - Added DB migration (0005) to update existing monitors with the old status value --- .../Components/design-elements/StatusBox.tsx | 4 +-- .../design-elements/StatusLabel.tsx | 4 +-- .../monitors/HeaderMonitorsSummary.tsx | 8 +++--- .../Pages/Infrastructure/Monitors/index.tsx | 2 +- client/src/Types/Monitor.ts | 4 +-- client/src/Utils/MonitorUtils.ts | 2 +- client/src/locales/en.json | 2 +- .../0005_renameBreachedToExceeded.ts | 25 +++++++++++++++++++ server/src/db/migration/index.ts | 2 ++ .../monitors/MongoMonitorsRepository.ts | 6 ++--- .../SuperSimpleQueueHelper.ts | 6 ++--- .../notificationMessageBuilder.ts | 6 ++--- .../notificationProviders/email.ts | 2 +- .../service/infrastructure/statusService.ts | 22 ++++++++-------- server/src/types/monitor.ts | 4 +-- 15 files changed, 63 insertions(+), 36 deletions(-) create mode 100644 server/src/db/migration/0005_renameBreachedToExceeded.ts diff --git a/client/src/Components/design-elements/StatusBox.tsx b/client/src/Components/design-elements/StatusBox.tsx index 96a9d9fbf..895709b04 100644 --- a/client/src/Components/design-elements/StatusBox.tsx +++ b/client/src/Components/design-elements/StatusBox.tsx @@ -139,12 +139,12 @@ export const InitializingStatusBox = ({ n }: { n: number }) => { /> ); }; -export const BreachedStatusBox = ({ n }: { n: number }) => { +export const ExceededStatusBox = ({ n }: { n: number }) => { const theme = useTheme(); const { t } = useTranslation(); return ( diff --git a/client/src/Components/design-elements/StatusLabel.tsx b/client/src/Components/design-elements/StatusLabel.tsx index d50058378..e9c92a490 100644 --- a/client/src/Components/design-elements/StatusLabel.tsx +++ b/client/src/Components/design-elements/StatusLabel.tsx @@ -21,8 +21,8 @@ export const StatusLabel = ({ status, sx }: { status: MonitorStatus; sx?: SxProp return t("pages.common.monitors.status.up"); } else if (status === "down") { return t("pages.common.monitors.status.down"); - } else if (status === "breached") { - return t("pages.common.monitors.status.breached"); + } else if (status === "exceeded") { + return t("pages.common.monitors.status.exceeded"); } else if (status === "maintenance") { return t("pages.common.monitors.status.maintenance"); } else if (status === "paused") { diff --git a/client/src/Components/monitors/HeaderMonitorsSummary.tsx b/client/src/Components/monitors/HeaderMonitorsSummary.tsx index 1d130209d..07edc406a 100644 --- a/client/src/Components/monitors/HeaderMonitorsSummary.tsx +++ b/client/src/Components/monitors/HeaderMonitorsSummary.tsx @@ -3,7 +3,7 @@ import { DownStatusBox, PausedStatusBox, InitializingStatusBox, - BreachedStatusBox, + ExceededStatusBox, } from "@/Components/design-elements"; import Stack from "@mui/material/Stack"; @@ -12,12 +12,12 @@ import { useTheme } from "@mui/material"; interface MonitorsSummaryProps { summary: MonitorsSummary | null; - showBreached?: boolean; + showExceeded?: boolean; } export const HeaderMonitorsSummary = ({ summary, - showBreached = false, + showExceeded = false, }: MonitorsSummaryProps) => { const theme = useTheme(); return ( @@ -27,7 +27,7 @@ export const HeaderMonitorsSummary = ({ > - {showBreached && } + {showExceeded && } diff --git a/client/src/Pages/Infrastructure/Monitors/index.tsx b/client/src/Pages/Infrastructure/Monitors/index.tsx index bdf477613..53c3f16e0 100644 --- a/client/src/Pages/Infrastructure/Monitors/index.tsx +++ b/client/src/Pages/Infrastructure/Monitors/index.tsx @@ -135,7 +135,7 @@ const InfrastructureMonitors = () => { /> { if (status === "down") { return "error"; } - if (status === "breached") { + if (status === "exceeded") { return "error"; } return "warning"; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 4c4965aec..85357772e 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -401,7 +401,7 @@ }, "status": { "down": "down", - "breached": "breached", + "exceeded": "threshold exceeded", "initializing": "initializing", "maintenance": "maintenance", "paused": "paused", diff --git a/server/src/db/migration/0005_renameBreachedToExceeded.ts b/server/src/db/migration/0005_renameBreachedToExceeded.ts new file mode 100644 index 000000000..ea2f9d24e --- /dev/null +++ b/server/src/db/migration/0005_renameBreachedToExceeded.ts @@ -0,0 +1,25 @@ +import { MonitorModel } from "../models/Monitor.js"; +import { logger } from "@/utils/logger.js"; + +/** + * Rename monitor status "breached" to "exceeded" for clarity. + * The word "breached" was confusing users as it implied a security breach. + */ +export async function renameBreachedToExceeded(): Promise { + const SERVICE_NAME = "Migration:RenameBreachedToExceeded"; + + try { + logger.info({ service: SERVICE_NAME, message: "Starting status rename: breached -> exceeded" }); + + const result = await MonitorModel.updateMany({ status: "breached" }, { $set: { status: "exceeded" } }); + + logger.info({ + service: SERVICE_NAME, + message: `Updated ${result.modifiedCount} monitors from 'breached' to 'exceeded'`, + }); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + logger.error({ service: SERVICE_NAME, message: `Error renaming status: ${errorMessage}` }); + throw error; + } +} diff --git a/server/src/db/migration/index.ts b/server/src/db/migration/index.ts index 3b7b45ada..61bf358eb 100644 --- a/server/src/db/migration/index.ts +++ b/server/src/db/migration/index.ts @@ -2,6 +2,7 @@ import { migrateStatusWindowThreshold } from "./0001_migrateStatusWindowThreshol import { convertChecksToTimeSeries } from "./0002_convertChecksToTimeSeries.js"; import { cleanupDuplicateMonitorStats } from "./0003_cleanupDuplicateMonitorStats.js"; import { fixInfrastructureThresholds } from "./0004_fixInfrastructureThresholds.js"; +import { renameBreachedToExceeded } from "./0005_renameBreachedToExceeded.js"; import MigrationModel from "../models/Migration.js"; type MigrationEntry = { @@ -14,6 +15,7 @@ const migrations: MigrationEntry[] = [ { name: "0002_convertChecksToTimeSeries", execute: convertChecksToTimeSeries }, { name: "0003_cleanupDuplicateMonitorStats", execute: cleanupDuplicateMonitorStats }, { name: "0004_fixInfrastructureThresholds", execute: fixInfrastructureThresholds }, + { name: "0005_renameBreachedToExceeded", execute: renameBreachedToExceeded }, ]; const runMigrations = async (logger?: { info: Function; error: Function }) => { diff --git a/server/src/repositories/monitors/MongoMonitorsRepository.ts b/server/src/repositories/monitors/MongoMonitorsRepository.ts index a3b40f459..a075d42b9 100644 --- a/server/src/repositories/monitors/MongoMonitorsRepository.ts +++ b/server/src/repositories/monitors/MongoMonitorsRepository.ts @@ -262,9 +262,9 @@ class MongoMonitorsRepository implements IMonitorsRepository { $cond: [{ $eq: ["$status", "maintenance"] }, 1, 0], }, }, - breachedMonitors: { + exceededMonitors: { $sum: { - $cond: [{ $eq: ["$status", "breached"] }, 1, 0], + $cond: [{ $eq: ["$status", "exceeded"] }, 1, 0], }, }, }, @@ -281,7 +281,7 @@ class MongoMonitorsRepository implements IMonitorsRepository { pausedMonitors: 0, initializingMonitors: 0, maintenanceMonitors: 0, - breachedMonitors: 0, + exceededMonitors: 0, } ); }; diff --git a/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts b/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts index b6908127b..e5d746635 100644 --- a/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts +++ b/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts @@ -440,14 +440,14 @@ export class SuperSimpleQueueHelper implements ISuperSimpleQueueHelper { decision.shouldSendNotification = true; decision.incidentReason = "status_down"; decision.notificationReason = "status_change"; - } else if (monitor.status === "breached") { + } else if (monitor.status === "exceeded") { // Hardware monitor exceeded thresholds decision.shouldCreateIncident = true; decision.shouldSendNotification = true; decision.incidentReason = "threshold_breach"; decision.notificationReason = "threshold_breach"; - } else if (monitor.status === "up" && (prevStatus === "down" || prevStatus === "breached")) { - // Monitor recovered from down or breached state + } else if (monitor.status === "up" && (prevStatus === "down" || prevStatus === "exceeded")) { + // Monitor recovered from down or exceeded state decision.shouldResolveIncident = true; decision.shouldSendNotification = true; decision.notificationReason = "status_change"; diff --git a/server/src/service/infrastructure/notificationMessageBuilder.ts b/server/src/service/infrastructure/notificationMessageBuilder.ts index 3d16acf19..934163b2a 100644 --- a/server/src/service/infrastructure/notificationMessageBuilder.ts +++ b/server/src/service/infrastructure/notificationMessageBuilder.ts @@ -145,9 +145,9 @@ export class NotificationMessageBuilder implements INotificationMessageBuilder { } private buildThresholdBreachContent(monitor: Monitor, monitorStatusResponse: MonitorStatusResponse): NotificationContent { - const title = `Threshold Breach: ${monitor.name}`; - const summary = `Monitor "${monitor.name}" has breached one or more thresholds.`; - const details = [`URL: ${monitor.url}`, `Status: Breached`, `Type: ${monitor.type}`]; + const title = `Threshold Exceeded: ${monitor.name}`; + const summary = `Monitor "${monitor.name}" has exceeded one or more thresholds.`; + const details = [`URL: ${monitor.url}`, `Status: Threshold exceeded`, `Type: ${monitor.type}`]; const thresholds = this.extractThresholdBreaches(monitor, monitorStatusResponse); diff --git a/server/src/service/infrastructure/notificationProviders/email.ts b/server/src/service/infrastructure/notificationProviders/email.ts index c14d59a85..338ceb619 100644 --- a/server/src/service/infrastructure/notificationProviders/email.ts +++ b/server/src/service/infrastructure/notificationProviders/email.ts @@ -84,7 +84,7 @@ export class EmailProvider implements INotificationProvider { case "monitor_up": return `Monitor ${message.monitor.name} is back up`; case "threshold_breach": - return `Monitor ${message.monitor.name} threshold breached`; + return `Monitor ${message.monitor.name} threshold exceeded`; case "threshold_resolved": return `Monitor ${message.monitor.name} thresholds resolved`; default: diff --git a/server/src/service/infrastructure/statusService.ts b/server/src/service/infrastructure/statusService.ts index badcf78ec..ef8c6125e 100755 --- a/server/src/service/infrastructure/statusService.ts +++ b/server/src/service/infrastructure/statusService.ts @@ -292,7 +292,7 @@ export class StatusService implements IStatusService { temp: tempBreach, }; - // Update counters: decrement if breached, reset to 5 if not breached + // Update counters: decrement if exceeded, reset to 5 if not exceeded if (cpuBreach) { monitor.cpuAlertCounter = Math.max(0, monitor.cpuAlertCounter - 1); } else { @@ -321,23 +321,23 @@ export class StatusService implements IStatusService { const anyCounterZero = monitor.cpuAlertCounter === 0 || monitor.memoryAlertCounter === 0 || monitor.diskAlertCounter === 0 || monitor.tempAlertCounter === 0; - const anyThresholdBreached = cpuBreach || memoryBreach || diskBreach || tempBreach; + const anyThresholdExceeded = cpuBreach || memoryBreach || diskBreach || tempBreach; const allThresholdsNormal = !cpuBreach && !memoryBreach && !diskBreach && !tempBreach; - // Update monitor status based on threshold breach state + // Update monitor status based on threshold exceeded state if (newStatus !== "down") { // Don't override "down" status - service unreachable takes precedence // Check current monitor status, not newStatus for comparison - if (anyCounterZero && anyThresholdBreached && monitor.status !== "breached") { - // Initial breach: counter hit zero, change status to breached - newStatus = "breached"; + if (anyCounterZero && anyThresholdExceeded && monitor.status !== "exceeded") { + // Threshold exceeded: counter hit zero, change status to exceeded + newStatus = "exceeded"; statusChanged = true; - } else if (anyCounterZero && anyThresholdBreached && monitor.status === "breached") { - // Already breached, keep status but don't mark as changed - newStatus = "breached"; + } else if (anyCounterZero && anyThresholdExceeded && monitor.status === "exceeded") { + // Already exceeded, keep status but don't mark as changed + newStatus = "exceeded"; // statusChanged remains false - } else if (allThresholdsNormal && monitor.status === "breached") { - // All thresholds returned to normal, recover from breached state + } else if (allThresholdsNormal && monitor.status === "exceeded") { + // All thresholds returned to normal, recover from exceeded state newStatus = "up"; statusChanged = true; } diff --git a/server/src/types/monitor.ts b/server/src/types/monitor.ts index 89740162b..62a0d3aa6 100644 --- a/server/src/types/monitor.ts +++ b/server/src/types/monitor.ts @@ -9,7 +9,7 @@ export type MonitorType = (typeof MonitorTypes)[number]; export const GeoCheckSupportedTypes: readonly MonitorType[] = ["http", "ping"] as const; export const supportsGeoCheck = (type: MonitorType): boolean => GeoCheckSupportedTypes.includes(type); -export const MonitorStatuses = ["up", "down", "paused", "initializing", "maintenance", "breached"] as const; +export const MonitorStatuses = ["up", "down", "paused", "initializing", "maintenance", "exceeded"] as const; export type MonitorStatus = (typeof MonitorStatuses)[number]; export type MonitorMatchMethod = "equal" | "include" | "regex" | ""; @@ -64,7 +64,7 @@ export interface MonitorsSummary { pausedMonitors: number; initializingMonitors: number; maintenanceMonitors: number; - breachedMonitors: number; + exceededMonitors: number; } export interface MonitorsWithChecksByTeamIdResult { From 94660903328cec032a0d129185d0616729f51bc8 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Wed, 11 Mar 2026 16:30:30 -0400 Subject: [PATCH 2/2] fix: rename "breached" to "threshold exceeded" in user-facing strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only changes user-facing text — no enum, type, or backend status changes. ## Changes - locales/en.json: "breached" → "threshold exceeded" - notificationMessageBuilder.ts: notification title/summary/details - email.ts: email subject line --- .../Components/design-elements/StatusBox.tsx | 4 +-- .../design-elements/StatusLabel.tsx | 4 +-- .../monitors/HeaderMonitorsSummary.tsx | 8 +++--- .../Pages/Infrastructure/Monitors/index.tsx | 2 +- client/src/Types/Monitor.ts | 4 +-- client/src/Utils/MonitorUtils.ts | 2 +- client/src/locales/en.json | 2 +- .../0005_renameBreachedToExceeded.ts | 25 ------------------- server/src/db/migration/index.ts | 2 -- .../monitors/MongoMonitorsRepository.ts | 6 ++--- .../SuperSimpleQueueHelper.ts | 6 ++--- .../service/infrastructure/statusService.ts | 22 ++++++++-------- server/src/types/monitor.ts | 4 +-- 13 files changed, 32 insertions(+), 59 deletions(-) delete mode 100644 server/src/db/migration/0005_renameBreachedToExceeded.ts diff --git a/client/src/Components/design-elements/StatusBox.tsx b/client/src/Components/design-elements/StatusBox.tsx index 895709b04..96a9d9fbf 100644 --- a/client/src/Components/design-elements/StatusBox.tsx +++ b/client/src/Components/design-elements/StatusBox.tsx @@ -139,12 +139,12 @@ export const InitializingStatusBox = ({ n }: { n: number }) => { /> ); }; -export const ExceededStatusBox = ({ n }: { n: number }) => { +export const BreachedStatusBox = ({ n }: { n: number }) => { const theme = useTheme(); const { t } = useTranslation(); return ( diff --git a/client/src/Components/design-elements/StatusLabel.tsx b/client/src/Components/design-elements/StatusLabel.tsx index e9c92a490..d50058378 100644 --- a/client/src/Components/design-elements/StatusLabel.tsx +++ b/client/src/Components/design-elements/StatusLabel.tsx @@ -21,8 +21,8 @@ export const StatusLabel = ({ status, sx }: { status: MonitorStatus; sx?: SxProp return t("pages.common.monitors.status.up"); } else if (status === "down") { return t("pages.common.monitors.status.down"); - } else if (status === "exceeded") { - return t("pages.common.monitors.status.exceeded"); + } else if (status === "breached") { + return t("pages.common.monitors.status.breached"); } else if (status === "maintenance") { return t("pages.common.monitors.status.maintenance"); } else if (status === "paused") { diff --git a/client/src/Components/monitors/HeaderMonitorsSummary.tsx b/client/src/Components/monitors/HeaderMonitorsSummary.tsx index 07edc406a..1d130209d 100644 --- a/client/src/Components/monitors/HeaderMonitorsSummary.tsx +++ b/client/src/Components/monitors/HeaderMonitorsSummary.tsx @@ -3,7 +3,7 @@ import { DownStatusBox, PausedStatusBox, InitializingStatusBox, - ExceededStatusBox, + BreachedStatusBox, } from "@/Components/design-elements"; import Stack from "@mui/material/Stack"; @@ -12,12 +12,12 @@ import { useTheme } from "@mui/material"; interface MonitorsSummaryProps { summary: MonitorsSummary | null; - showExceeded?: boolean; + showBreached?: boolean; } export const HeaderMonitorsSummary = ({ summary, - showExceeded = false, + showBreached = false, }: MonitorsSummaryProps) => { const theme = useTheme(); return ( @@ -27,7 +27,7 @@ export const HeaderMonitorsSummary = ({ > - {showExceeded && } + {showBreached && } diff --git a/client/src/Pages/Infrastructure/Monitors/index.tsx b/client/src/Pages/Infrastructure/Monitors/index.tsx index 53c3f16e0..bdf477613 100644 --- a/client/src/Pages/Infrastructure/Monitors/index.tsx +++ b/client/src/Pages/Infrastructure/Monitors/index.tsx @@ -135,7 +135,7 @@ const InfrastructureMonitors = () => { /> { if (status === "down") { return "error"; } - if (status === "exceeded") { + if (status === "breached") { return "error"; } return "warning"; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 85357772e..04e18e3dc 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -401,7 +401,7 @@ }, "status": { "down": "down", - "exceeded": "threshold exceeded", + "breached": "threshold exceeded", "initializing": "initializing", "maintenance": "maintenance", "paused": "paused", diff --git a/server/src/db/migration/0005_renameBreachedToExceeded.ts b/server/src/db/migration/0005_renameBreachedToExceeded.ts deleted file mode 100644 index ea2f9d24e..000000000 --- a/server/src/db/migration/0005_renameBreachedToExceeded.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { MonitorModel } from "../models/Monitor.js"; -import { logger } from "@/utils/logger.js"; - -/** - * Rename monitor status "breached" to "exceeded" for clarity. - * The word "breached" was confusing users as it implied a security breach. - */ -export async function renameBreachedToExceeded(): Promise { - const SERVICE_NAME = "Migration:RenameBreachedToExceeded"; - - try { - logger.info({ service: SERVICE_NAME, message: "Starting status rename: breached -> exceeded" }); - - const result = await MonitorModel.updateMany({ status: "breached" }, { $set: { status: "exceeded" } }); - - logger.info({ - service: SERVICE_NAME, - message: `Updated ${result.modifiedCount} monitors from 'breached' to 'exceeded'`, - }); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - logger.error({ service: SERVICE_NAME, message: `Error renaming status: ${errorMessage}` }); - throw error; - } -} diff --git a/server/src/db/migration/index.ts b/server/src/db/migration/index.ts index 61bf358eb..3b7b45ada 100644 --- a/server/src/db/migration/index.ts +++ b/server/src/db/migration/index.ts @@ -2,7 +2,6 @@ import { migrateStatusWindowThreshold } from "./0001_migrateStatusWindowThreshol import { convertChecksToTimeSeries } from "./0002_convertChecksToTimeSeries.js"; import { cleanupDuplicateMonitorStats } from "./0003_cleanupDuplicateMonitorStats.js"; import { fixInfrastructureThresholds } from "./0004_fixInfrastructureThresholds.js"; -import { renameBreachedToExceeded } from "./0005_renameBreachedToExceeded.js"; import MigrationModel from "../models/Migration.js"; type MigrationEntry = { @@ -15,7 +14,6 @@ const migrations: MigrationEntry[] = [ { name: "0002_convertChecksToTimeSeries", execute: convertChecksToTimeSeries }, { name: "0003_cleanupDuplicateMonitorStats", execute: cleanupDuplicateMonitorStats }, { name: "0004_fixInfrastructureThresholds", execute: fixInfrastructureThresholds }, - { name: "0005_renameBreachedToExceeded", execute: renameBreachedToExceeded }, ]; const runMigrations = async (logger?: { info: Function; error: Function }) => { diff --git a/server/src/repositories/monitors/MongoMonitorsRepository.ts b/server/src/repositories/monitors/MongoMonitorsRepository.ts index a075d42b9..a3b40f459 100644 --- a/server/src/repositories/monitors/MongoMonitorsRepository.ts +++ b/server/src/repositories/monitors/MongoMonitorsRepository.ts @@ -262,9 +262,9 @@ class MongoMonitorsRepository implements IMonitorsRepository { $cond: [{ $eq: ["$status", "maintenance"] }, 1, 0], }, }, - exceededMonitors: { + breachedMonitors: { $sum: { - $cond: [{ $eq: ["$status", "exceeded"] }, 1, 0], + $cond: [{ $eq: ["$status", "breached"] }, 1, 0], }, }, }, @@ -281,7 +281,7 @@ class MongoMonitorsRepository implements IMonitorsRepository { pausedMonitors: 0, initializingMonitors: 0, maintenanceMonitors: 0, - exceededMonitors: 0, + breachedMonitors: 0, } ); }; diff --git a/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts b/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts index e5d746635..b6908127b 100644 --- a/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts +++ b/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.ts @@ -440,14 +440,14 @@ export class SuperSimpleQueueHelper implements ISuperSimpleQueueHelper { decision.shouldSendNotification = true; decision.incidentReason = "status_down"; decision.notificationReason = "status_change"; - } else if (monitor.status === "exceeded") { + } else if (monitor.status === "breached") { // Hardware monitor exceeded thresholds decision.shouldCreateIncident = true; decision.shouldSendNotification = true; decision.incidentReason = "threshold_breach"; decision.notificationReason = "threshold_breach"; - } else if (monitor.status === "up" && (prevStatus === "down" || prevStatus === "exceeded")) { - // Monitor recovered from down or exceeded state + } else if (monitor.status === "up" && (prevStatus === "down" || prevStatus === "breached")) { + // Monitor recovered from down or breached state decision.shouldResolveIncident = true; decision.shouldSendNotification = true; decision.notificationReason = "status_change"; diff --git a/server/src/service/infrastructure/statusService.ts b/server/src/service/infrastructure/statusService.ts index ef8c6125e..badcf78ec 100755 --- a/server/src/service/infrastructure/statusService.ts +++ b/server/src/service/infrastructure/statusService.ts @@ -292,7 +292,7 @@ export class StatusService implements IStatusService { temp: tempBreach, }; - // Update counters: decrement if exceeded, reset to 5 if not exceeded + // Update counters: decrement if breached, reset to 5 if not breached if (cpuBreach) { monitor.cpuAlertCounter = Math.max(0, monitor.cpuAlertCounter - 1); } else { @@ -321,23 +321,23 @@ export class StatusService implements IStatusService { const anyCounterZero = monitor.cpuAlertCounter === 0 || monitor.memoryAlertCounter === 0 || monitor.diskAlertCounter === 0 || monitor.tempAlertCounter === 0; - const anyThresholdExceeded = cpuBreach || memoryBreach || diskBreach || tempBreach; + const anyThresholdBreached = cpuBreach || memoryBreach || diskBreach || tempBreach; const allThresholdsNormal = !cpuBreach && !memoryBreach && !diskBreach && !tempBreach; - // Update monitor status based on threshold exceeded state + // Update monitor status based on threshold breach state if (newStatus !== "down") { // Don't override "down" status - service unreachable takes precedence // Check current monitor status, not newStatus for comparison - if (anyCounterZero && anyThresholdExceeded && monitor.status !== "exceeded") { - // Threshold exceeded: counter hit zero, change status to exceeded - newStatus = "exceeded"; + if (anyCounterZero && anyThresholdBreached && monitor.status !== "breached") { + // Initial breach: counter hit zero, change status to breached + newStatus = "breached"; statusChanged = true; - } else if (anyCounterZero && anyThresholdExceeded && monitor.status === "exceeded") { - // Already exceeded, keep status but don't mark as changed - newStatus = "exceeded"; + } else if (anyCounterZero && anyThresholdBreached && monitor.status === "breached") { + // Already breached, keep status but don't mark as changed + newStatus = "breached"; // statusChanged remains false - } else if (allThresholdsNormal && monitor.status === "exceeded") { - // All thresholds returned to normal, recover from exceeded state + } else if (allThresholdsNormal && monitor.status === "breached") { + // All thresholds returned to normal, recover from breached state newStatus = "up"; statusChanged = true; } diff --git a/server/src/types/monitor.ts b/server/src/types/monitor.ts index 62a0d3aa6..89740162b 100644 --- a/server/src/types/monitor.ts +++ b/server/src/types/monitor.ts @@ -9,7 +9,7 @@ export type MonitorType = (typeof MonitorTypes)[number]; export const GeoCheckSupportedTypes: readonly MonitorType[] = ["http", "ping"] as const; export const supportsGeoCheck = (type: MonitorType): boolean => GeoCheckSupportedTypes.includes(type); -export const MonitorStatuses = ["up", "down", "paused", "initializing", "maintenance", "exceeded"] as const; +export const MonitorStatuses = ["up", "down", "paused", "initializing", "maintenance", "breached"] as const; export type MonitorStatus = (typeof MonitorStatuses)[number]; export type MonitorMatchMethod = "equal" | "include" | "regex" | ""; @@ -64,7 +64,7 @@ export interface MonitorsSummary { pausedMonitors: number; initializingMonitors: number; maintenanceMonitors: number; - exceededMonitors: number; + breachedMonitors: number; } export interface MonitorsWithChecksByTeamIdResult {