## Changes ### Server - Add `locations` field to Monitor model and types (up to 5 locations per monitor) - Add `location` field to Check metadata for per-location tracking - Add `globalpingApiKey` to AppSettings for API key management - Create GlobalpingService that wraps the Globalping SDK to run distributed HTTP/ping checks from multiple global locations (NA, EU, AS, SA, OC, AF) - Extend SuperSimpleQueueHelper with fire-and-forget Globalping checks that run alongside the existing local check without affecting the main pipeline - Add location-aware check queries with aggregation pipeline grouping by location in MongoChecksRepository - Filter location checks from main uptime aggregation to preserve local check as source of truth for status/incidents - Extend monitor details endpoint to return per-location check data - Add GET /globalping/locations endpoint for available location options - Add globalpingKeySet to settings response - Add Joi validation for locations and globalpingApiKey fields ### Client - Add locations multi-select (Autocomplete with chips) to monitor creation form, shown only for HTTP and ping monitor types - Add SettingsGlobalping component for API key management (matching existing PageSpeed pattern with set/reset flow) - Add per-location breakdown section to uptime details page with tabs, avg response time, uptime percentage, and response time charts - Add globe icon with tooltip to monitor table for monitors with locations - Add Zod validation for locations field in HTTP and ping schemas - Add all translation keys for globalping settings, locations form, and location details sections ## Benefits - Users gain visibility into geographic availability and latency data - Local check remains the source of truth, Globalping runs alongside - Supports up to 5 locations per monitor with 6 continent-level options - Graceful degradation when API key is not configured or rate limited
66 lines
2.7 KiB
TypeScript
Executable File
66 lines
2.7 KiB
TypeScript
Executable File
import { Router } from "express";
|
|
import { isAllowed } from "@/middleware/isAllowed.js";
|
|
import multer from "multer";
|
|
import { fetchMonitorCertificate } from "@/controllers/controllerUtils.js";
|
|
const upload = multer({
|
|
storage: multer.memoryStorage(), // Store file in memory as Buffer
|
|
});
|
|
|
|
class MonitorRoutes {
|
|
private router: Router;
|
|
private monitorController: any;
|
|
constructor(monitorController: any) {
|
|
this.router = Router();
|
|
this.monitorController = monitorController;
|
|
this.initRoutes();
|
|
}
|
|
|
|
initRoutes() {
|
|
// Team routes
|
|
this.router.get("/team", this.monitorController.getMonitorsByTeamId);
|
|
this.router.get("/team/with-checks", this.monitorController.getMonitorsWithChecksByTeamId);
|
|
this.router.get("/team/groups", this.monitorController.getGroupsByTeamId);
|
|
|
|
// Globalping locations
|
|
this.router.get("/globalping/locations", this.monitorController.getGlobalpingLocations);
|
|
|
|
// Uptime routes
|
|
this.router.get("/uptime/details/:monitorId", this.monitorController.getUptimeDetailsById);
|
|
|
|
// Hardware routes
|
|
this.router.get("/hardware/details/:monitorId", this.monitorController.getHardwareDetailsById);
|
|
// PageSpeed routes
|
|
this.router.get("/pagespeed/details/:monitorId", this.monitorController.getPageSpeedDetailsById);
|
|
|
|
// General monitor routes
|
|
this.router.post("/pause/:monitorId", isAllowed(["admin", "superadmin"]), this.monitorController.pauseMonitor);
|
|
|
|
// Util routes
|
|
this.router.get("/certificate/:monitorId", (req, res, next) => {
|
|
this.monitorController.getMonitorCertificate(req, res, next, fetchMonitorCertificate);
|
|
});
|
|
|
|
// General monitor CRUD routes
|
|
this.router.post("/", isAllowed(["admin", "superadmin"]), this.monitorController.createMonitor);
|
|
this.router.delete("/", isAllowed(["superadmin"]), this.monitorController.deleteAllMonitors);
|
|
|
|
// Other static routes
|
|
this.router.post("/demo", isAllowed(["admin", "superadmin"]), this.monitorController.addDemoMonitors);
|
|
this.router.get("/export/json", isAllowed(["admin", "superadmin"]), this.monitorController.exportMonitorsToJSON);
|
|
this.router.post("/bulk", isAllowed(["admin", "superadmin"]), upload.single("csvFile"), this.monitorController.createBulkMonitors);
|
|
this.router.post("/test-email", isAllowed(["admin", "superadmin"]), this.monitorController.sendTestEmail);
|
|
this.router.get("/games", this.monitorController.getAllGames);
|
|
|
|
// Individual monitor CRUD routes
|
|
this.router.get("/:monitorId", this.monitorController.getMonitorById);
|
|
this.router.patch("/:monitorId", isAllowed(["admin", "superadmin"]), this.monitorController.editMonitor);
|
|
this.router.delete("/:monitorId", isAllowed(["admin", "superadmin"]), this.monitorController.deleteMonitor);
|
|
}
|
|
|
|
getRouter() {
|
|
return this.router;
|
|
}
|
|
}
|
|
|
|
export default MonitorRoutes;
|