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 {