diff --git a/client/src/pages/docker/DockerMonitors.tsx b/client/src/pages/docker/DockerMonitors.tsx
index 56cb963d0..b71a42897 100644
--- a/client/src/pages/docker/DockerMonitors.tsx
+++ b/client/src/pages/docker/DockerMonitors.tsx
@@ -70,7 +70,7 @@ const DockerMonitorsPage = () => {
const monitorLimitReached = useLimitReached("monitorsMax", count);
const handleConfirm = async () => {
- await deleteFn(`/monitors/${selectedMonitor?._id}`);
+ await deleteFn(`/monitors/${selectedMonitor?.id}`);
setSelectedMonitor(null);
refetch();
};
diff --git a/client/src/pages/docker/DockerMonitorsTable.tsx b/client/src/pages/docker/DockerMonitorsTable.tsx
index 066d909dd..e7f77e770 100644
--- a/client/src/pages/docker/DockerMonitorsTable.tsx
+++ b/client/src/pages/docker/DockerMonitorsTable.tsx
@@ -58,17 +58,17 @@ export const DockerMonitorsTable = ({
{
id: 2,
label: t("monitors.common.actions.details"),
- action: () => navigate(`/docker/${monitor._id}`),
+ action: () => navigate(`/docker/${monitor.id}`),
},
{
id: 3,
label: t("monitors.common.actions.incidents"),
- action: () => navigate(`/incidents?monitorId=${monitor._id}`),
+ action: () => navigate(`/incidents?monitorId=${monitor.id}`),
},
{
id: 4,
label: t("monitors.common.actions.configure"),
- action: () => navigate(`/docker/${monitor._id}/configure`),
+ action: () => navigate(`/docker/${monitor.id}/configure`),
},
{
id: 6,
@@ -77,7 +77,7 @@ export const DockerMonitorsTable = ({
? t("common.buttons.resume")
: t("common.buttons.pause"),
action: async () => {
- await patch(`/monitors/${monitor._id}/active`);
+ await patch(`/monitors/${monitor.id}/active`);
refetch();
},
closeMenu: true,
@@ -124,7 +124,7 @@ export const DockerMonitorsTable = ({
),
render: (row) => {
const containerCount = (
- checksMap[row._id]?.[0]?.dockerContainers || []
+ checksMap[row.id]?.[0]?.dockerContainers || []
).filter((c: any) => c?.running).length;
return containerCount;
},
@@ -145,7 +145,7 @@ export const DockerMonitorsTable = ({
navigate(`/docker/${row._id}`)}
+ onRowClick={(row) => navigate(`/docker/${row.id}`)}
/>
{
const monitorLimitReached = useLimitReached("monitorsMax", count);
const handleConfirm = async () => {
- await deleteFn(`/monitors/${selectedMonitor?._id}`);
+ await deleteFn(`/monitors/${selectedMonitor?.id}`);
setSelectedMonitor(null);
refetch();
};
diff --git a/client/src/pages/infrastructure/InfraMonitorsTable.tsx b/client/src/pages/infrastructure/InfraMonitorsTable.tsx
index 8035c2db0..8c3e17a99 100644
--- a/client/src/pages/infrastructure/InfraMonitorsTable.tsx
+++ b/client/src/pages/infrastructure/InfraMonitorsTable.tsx
@@ -97,21 +97,21 @@ export const InfraMonitorsTable = ({
id: 2,
label: t("monitors.common.actions.details"),
action: () => {
- navigate(`${monitor._id}`);
+ navigate(`${monitor.id}`);
},
},
{
id: 3,
label: t("monitors.common.actions.incidents"),
action: () => {
- navigate(`/incidents?monitorId=${monitor._id}`);
+ navigate(`/incidents?monitorId=${monitor.id}`);
},
},
{
id: 4,
label: t("monitors.common.actions.configure"),
action: () => {
- navigate(`/infrastructure/${monitor._id}/configure`);
+ navigate(`/infrastructure/${monitor.id}/configure`);
},
},
// {
@@ -128,7 +128,7 @@ export const InfraMonitorsTable = ({
? t("common.buttons.resume")
: t("common.buttons.pause"),
action: async () => {
- await patch(`/monitors/${monitor._id}/active`);
+ await patch(`/monitors/${monitor.id}/active`);
refetch();
},
closeMenu: true,
@@ -208,7 +208,7 @@ export const InfraMonitorsTable = ({
content: t("monitors.infrastructure.table.headers.cpu"),
render: (row) => {
const cpuUsage =
- (checksMap[row._id]?.[0]?.system?.cpu?.usage_percent || 0) * 100;
+ (checksMap[row.id]?.[0]?.system?.cpu?.usage_percent || 0) * 100;
return ;
},
},
@@ -217,7 +217,7 @@ export const InfraMonitorsTable = ({
content: t("monitors.infrastructure.table.headers.memory"),
render: (row) => {
const memoryUsage =
- (checksMap[row._id]?.[0]?.system?.memory?.usage_percent || 0) * 100;
+ (checksMap[row.id]?.[0]?.system?.memory?.usage_percent || 0) * 100;
return ;
},
},
@@ -225,11 +225,11 @@ export const InfraMonitorsTable = ({
id: "disk",
content: t("monitors.infrastructure.table.headers.disk"),
render: (row) => {
- const totalDiskUsage = checksMap[row._id]?.[0]?.system?.disk?.reduce(
+ const totalDiskUsage = checksMap[row.id]?.[0]?.system?.disk?.reduce(
(acc, disk) => acc + disk.usage_percent,
0
);
- const diskCount = checksMap[row._id]?.[0]?.system?.disk?.length || 1;
+ const diskCount = checksMap[row.id]?.[0]?.system?.disk?.length || 1;
const diskUsage = ((totalDiskUsage || 0) / diskCount) * 100;
return ;
},
@@ -257,7 +257,7 @@ export const InfraMonitorsTable = ({
headers={headers}
data={monitors}
onRowClick={(row) => {
- navigate(`/infrastructure/${row._id}`);
+ navigate(`/infrastructure/${row.id}`);
}}
/>
{
- navigate(`${monitor._id}`);
+ navigate(`${monitor.id}`);
},
},
{
id: 3,
label: t("monitors.common.actions.incidents"),
action: () => {
- navigate(`/incidents?monitorId=${monitor._id}`);
+ navigate(`/incidents?monitorId=${monitor.id}`);
},
},
{
id: 4,
label: t("monitors.common.actions.configure"),
action: () => {
- navigate(`/pagespeed/${monitor._id}/configure`);
+ navigate(`/pagespeed/${monitor.id}/configure`);
},
},
// {
@@ -129,7 +129,7 @@ export const PageSpeedMonitorTable = ({
? t("common.buttons.resume")
: t("common.buttons.pause"),
action: async () => {
- await patch(`/monitors/${monitor._id}/active`);
+ await patch(`/monitors/${monitor.id}/active`);
refetch();
},
closeMenu: true,
@@ -207,7 +207,7 @@ export const PageSpeedMonitorTable = ({
return (
@@ -237,7 +237,7 @@ export const PageSpeedMonitorTable = ({
headers={headers}
data={monitors}
onRowClick={(row) => {
- navigate(`/pagespeed/${row._id}`);
+ navigate(`/pagespeed/${row.id}`);
}}
/>
{
const monitorLimitReached = useLimitReached("monitorsMax", count);
const handleConfirm = async () => {
- await deleteFn(`/monitors/${selectedMonitor?._id}`);
+ await deleteFn(`/monitors/${selectedMonitor?.id}`);
setSelectedMonitor(null);
refetch();
};
diff --git a/client/src/pages/uptime/UptimeDetails.tsx b/client/src/pages/uptime/UptimeDetails.tsx
index b22292b1c..cf75ebc50 100644
--- a/client/src/pages/uptime/UptimeDetails.tsx
+++ b/client/src/pages/uptime/UptimeDetails.tsx
@@ -155,7 +155,7 @@ const UptimeDetailsPage = () => {
-
+
);
};
diff --git a/client/src/pages/uptime/UptimeMonitors.tsx b/client/src/pages/uptime/UptimeMonitors.tsx
index 429b3c323..49d270626 100644
--- a/client/src/pages/uptime/UptimeMonitors.tsx
+++ b/client/src/pages/uptime/UptimeMonitors.tsx
@@ -97,7 +97,7 @@ const UptimeMonitors = () => {
const monitorLimitReached = useLimitReached("monitorsMax", count);
const handleConfirm = async () => {
- await deleteFn(`/monitors/${selectedMonitor?._id}`);
+ await deleteFn(`/monitors/${selectedMonitor?.id}`);
setSelectedMonitor(null);
refetch();
};
diff --git a/client/src/pages/uptime/UptimeMonitorsTable.tsx b/client/src/pages/uptime/UptimeMonitorsTable.tsx
index dbabecb5c..b4a53afb0 100644
--- a/client/src/pages/uptime/UptimeMonitorsTable.tsx
+++ b/client/src/pages/uptime/UptimeMonitorsTable.tsx
@@ -102,21 +102,21 @@ export const MonitorTable = ({
id: 2,
label: t("monitors.common.actions.details"),
action: () => {
- navigate(`${monitor._id}`);
+ navigate(`${monitor.id}`);
},
},
{
id: 3,
label: t("monitors.common.actions.incidents"),
action: () => {
- navigate(`/incidents?monitorId=${monitor._id}`);
+ navigate(`/incidents?monitorId=${monitor.id}`);
},
},
{
id: 4,
label: t("monitors.common.actions.configure"),
action: () => {
- navigate(`/uptime/${monitor._id}/configure`);
+ navigate(`/uptime/${monitor.id}/configure`);
},
},
// {
@@ -133,7 +133,7 @@ export const MonitorTable = ({
? t("common.buttons.resume")
: t("common.buttons.pause"),
action: async () => {
- await patch(`/monitors/${monitor._id}/active`);
+ await patch(`/monitors/${monitor.id}/active`);
refetch();
},
closeMenu: true,
@@ -209,9 +209,9 @@ export const MonitorTable = ({
content: t("monitors.uptime.table.headers.responseTime"),
render: (row) => {
if (chartType === "histogram") {
- return ;
+ return ;
} else {
- return ;
+ return ;
}
},
},
@@ -253,7 +253,7 @@ export const MonitorTable = ({
headers={headers}
data={monitors}
onRowClick={(row) => {
- navigate(`/uptime/${row._id}`);
+ navigate(`/uptime/${row.id}`);
}}
/>
{
down: "error",
paused: "warning",
initializing: "warning",
+ resuming: "warning",
};
return paletteMap[status];
};
@@ -40,6 +41,7 @@ export const getStatusColor = (status: MonitorStatus, theme: any): string => {
down: theme.palette.error.light,
paused: theme.palette.warning.light,
initializing: theme.palette.warning.light,
+ resuming: theme.palette.warning.light,
};
return statusColors[status];
};
diff --git a/server/src/init/services.ts b/server/src/init/services.ts
index 866f08696..f58773a48 100644
--- a/server/src/init/services.ts
+++ b/server/src/init/services.ts
@@ -33,6 +33,7 @@ import {
} from "@/services/index.js";
import { EntitlementsFactory } from "@/services/system/EntitlementsService.js";
import { MeService } from "@/services/index.js";
+import { MongoMonitorRepository } from "@/repositories/index.js";
export const initServices = async () => {
const checkService = new CheckService();
@@ -71,7 +72,8 @@ export const initServices = async () => {
const entitlementsProvider = EntitlementsFactory.create();
const authService = new AuthService(jobQueue, entitlementsProvider);
const meService = new MeService(entitlementsProvider);
- const monitorService = new MonitorService(jobQueue);
+ const monitorRepository = new MongoMonitorRepository();
+ const monitorService = new MonitorService(jobQueue, monitorRepository);
const queueService = new QueueService(jobQueue);
const teamService = new TeamService(jobQueue);
const roleService = new RoleService();
diff --git a/server/src/repositories/checks/ICheckRepository.ts b/server/src/repositories/checks/ICheckRepository.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/server/src/repositories/checks/MongoChecksRepository.ts b/server/src/repositories/checks/MongoChecksRepository.ts
deleted file mode 100644
index 9265c0b1e..000000000
--- a/server/src/repositories/checks/MongoChecksRepository.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Check } from "@/db/models/index.js";
-import type { ICheck } from "@/db/models/index.js";
-import type { IChecksRepository } from "@/repositories/checks/IChecksRepository.js";
-import { CheckEntity } from "@/types/domain/check.js";
-import mongoose from "mongoose";
-
-export class MongoChecksRepository implements IChecksRepository {
- private toEntity = (check: ICheck): CheckEntity => {
- return {
- id: check._id.toString(),
- metadata: {
- monitorId: check.metadata.monitorId.toString(),
- teamId: check.metadata.teamId.toString(),
- type: check.metadata.type,
- },
- status: check.status,
- httpStatusCode: check.httpStatusCode,
- message: check.message,
- timings: check.timings,
- errorMessage: check.errorMessage,
- ackAt: check.ackAt,
- ackBy: check.ackBy?.toString(),
- system: check.system,
- capture: check.capture,
- lighthouse: check.lighthouse,
- dockerContainers: check.dockerContainers,
- createdAt: check.createdAt,
- updatedAt: check.updatedAt,
- expiry: check.expiry,
- };
- };
-
- findLatestByMonitorIds = async (monitorIds: string[]) => {
- const checks = await Check.aggregate([
- {
- $match: {
- "metadata.monitorId": {
- $in: monitorIds.map((id) => new mongoose.Types.ObjectId(id)),
- },
- },
- },
- { $sort: { createdAt: -1 } },
- {
- $group: {
- _id: "$metadata.monitorId",
- latestChecks: { $push: "$$ROOT" },
- },
- },
- {
- $project: {
- latestChecks: { $slice: [{ $ifNull: ["$latestChecks", []] }, 25] },
- },
- },
- ]);
- console.log(checks);
- return checks;
- };
-}
diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts
new file mode 100644
index 000000000..0d32ec8a1
--- /dev/null
+++ b/server/src/repositories/index.ts
@@ -0,0 +1,5 @@
+export type {
+ IMonitorRepository,
+ TeamQueryConfig,
+} from "@/repositories/monitors/IMonitorRepoistory.js";
+export { default as MongoMonitorRepository } from "@/repositories/monitors/MongoMonitorRepository.js";
diff --git a/server/src/repositories/monitors/IMonitorRepoistory.ts b/server/src/repositories/monitors/IMonitorRepoistory.ts
new file mode 100644
index 000000000..702fd29ad
--- /dev/null
+++ b/server/src/repositories/monitors/IMonitorRepoistory.ts
@@ -0,0 +1,41 @@
+import type {
+ Monitor,
+ MonitorType,
+ MonitorStatus,
+} from "@/types/domain/monitor.js";
+
+export interface TeamQueryConfig {
+ search: string;
+ sortField: string;
+ sortOrder: string;
+ page: number;
+ rowsPerPage: number;
+ type: MonitorType[];
+ status: MonitorStatus[];
+}
+
+export interface IMonitorRepository {
+ // Single fetch
+ findById(monitorId: string, teamId: string): Promise;
+
+ // Collection fetches
+ findByTeamId(teamId: string): Promise;
+ findByTeamIdWithConfig(
+ teamId: string,
+ config: TeamQueryConfig
+ ): Promise;
+
+ findMonitorCountsByTeamId(teamId: string): Promise<{
+ total: number;
+ upCount: number;
+ downCount: number;
+ pausedCount: number;
+ }>;
+ findByOrgId(orgId: string): Promise;
+
+ // Deletions
+ deleteById(id: string): Promise;
+ deleteByOrgId(orgId: string): Promise;
+}
+
+export default IMonitorRepository;
diff --git a/server/src/repositories/monitors/MongoMonitorRepository.ts b/server/src/repositories/monitors/MongoMonitorRepository.ts
new file mode 100644
index 000000000..a889af178
--- /dev/null
+++ b/server/src/repositories/monitors/MongoMonitorRepository.ts
@@ -0,0 +1,126 @@
+import { Monitor, IMonitor } from "@/db/models/index.js";
+import { IMonitorRepository, TeamQueryConfig } from "@/repositories/index.js";
+import type { Monitor as MonitorEntity } from "@/types/domain/monitor.js";
+import mongoose from "mongoose";
+class MongoMonitorRepository implements IMonitorRepository {
+ private toEntity = (monitor: IMonitor): MonitorEntity => {
+ return {
+ id: monitor._id.toString(),
+ orgId: monitor.orgId.toString(),
+ teamId: monitor.teamId.toString(),
+ name: monitor.name,
+ url: monitor.url,
+ port: monitor.port,
+ secret: monitor.secret,
+ type: monitor.type,
+ interval: monitor.interval,
+ rejectUnauthorized: monitor.rejectUnauthorized,
+ status: monitor.status,
+ n: monitor.n,
+ thresholds: monitor.thresholds,
+ lastCheckedAt: monitor.lastCheckedAt,
+ latestStatuses: monitor.latestStatuses,
+ notificationChannels: monitor.notificationChannels?.map((id) =>
+ id.toString()
+ ),
+ createdBy: monitor.createdBy.toString(),
+ updatedBy: monitor.updatedBy.toString(),
+ createdAt: monitor.createdAt,
+ updatedAt: monitor.updatedAt,
+ };
+ };
+
+ // Single fetch
+ findById = async (monitorId: string, teamId: string) => {
+ const monitor = await Monitor.findOne({ _id: monitorId, teamId });
+ if (!monitor) return null;
+ return this.toEntity(monitor);
+ };
+
+ // Collection fetches
+ findByTeamId = async (teamId: string) => {
+ const monitors = await Monitor.find({ teamId });
+ return monitors.map(this.toEntity);
+ };
+
+ findByTeamIdWithConfig = async (teamId: string, config: TeamQueryConfig) => {
+ if (!config) {
+ const monitors = await Monitor.find({ teamId });
+ return monitors.map(this.toEntity);
+ }
+
+ const { search, sortField, sortOrder, page, rowsPerPage, type, status } =
+ config;
+
+ const match: Record = {
+ teamId: new mongoose.Types.ObjectId(teamId),
+ };
+
+ if (search && search.trim() !== "") {
+ const term = search.trim();
+ (match as any).$or = [
+ { name: { $regex: term, $options: "i" } },
+ { url: { $regex: term, $options: "i" } },
+ ];
+ }
+
+ if (Array.isArray(type) && type.length > 0) {
+ match.type = { $in: type };
+ }
+
+ if (Array.isArray(status) && status.length > 0) {
+ match.status = { $in: status };
+ }
+
+ const skip = page * rowsPerPage;
+
+ const monitors = await Monitor.find(match)
+ .sort({ [sortField]: sortOrder === "asc" ? 1 : -1 })
+ .skip(skip)
+ .limit(rowsPerPage);
+
+ return monitors.map(this.toEntity);
+ };
+ findByOrgId = async (orgId: string) => {
+ return [];
+ };
+
+ findMonitorCountsByTeamId = async (teamId: string) => {
+ const countResult = await Monitor.aggregate([
+ {
+ $match: { teamId: new mongoose.Types.ObjectId(teamId) },
+ },
+ {
+ $group: {
+ _id: null,
+ total: { $sum: 1 },
+ upCount: { $sum: { $cond: [{ $eq: ["$status", "up"] }, 1, 0] } },
+ downCount: { $sum: { $cond: [{ $eq: ["$status", "down"] }, 1, 0] } },
+ pausedCount: {
+ $sum: {
+ $cond: [{ $in: ["$status", ["paused", "resuming"]] }, 1, 0],
+ },
+ },
+ },
+ },
+ ]);
+
+ const counts = countResult[0] || {
+ total: 0,
+ upCount: 0,
+ downCount: 0,
+ pausedCount: 0,
+ };
+ return counts;
+ };
+
+ // Deletions
+ deleteById = async (id: string) => {
+ return false;
+ };
+ deleteByOrgId = async (orgId: string) => {
+ return 0;
+ };
+}
+
+export default MongoMonitorRepository;
diff --git a/server/src/services/business/MonitorService.ts b/server/src/services/business/MonitorService.ts
index 3b7aee38c..abf8f864f 100644
--- a/server/src/services/business/MonitorService.ts
+++ b/server/src/services/business/MonitorService.ts
@@ -8,6 +8,8 @@ import { MonitorWithChecksResponse } from "@/types/index.js";
import { MonitorStatus, MonitorType } from "@/db/models/monitors/Monitor.js";
import { Entitlements } from "@/types/entitlements.js";
import { getStartDate } from "@/utils/TimeUtils.js";
+import { IMonitorRepository } from "@/repositories/index.js";
+import type { Monitor as MonitorEntity } from "@/types/domain/index.js";
export interface IImportedMonitor {
name: string;
@@ -44,7 +46,7 @@ export interface IMonitorService {
currentTeamId: string,
monitorData: IMonitor
) => Promise;
- getAll: (teamId: string) => Promise;
+ getAll: (teamId: string) => Promise;
getAllEmbedChecks: (
teamId: string,
search: string,
@@ -61,7 +63,7 @@ export interface IMonitorService {
pausedCount: number;
monitors: any[];
}>;
- get: (teamId: string, monitorId: string) => Promise;
+ get: (teamId: string, monitorId: string) => Promise;
getEmbedChecks: (
teamId: string,
monitorId: string,
@@ -93,9 +95,11 @@ export interface IMonitorService {
class MonitorService implements IMonitorService {
public SERVICE_NAME: string;
private jobQueue: IJobQueue;
- constructor(jobQueue: IJobQueue) {
+ private monitorRepository: IMonitorRepository;
+ constructor(jobQueue: IJobQueue, monitorRepository: IMonitorRepository) {
this.SERVICE_NAME = SERVICE_NAME;
this.jobQueue = jobQueue;
+ this.monitorRepository = monitorRepository;
}
create = async (
@@ -122,7 +126,7 @@ class MonitorService implements IMonitorService {
};
getAll = async (teamId: string) => {
- return Monitor.find({ teamId });
+ return await this.monitorRepository.findByTeamId(teamId);
};
getAllEmbedChecks = async (
@@ -135,61 +139,24 @@ class MonitorService implements IMonitorService {
type: MonitorType[] = [],
status: MonitorStatus[] = []
) => {
- const teamObjectId = new mongoose.Types.ObjectId(teamId);
+ const counts = await this.monitorRepository.findMonitorCountsByTeamId(
+ teamId
+ );
- const matchConditions: Record = {
- teamId: teamObjectId,
- };
-
- if (search && search.trim() !== "") {
- const term = search.trim();
- (matchConditions as any).$or = [
- { name: { $regex: term, $options: "i" } },
- { url: { $regex: term, $options: "i" } },
- ];
- }
-
- if (Array.isArray(type) && type.length > 0) {
- matchConditions.type = { $in: type };
- }
-
- if (Array.isArray(status) && status.length > 0) {
- matchConditions.status = { $in: status };
- }
-
- const countResult = await Monitor.aggregate([
+ const monitors = await this.monitorRepository.findByTeamIdWithConfig(
+ teamId,
{
- $match: { teamId: teamObjectId },
- },
- {
- $group: {
- _id: null,
- total: { $sum: 1 },
- upCount: { $sum: { $cond: [{ $eq: ["$status", "up"] }, 1, 0] } },
- downCount: { $sum: { $cond: [{ $eq: ["$status", "down"] }, 1, 0] } },
- pausedCount: {
- $sum: { $cond: [{ $eq: ["$status", "paused"] }, 1, 0] },
- },
- },
- },
- ]);
+ search,
+ sortField,
+ sortOrder,
+ page,
+ rowsPerPage,
+ type,
+ status,
+ }
+ );
- const counts = countResult[0] || {
- total: 0,
- upCount: 0,
- downCount: 0,
- pausedCount: 0,
- };
-
- const skip = page * rowsPerPage;
-
- const monitors = await Monitor.find(matchConditions)
- .lean()
- .sort({ [sortField]: sortOrder === "asc" ? 1 : -1 })
- .skip(skip)
- .limit(rowsPerPage);
-
- const monitorIds = monitors.map((m) => m._id);
+ const monitorIds = monitors.map((m) => new mongoose.Types.ObjectId(m.id));
const checks = await Check.aggregate([
{
@@ -226,7 +193,7 @@ class MonitorService implements IMonitorService {
};
get = async (teamId: string, monitorId: string) => {
- const monitor = await Monitor.findOne({ _id: monitorId, teamId });
+ const monitor = await this.monitorRepository.findById(monitorId, teamId);
if (!monitor) {
throw new ApiError("Monitor not found", 404);
}
@@ -555,13 +522,16 @@ class MonitorService implements IMonitorService {
return {};
};
- private getEmbedChecksRecent = async (monitor: IMonitor, startDate: Date) => {
+ private getEmbedChecksRecent = async (
+ monitor: MonitorEntity,
+ startDate: Date
+ ) => {
const endDate = new Date();
const matchStage: {
"metadata.monitorId": mongoose.Types.ObjectId;
createdAt: { $gte: Date; $lt: Date };
} = {
- "metadata.monitorId": monitor._id,
+ "metadata.monitorId": new mongoose.Types.ObjectId(monitor.id),
createdAt: { $gte: startDate, $lt: endDate },
};
@@ -652,7 +622,7 @@ class MonitorService implements IMonitorService {
// Get monitor stats
const monitorStats = await MonitorStats.findOne({
- monitorId: monitor._id,
+ monitorId: monitor.id,
});
if (!monitorStats) {
@@ -660,19 +630,19 @@ class MonitorService implements IMonitorService {
}
return {
- monitor: monitor.toObject(),
+ monitor: monitor,
checks,
stats: monitorStats,
};
};
private getEmbedChecksOtherRanges = async (
- monitor: IMonitor,
+ monitor: MonitorEntity,
range: string,
startDate: Date
) => {
const monitorStats = await MonitorStats.findOne({
- monitorId: monitor._id,
+ monitorId: monitor.id,
});
if (!monitorStats) {
throw new ApiError("Monitor stats not found", 404);
@@ -683,7 +653,7 @@ class MonitorService implements IMonitorService {
const endDate = new Date();
const docs = await Model.find({
- monitorId: monitor._id,
+ monitorId: monitor.id,
windowStart: { $gte: startDate, $lt: endDate },
})
.sort({ windowStart: -1 })
@@ -739,7 +709,7 @@ class MonitorService implements IMonitorService {
});
return {
- monitor: monitor.toObject(),
+ monitor: monitor,
checks,
stats: monitorStats,
};
@@ -750,7 +720,7 @@ class MonitorService implements IMonitorService {
monitorId: string,
range: string
): Promise => {
- const monitor = await Monitor.findOne({ _id: monitorId, teamId });
+ const monitor = await this.monitorRepository.findById(monitorId, teamId);
if (!monitor) {
throw new ApiError("Monitor not found", 404);
}
diff --git a/server/src/types/domain/index.ts b/server/src/types/domain/index.ts
new file mode 100644
index 000000000..e7790153d
--- /dev/null
+++ b/server/src/types/domain/index.ts
@@ -0,0 +1 @@
+export type { Monitor } from "@/types/domain/monitor.js";
diff --git a/server/src/types/domain/monitor.ts b/server/src/types/domain/monitor.ts
new file mode 100644
index 000000000..825ab989c
--- /dev/null
+++ b/server/src/types/domain/monitor.ts
@@ -0,0 +1,49 @@
+export const MonitorTypes = [
+ "http",
+ "https",
+ "port",
+ "ping",
+ "infrastructure",
+ "pagespeed",
+ "docker",
+] as const;
+export type MonitorType = (typeof MonitorTypes)[number];
+
+export const MonitorStatuses = [
+ "up",
+ "down",
+ "paused",
+ "initializing",
+ "resuming",
+] as const;
+export type MonitorStatus = (typeof MonitorStatuses)[number];
+
+export interface MonitorThresholds {
+ cpu?: number;
+ memory?: number;
+ disk?: number;
+ temperature?: number;
+}
+
+export interface Monitor {
+ id: string;
+ orgId: string;
+ teamId: string;
+ name: string;
+ url: string;
+ port?: number;
+ secret?: string;
+ type: MonitorType;
+ interval: number; // in ms
+ rejectUnauthorized: boolean;
+ status: MonitorStatus;
+ n: number; // Number of consecutive successes required to change status
+ thresholds?: MonitorThresholds;
+ lastCheckedAt?: Date;
+ latestStatuses?: MonitorStatus[];
+ notificationChannels?: string[];
+ createdBy: string;
+ updatedBy: string;
+ createdAt: Date;
+ updatedAt: Date;
+}
diff --git a/server/src/types/monitor-response-with-checks.ts b/server/src/types/monitor-response-with-checks.ts
index b547459e5..f9e064e44 100644
--- a/server/src/types/monitor-response-with-checks.ts
+++ b/server/src/types/monitor-response-with-checks.ts
@@ -1,7 +1,7 @@
-import { IMonitor, IMonitorStats } from "@/db/models/index.js";
-
+import { IMonitorStats } from "@/db/models/index.js";
+import type { Monitor } from "@/types/domain/index.js";
export interface MonitorWithChecksResponse {
- monitor: IMonitor;
+ monitor: Monitor;
checks: Array<{
_id: string;
count: number;