feat: add per-monitor Globalping toggle
Add a globalpingEnabled boolean to the Monitor model so users can opt-in to global location checks per monitor during creation/edit. ## Changes - Add globalpingEnabled field to server types, Mongoose model, Joi validation, and repository mappers - Add globalpingEnabled to client Monitor type, Zod schemas for HTTP and ping monitors, and form defaults - Add "Global monitoring" ConfigBox with Switch toggle to the monitor creation/edit form, visible for HTTP and ping types - Queue helper and monitorService now check globalpingEnabled before running Globalping checks or fetching location data - Add translation keys for the new form section ## Benefits - Users can selectively enable Globalping on monitors that need it rather than running location checks on every HTTP/ping monitor - Reduces unnecessary API usage and keeps the UI clean for monitors that only need local checks
This commit is contained in:
1 parent
7f9d2f275e
commit
4ca24c794e
11 files changed
+47
-3
No files matched your search
@@ -37,6 +37,7 @@ export const useMonitorForm = ({
|
||||
matchMethod: data?.matchMethod || "",
|
||||
expectedValue: data?.expectedValue || "",
|
||||
jsonPath: data?.jsonPath || "",
|
||||
globalpingEnabled: data?.globalpingEnabled || false,
|
||||
};
|
||||
break;
|
||||
case "ping":
|
||||
@@ -44,6 +45,7 @@ export const useMonitorForm = ({
|
||||
...base,
|
||||
type: "ping",
|
||||
url: data?.url || "",
|
||||
globalpingEnabled: data?.globalpingEnabled || false,
|
||||
};
|
||||
break;
|
||||
case "port":
|
||||
|
||||
@@ -488,6 +488,27 @@ const CreateMonitorPage = () => {
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Global monitoring - only for http and ping types */}
|
||||
{(watchedType === "http" || watchedType === "ping") && (
|
||||
<ConfigBox
|
||||
title={t("pages.createMonitor.form.globalping.title")}
|
||||
subtitle={t("pages.createMonitor.form.globalping.description")}
|
||||
rightContent={
|
||||
<Controller
|
||||
name="globalpingEnabled"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Switch
|
||||
id="globalpingEnabled"
|
||||
isChecked={field.value ?? false}
|
||||
onChange={(e) => field.onChange(e.target.checked)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Alert Thresholds - only for hardware type */}
|
||||
{generalSettingsConfig.showSecret && (
|
||||
<ConfigBox
|
||||
|
||||
@@ -59,6 +59,7 @@ export interface Monitor {
|
||||
gameId?: string;
|
||||
group: string | null;
|
||||
locations: string[];
|
||||
globalpingEnabled: boolean;
|
||||
recentChecks: CheckSnapshot[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
|
||||
@@ -31,12 +31,14 @@ const httpSchema = baseSchema.extend({
|
||||
matchMethod: z.enum(["equal", "include", "regex", ""]).optional(),
|
||||
expectedValue: z.string().optional(),
|
||||
jsonPath: z.string().optional(),
|
||||
globalpingEnabled: z.boolean(),
|
||||
});
|
||||
|
||||
// Ping monitor schema
|
||||
const pingSchema = baseSchema.extend({
|
||||
type: z.literal("ping"),
|
||||
url: z.string().min(1, "Host is required"),
|
||||
globalpingEnabled: z.boolean(),
|
||||
});
|
||||
|
||||
// Port monitor schema
|
||||
|
||||
@@ -445,6 +445,15 @@
|
||||
},
|
||||
"title": "Check frequency"
|
||||
},
|
||||
"globalping": {
|
||||
"title": "Global monitoring",
|
||||
"description": "Run checks from multiple locations around the world using the Globalping network. Configure the API key and location count in settings.",
|
||||
"option": {
|
||||
"enabled": {
|
||||
"label": "Enable Globalping"
|
||||
}
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"option": {
|
||||
"container": {
|
||||
|
||||
@@ -164,6 +164,10 @@ const MonitorSchema = new Schema<MonitorDocument>(
|
||||
type: [String],
|
||||
default: [],
|
||||
},
|
||||
globalpingEnabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
group: {
|
||||
type: String,
|
||||
trim: true,
|
||||
|
||||
@@ -344,6 +344,7 @@ class MongoMonitorsRepository implements IMonitorsRepository {
|
||||
gameId: doc.gameId ?? undefined,
|
||||
group: doc.group ?? null,
|
||||
locations: doc.locations ?? [],
|
||||
globalpingEnabled: doc.globalpingEnabled ?? false,
|
||||
recentChecks: (doc.recentChecks ?? []).map((check: any) => this.toCheckSnapshot(check)),
|
||||
createdAt: toDateString(doc.createdAt),
|
||||
updatedAt: toDateString(doc.updatedAt),
|
||||
@@ -400,6 +401,7 @@ class MongoMonitorsRepository implements IMonitorsRepository {
|
||||
gameId: doc.gameId ?? undefined,
|
||||
group: doc.group ?? null,
|
||||
locations: doc.locations ?? [],
|
||||
globalpingEnabled: doc.globalpingEnabled ?? false,
|
||||
recentChecks: (doc.recentChecks ?? []).map((check: any) => this.toCheckSnapshot(check)),
|
||||
createdAt: toDateString(doc.createdAt),
|
||||
updatedAt: toDateString(doc.updatedAt),
|
||||
|
||||
@@ -223,9 +223,9 @@ export class MonitorService implements IMonitorService {
|
||||
throw new AppError({ message: `${monitor.type} monitors are not supported for uptime details`, status: 400 });
|
||||
}
|
||||
|
||||
// Fetch location checks if this is an HTTP or ping monitor
|
||||
// Fetch location checks if Globalping is enabled for this monitor
|
||||
let locationChecks: Record<string, LocationCheckData> | undefined;
|
||||
if (monitor.type === "http" || monitor.type === "ping") {
|
||||
if (monitor.globalpingEnabled && (monitor.type === "http" || monitor.type === "ping")) {
|
||||
const locData = await this.checksRepository.findLocationChecksByMonitorId(
|
||||
monitor.id,
|
||||
start,
|
||||
|
||||
@@ -128,7 +128,7 @@ class SuperSimpleQueueHelper {
|
||||
}
|
||||
|
||||
// Step 2b. Run Globalping checks (fire-and-forget, doesn't affect local check pipeline)
|
||||
if (monitor.type === "http" || monitor.type === "ping") {
|
||||
if (monitor.globalpingEnabled && (monitor.type === "http" || monitor.type === "ping")) {
|
||||
this.globalpingService
|
||||
.runChecks(monitor)
|
||||
.then((locationStatuses) => {
|
||||
|
||||
@@ -44,6 +44,7 @@ export interface Monitor {
|
||||
gameId?: string;
|
||||
group: string | null;
|
||||
locations: string[];
|
||||
globalpingEnabled: boolean;
|
||||
recentChecks: CheckSnapshot[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
|
||||
@@ -173,6 +173,7 @@ const createMonitorBodyValidation = joi.object({
|
||||
selectedDisks: joi.array().items(joi.string()).optional(),
|
||||
group: joi.string().max(50).trim().allow(null, "").optional(),
|
||||
locations: joi.array().items(joi.string()).max(5).optional(),
|
||||
globalpingEnabled: joi.boolean().optional(),
|
||||
});
|
||||
|
||||
const createMonitorsBodyValidation = joi.array().items(
|
||||
@@ -205,6 +206,7 @@ const editMonitorBodyValidation = joi
|
||||
selectedDisks: joi.array().items(joi.string()).optional(),
|
||||
group: joi.string().max(50).trim().allow(null, "").optional(),
|
||||
locations: joi.array().items(joi.string()).max(5).optional(),
|
||||
globalpingEnabled: joi.boolean().optional(),
|
||||
})
|
||||
.options({ stripUnknown: true });
|
||||
|
||||
|
||||
Reference in new issue
Block a user