Generated detailed architecture guide covering: - Project structure and technology stack - Monitor types and implementation patterns - Database schema and models - API patterns and endpoints - Job scheduling and polling mechanisms - Frontend components and UI structure - Authentication and configuration flow This documentation supports the Docker monitoring integration with Capture API.
27 KiB
Checkmate Codebase Architecture - Docker Monitoring Integration Guide
1. PROJECT STRUCTURE
Directory Layout
Checkmate/
├── server/ # Backend Node.js/Express
│ ├── src/
│ │ ├── db/v1|v2/ # Database (MongoDB)
│ │ ├── service/v1|v2/ # Business logic
│ │ ├── routes/v1|v2/ # API routes
│ │ ├── controllers/v1|v2/ # HTTP request handlers
│ │ ├── middleware/v1/ # Express middleware
│ │ ├── config/ # Service initialization
│ │ ├── validation/ # Input validation
│ │ └── utils/ # Helper functions
│ └── package.json # Dependencies (Node >=20)
├── client/ # Frontend React + TypeScript
│ ├── src/
│ │ ├── Components/v1|v2/ # UI Components
│ │ ├── Pages/v1|v2/ # Page layouts
│ │ ├── Hooks/ # React hooks (data fetching)
│ │ ├── Features/ # Redux slices
│ │ └── Utils/ # Utilities & API client
│ └── package.json # React, Vite, MUI
└── docker/ # Deployment configs
Technology Stack
Backend:
- Express 4.19 (HTTP server)
- MongoDB 8.3 (database)
- Mongoose (ODM)
- BullMQ 5.41 (job queue) - V2 only
- super-simple-scheduler 1.4 (job scheduling) - V1
- Dockerode 4.0.6 (Docker API client)
- JWT authentication
- Winston (logging)
Frontend:
- React 18.3 + TypeScript
- Vite (build tool)
- MUI v6 (Material-UI)
- Redux Toolkit (state management)
- Axios (HTTP client)
- React Router (navigation)
- i18next (internationalization)
Architectures:
- V1: Simpler, SuperSimpleQueue-based job scheduling
- V2: TypeScript-based, BullMQ, more structured (in development)
2. MONITOR TYPES & IMPLEMENTATION
Supported Monitor Types
Defined in /server/src/db/v1/models/Monitor.js line 46:
type: {
enum: ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"],
required: true
}
How Monitor Types Are Handled
Request Dispatch (NetworkService)
Location: /server/src/service/v1/infrastructure/networkService.js (580 lines)
Entry point: requestStatus(monitor) - Routes to type-specific handlers:
async requestStatus(monitor) {
switch(monitor.type) {
case "ping": return await this.requestPing(monitor);
case "http": return await this.requestHttp(monitor);
case "pagespeed": return await this.requestPageSpeed(monitor);
case "hardware": return await this.requestHardware(monitor);
case "docker": return await this.requestDocker(monitor);
case "port": return await this.requestPort(monitor);
case "game": return await this.requestGame(monitor);
}
}
DOCKER IMPLEMENTATION (Lines 289-383)
async requestDocker(monitor) {
// Uses Dockerode to connect to /var/run/docker.sock
const docker = new this.Docker({
socketPath: "/var/run/docker.sock",
handleError: true,
});
// Container matching (priority-based):
// 1. Exact full ID match (64-char)
// 2. Exact name match (case-insensitive)
// 3. Partial ID match (backwards compatibility)
// Returns: { status: bool, code: int, message: string, responseTime: ms }
}
Docker Monitor Storage:
monitor.url: Container ID or name (e.g., "my-app" or "a1b2c3d4...")monitor.port: Not used for Docker- Returns: Only status and response time (no detailed metrics)
HARDWARE IMPLEMENTATION (Lines 279-287)
async requestHardware(monitor) {
return await this.requestHttp(monitor); // Delegates to HTTP!
}
Hardware monitors send HTTP requests to Capture API endpoint with secret authentication.
Hardware/Docker Check Data Structure
Location: /server/src/db/v1/models/Check.js (176 lines)
Check schema includes:
// Common fields
monitorId, teamId, type, status, responseTime, message
// Hardware/Docker specific (capture data):
cpu: {
physical_core, logical_core, frequency, temperature[],
free_percent, usage_percent
},
memory: {
total_bytes, available_bytes, used_bytes, usage_percent
},
disk: [{
read_speed_bytes, write_speed_bytes,
total_bytes, free_bytes, usage_percent
}],
host: { os, platform, kernel_version },
errors: [{ metric[], err }],
capture: { version, mode },
net: [{ name, bytes_sent, bytes_recv, ... }]
TTL: Auto-deletes after 30 days Indexes: monitorId, type, status, updatedAt (optimized for queries)
3. DATABASE SCHEMA
Core Models
Monitor Model
File: /server/src/db/v1/models/Monitor.js (208 lines)
{
userId: ObjectId (immutable, required),
teamId: ObjectId (immutable, required),
name: String (required),
description: String,
type: String (enum: http|ping|pagespeed|hardware|docker|port|game),
url: String (required) // container name/ID for docker
port: Number,
interval: Number (ms, default: 60000),
isActive: Boolean (default: true),
status: Boolean, // Current up/down
statusWindow: [Boolean], // Last N checks
statusWindowSize: Number (default: 5),
statusWindowThreshold: Number (default: 60),
// Hardware/Docker thresholds
thresholds: {
usage_cpu: Number (0-1),
usage_memory: Number (0-1),
usage_disk: Number (0-1),
usage_temperature: Number
},
// Notification thresholds
alertThreshold: Number (default: 5),
cpuAlertThreshold, memoryAlertThreshold, diskAlertThreshold, tempAlertThreshold,
// Relationships
notifications: [ObjectId], // refs to Notification model
// Advanced
secret: String, // For Capture API auth
ignoreTlsErrors: Boolean,
jsonPath: String,
expectedValue: String,
matchMethod: String (equal|include|regex),
gameId: String,
group: String (max 50 chars),
// Computed
uptimePercentage: Number,
timestamps: true // createdAt, updatedAt
}
// Indexes
MonitorSchema.index({ teamId: 1, type: 1 });
// Pre-hooks
pre("findOneAndDelete"): Deletes checks, stats, removes from status pages
pre("deleteMany"): Cascade deletes
pre("save"): Syncs alertThresholds
pre("findOneAndUpdate"): Updates thresholds
Check Model
File: /server/src/db/v1/models/Check.js
{
monitorId: ObjectId (ref: Monitor, immutable, indexed),
teamId: ObjectId (ref: Team, immutable, indexed),
type: String (enum: http|ping|pagespeed|hardware|docker|port|game, indexed),
status: Boolean (indexed),
responseTime: Number,
timings: Object,
statusCode: Number,
message: String,
// Acknowledgment
ack: Boolean (default: false),
ackAt: Date,
// Hardware fields (see above)
cpu, memory, disk[], host, errors[], capture, net[]
// PageSpeed only
accessibility, bestPractices, seo, performance, audits,
// Expiry
expiry: Date (TTL index: 30 days),
timestamps: true
}
// Indexes
CheckSchema.index({ updatedAt: 1 });
CheckSchema.index({ monitorId: 1, updatedAt: 1 });
CheckSchema.index({ monitorId: 1, updatedAt: -1 });
CheckSchema.index({ teamId: 1, updatedAt: -1 });
MonitorStats Model
File: /server/src/db/v1/models/MonitorStats.js
{
monitorId: ObjectId (ref: Monitor, immutable, indexed),
avgResponseTime: Number,
totalChecks: Number,
totalUpChecks: Number,
totalDownChecks: Number,
uptimePercentage: Number,
lastCheckTimestamp: Number,
lastResponseTime: Number,
timeOfLastFailure: Number,
timestamps: true
}
Database Access Layer
Location: /server/src/db/v1/modules/
MonitorModule.js(593 lines) - Monitor CRUD + aggregationsCheckModule.js- Check recordingMonitorModuleQueries.js- MongoDB aggregation pipelines
Key Methods:
// Creation
Monitor.createMonitor({ body, teamId, userId })
Monitor.createBulkMonitors(monitors)
// Retrieval
Monitor.getMonitorById(id)
Monitor.getMonitorsByTeamId()
Monitor.getMonitorStatsById()
Monitor.getHardwareDetailsById()
// Updates
Monitor.updateMonitor(id, updateData)
// Deletions
Monitor.deleteMonitor(id)
4. API PATTERNS
REST Endpoint Structure
Base: /api/v1/
Monitor Routes
File: /server/src/routes/v1/monitorRoute.js
GET /monitors getAllMonitors
POST /monitors createMonitor
DELETE /monitors deleteAllMonitors (superadmin)
GET /monitors/:monitorId getMonitorById
PUT /monitors/:monitorId editMonitor (admin)
DELETE /monitors/:monitorId deleteMonitor (admin)
GET /monitors/team getMonitorsByTeamId
GET /monitors/team/with-checks getMonitorsWithChecksByTeamId
GET /monitors/team/summary getMonitorsSummaryByTeamId
GET /monitors/team/groups getGroupsByTeamId
GET /monitors/stats/:monitorId getMonitorStatsById
GET /monitors/uptime/details/:monitorId getUptimeDetailsById
GET /monitors/hardware/details/:monitorId getHardwareDetailsById
POST /monitors/pause/:monitorId pauseMonitor (admin)
POST /monitors/demo addDemoMonitors
POST /monitors/bulk createBulkMonitors (CSV upload)
POST /monitors/test-email sendTestEmail
GET /monitors/games getAllGames
GET /monitors/certificate/:monitorId fetchCertificate
Check Routes
File: /server/src/routes/v1/checkRoute.js
GET /checks/:monitorId getChecksByMonitorId
GET /checks/team/:teamId getChecksByTeamId
GET /checks/:monitorId/:checkId getCheckById
PUT /checks/:checkId updateCheck (ack)
Request/Response Pattern
Create Monitor Request:
POST /api/v1/monitors
Authorization: Bearer <JWT>
Content-Type: application/json
{
name: "My Docker Container",
description: "Monitors app container",
type: "docker",
url: "my-app-container", // Container name
interval: 60000, // 1 minute
isActive: true,
secret: "api-key-for-capture", // If using hardware monitoring
notifications: ["notif-id-1"],
thresholds: {
usage_cpu: 0.8, // 80%
usage_memory: 0.9, // 90%
usage_disk: 0.95
},
alertThreshold: 5, // Consecutive failures
statusWindowSize: 5, // Last 5 checks
statusWindowThreshold: 60 // % threshold
}
Response 200:
{
data: {
_id: "monitor-id",
name: "My Docker Container",
type: "docker",
status: true,
interval: 60000,
...
},
msg: "Monitor created successfully"
}
Edit Monitor Request:
PUT /api/v1/monitors/:monitorId
{
name: "Updated Name",
interval: 120000,
thresholds: { usage_cpu: 0.85 },
// Partial updates allowed
}
Authentication & Authorization
JWT Middleware: /server/src/middleware/v1/verifyJWT.js
- Header:
Authorization: Bearer <token> - Validates signature using
jwtSecretfrom AppSettings - Extracts user info:
req.user = { userId, teamId, role, ... }
Role-Based Access:
// isAllowed middleware checks req.user.role
router.post("/monitors", isAllowed(["admin", "superadmin"]), createMonitor);
router.delete("/monitors/:monitorId", isAllowed(["admin", "superadmin"]), deleteMonitor);
Validation
File: /server/src/validation/joi.js
const createMonitorBodyValidation = joi.object({
name: joi.string().required(),
description: joi.string().required(),
type: joi.string().required(),
url: joi.string().required(),
interval: joi.number(),
port: joi.number(),
thresholds: joi.object().keys({
usage_cpu: joi.number(),
usage_memory: joi.number(),
usage_disk: joi.number(),
usage_temperature: joi.number(),
}),
notifications: joi.array().items(joi.string()),
secret: joi.string(),
// ... more fields
});
5. POLLING/JOBS IMPLEMENTATION
Job Queue Architecture
V1: SuperSimpleScheduler (Production)
Files:
/server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js/server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js
Job Lifecycle:
- Initialization (on server startup):
// Load all monitors from DB
const monitors = await db.monitorModule.getAllMonitors();
for (const monitor of monitors) {
// Add job with random offset (0-100ms)
this.addJob(monitor._id, monitor);
}
// Register job template
scheduler.addTemplate("monitor-job", this.helper.getMonitorJob());
- Job Template (executed per interval):
getMonitorJob = () => {
return async (monitor) => {
// Check maintenance window
if (await this.isInMaintenanceWindow(monitorId, teamId)) {
return; // Skip
}
// Execute monitor check
const networkResponse = await this.networkService.requestStatus(monitor);
// Update monitor status
const { monitor: updated, statusChanged } =
await this.statusService.updateStatus(networkResponse);
// Send notifications if status changed
if (statusChanged) {
await this.notificationService.handleNotifications({
...networkResponse,
monitor: updated,
prevStatus,
statusChanged
});
}
};
};
- Job Control:
// Add job
addJob(monitorId, monitor) {
scheduler.addJob({
id: monitorId.toString(),
template: "monitor-job",
repeat: monitor.interval, // Milliseconds
active: monitor.isActive,
data: monitor.toObject()
});
}
// Pause/Resume
pauseJob(monitor) { scheduler.pauseJob(monitor._id); }
resumeJob(monitor) { scheduler.resumeJob(monitor._id); }
// Update interval
updateJob(monitor) {
scheduler.updateJob(monitor._id, {
repeat: monitor.interval,
data: monitor.toObject()
});
}
// Delete
deleteJob(monitor) { scheduler.removeJob(monitor._id); }
V2: BullMQ (TypeScript, Planned)
Files:
/server/src/service/v2/infrastructure/JobQueue.ts/server/src/service/v2/infrastructure/JobGenerator.ts
Key Differences:
- Uses Redis backing store
- TypeScript interfaces (type safety)
- More robust queue management
- Cleanup jobs for orphaned checks
// Cleanup job runs every 24 hours
scheduler.addJob({
id: "cleanup-orphaned-checks",
template: "cleanup-job",
repeat: 24 * 60 * 60 * 1000,
active: true
});
Monitor Execution Flow
Monitor Created/Updated
↓
MonitorService.createMonitor()
↓
jobQueue.addJob(monitor)
↓
Job scheduled at interval
↓
[Job Execution]
├─ Check maintenance window
├─ NetworkService.requestStatus(monitor)
│ └─ Routes to type handler (requestDocker, requestHttp, etc)
├─ Create Check record (database)
├─ StatusService.updateMonitorStatus()
│ └─ Updates Monitor.status field
├─ MonitorStatsService.updateStats()
├─ If status changed → NotificationService.handleNotifications()
└─ Job completes / reschedules for next interval
Status Update Logic
Location: /server/src/service/v1/infrastructure/statusService.js
async updateStatus(networkResponse) {
// networkResponse = { monitorId, type, status, code, message, responseTime }
// 1. Create Check record
const check = await Check.create({
monitorId, teamId, type, status,
responseTime, statusCode: code, message
});
// 2. Get previous status
const prevStatus = monitor.status;
// 3. Apply statusWindow logic (sliding window of checks)
monitor.statusWindow.push(status);
if (monitor.statusWindow.length > monitor.statusWindowSize) {
monitor.statusWindow.shift();
}
// 4. Determine if DOWN (majority of window is false)
const downCount = monitor.statusWindow.filter(s => !s).length;
const isDown = (downCount / monitor.statusWindowSize) >
(monitor.statusWindowThreshold / 100);
monitor.status = isDown ? false : true;
// 5. Return status change info
return {
monitor: await monitor.save(),
statusChanged: prevStatus !== monitor.status,
prevStatus
};
}
6. FRONTEND COMPONENTS
Monitor Management Pages
Infrastructure Monitors (Hardware/Docker)
Location: /client/src/Pages/v1/Infrastructure/
Infrastructure/
├── Create/
│ ├── index.jsx (Main form - 10K lines)
│ ├── Components/
│ │ ├── MonitorStatusHeader.jsx
│ │ ├── MonitorActionButtons.jsx
│ │ └── CustomAlertsSection.jsx
│ └── hooks/
│ ├── useInfrastructureMonitorForm.jsx
│ ├── useValidateInfrastructureForm.jsx
│ └── useInfrastructureSubmit.jsx
├── Details/
├── Monitors/
│ └── Components/
│ └── MonitorsTable.jsx
Form Structure (useInfrastructureMonitorForm hook)
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
url: "", // Container name/IP
name: "", // Display name
notifications: [], // Notification IDs
interval: 0.25, // Minutes (0.25 = 15s, 1 = 60s)
// Threshold toggles
cpu: false,
usage_cpu: "", // Percentage
memory: false,
usage_memory: "",
disk: false,
usage_disk: "",
temperature: false,
usage_temperature: "",
secret: "", // Capture API secret
statusWindowSize: 5,
statusWindowThreshold: 60
});
Frequency Options:
[
{ _id: 0.25, name: "15 Seconds" },
{ _id: 0.5, name: "30 Seconds" },
{ _id: 1, name: "1 Minute" },
{ _id: 2, name: "2 Minutes" },
{ _id: 5, name: "5 Minutes" },
{ _id: 10, name: "10 Minutes" }
]
Form Submission (useInfrastructureSubmit hook)
// Converts frontend form → backend model
const finalForm = {
url: `http${https ? "s" : ""}://` + infrastructureMonitor.url,
name: infrastructureMonitor.name || infrastructureMonitor.url,
interval: infrastructureMonitor.interval * 60000, // Convert to ms
type: "hardware", // Always "hardware" for infrastructure monitors
// Thresholds (convert % to decimal 0-1)
thresholds: {
...(cpu ? { usage_cpu: usage_cpu / 100 } : {}),
...(memory ? { usage_memory: usage_memory / 100 } : {}),
...(disk ? { usage_disk: usage_disk / 100 } : {}),
...(temperature ? { usage_temperature: usage_temperature / 100 } : {})
},
notifications: infrastructureMonitor.notifications
};
// API call
isCreate ?
await createMonitor({ monitor: finalForm, redirect: "/infrastructure" }) :
await updateMonitor({ monitor: finalForm, redirect: "/infrastructure" });
Monitor Display Components
Monitor Status Component
Location: /client/src/Components/v2/Monitors/MonitorStatus.tsx
Displays:
- Status indicator (up/down)
- Response time
- Last check time
- Incident badges
Monitoring Hooks
Location: /client/src/Hooks/v1/monitorHooks.js
// Fetch monitors
useFetchMonitorsByTeamId({ types, limit, page, ... })
useFetchMonitorsWithSummary({ types, monitorUpdateTrigger })
useFetchMonitorsWithChecks({ types, limit, ... })
// Fetch individual monitor
useFetchHardwareMonitorById({ monitorId, updateTrigger })
useFetchStatsByMonitorId({ monitorId, dateRange, ... })
// Manage monitors
useCreateMonitor() // POST /monitors
useUpdateMonitor() // PUT /monitors/:id
useDeleteMonitor() // DELETE /monitors/:id
usePauseMonitor() // POST /monitors/pause/:id
Network Service (API Client)
Location: /client/src/Utils/NetworkService.js (1157 lines)
// Constructor
constructor(store, dispatch, navigate) {
// Axios instance with:
// - Bearer token injection
// - Language header
// - 401 redirect to login
// - Network error handling
}
// Monitor endpoints
async createMonitor(config) {
return this.axiosInstance.post(`/monitors`, config.monitor);
}
async updateMonitor(config) {
return this.axiosInstance.put(`/monitors/${config.monitorId}`, config.monitor);
}
async getMonitorsByTeamId(config) {
// Query params: limit, types[], page, rowsPerPage, filter, field, order
return this.axiosInstance.get(`/monitors/team?...`);
}
async getHardwareDetailsByMonitorId(config) {
return this.axiosInstance.get(`/monitors/hardware/details/${config.monitorId}`);
}
async getStatsByMonitorId(config) {
// Query params: sortOrder, limit, dateRange, numToDisplay, normalize
return this.axiosInstance.get(`/monitors/stats/${config.monitorId}?...`);
}
7. AUTHENTICATION & API KEYS
User Authentication (JWT)
Registration/Login:
// POST /auth/register
{
firstName: "John",
lastName: "Doe",
email: "john@example.com",
password: "SecurePass123!"
}
Response:
{
user: { _id, email, role, teamId, ... },
token: "eyJhbGciOiJIUzI1NiIs..." // JWT
}
Token Storage: Redux store (Features/Auth/authSlice)
Token Injection: Automatic by NetworkService
config.headers.Authorization = `Bearer ${authToken}`;
Monitor-Specific Authentication
For Hardware/Docker Monitors via Capture API
Monitors can have a secret field for authenticating requests to the Capture API:
{
type: "hardware",
url: "http://192.168.1.100:3000", // Capture endpoint
secret: "api-key-12345", // Passed to Capture API
thresholds: { ... }
}
Implementation: The secret is stored in the Monitor model and could be:
- Sent as HTTP header:
Authorization: Bearer <secret> - Sent as query param:
?secret=<secret> - Sent in request body for POST requests
8. CONFIGURATION & USER SETTINGS
Global Settings
Model: /server/src/db/v1/models/AppSettings.js
{
jwtSecret: String, // For signing JWTs
sslCertificate: String, // SSL cert content
smtpConfig: Object, // Email settings
globalThresholds: { // Default thresholds
cpu: Number,
memory: Number,
disk: Number,
temperature: Number
},
siteTitle: String,
defaultLanguage: String,
maintenanceMode: Boolean
}
Fetching Settings:
// Frontend
useFetchGlobalSettings()
→ NetworkService.getGlobalSettings()
→ GET /settings
// Backend
SettingsService.loadSettings()
→ Loads from AppSettings collection
Monitor Configuration UI Flow
-
Create Page:
/infrastructure/create- Fetch global settings for default thresholds
- Form includes:
- Monitor name
- URL/Container name
- Interval (dropdown)
- CPU/Memory/Disk/Temp thresholds (checkboxes + inputs)
- Notification channels (multi-select)
- Secret (if using Capture API)
-
Edit Page:
/infrastructure/configure/:monitorId- Load existing monitor data
- Update form fields
- Save changes with PUT request
-
Details Page:
/infrastructure/:monitorId- Display monitor stats
- Show uptime graph
- List recent checks
- Status history
Team-Based Isolation
Access Control:
// All queries filtered by teamId
await Monitor.find({ teamId: req.user.teamId });
// verifyTeamAccess middleware
await verifyTeamAccess(req.user.teamId, req.params.monitorId);
KEY PATTERNS FOR DOCKER MONITORING INTEGRATION
1. Adding Docker Monitor Type
Already supported! Located in:
Monitor.schematype enum ✓NetworkService.requestDocker()✓Check.schemawith type ✓
2. Docker-Specific Data Collection
Currently: Only status + response time To Add Detailed Metrics:
- Extend
Check.schemawith Docker stats fields - Modify
NetworkService.requestDocker()to callcontainer.stats() - Stream stats to
Check.dockerfield
3. Capture API Integration (Hardware Monitoring)
Flow:
Monitor with type="hardware" and url="http://capture-endpoint"
↓
NetworkService.requestHardware()
↓ (delegates to)
NetworkService.requestHttp()
↓
Expects JSON response: { cpu, memory, disk, net, ... }
↓
Check record stores full payload in hardware fields
4. Database Queries
Get hardware checks:
Check.find({
monitorId: id,
type: "hardware",
createdAt: { $gte: startDate, $lte: endDate }
})
.sort({ createdAt: -1 })
.limit(100)
5. UI Display
- Stats dashboard:
/infrastructure/:monitorId - Uptime details:
/monitor/uptime/details/:monitorId - Hardware details:
/monitor/hardware/details/:monitorId
SERVICE ARCHITECTURE
Service Registry Pattern
Location: /server/src/service/v1/system/serviceRegistry.js
// Singleton pattern
ServiceRegistry.set(serviceName, serviceInstance);
const service = ServiceRegistry.get(serviceName);
Service Dependencies
Initialization: /server/src/config/services.js
// Infrastructure services
new NetworkService({
axios, got, https, jmespath, GameDig, ping,
logger, http, Docker, // ← Docker client injected
net, stringService, settingsService
})
// Business services
new MonitorService({
db, settingsService, jobQueue,
stringService, emailService, logger
})
KEY FILES SUMMARY
| Component | File | Lines | Purpose |
|---|---|---|---|
| Monitor Model | server/src/db/v1/models/Monitor.js |
209 | Schema, hooks |
| Check Model | server/src/db/v1/models/Check.js |
177 | Check records, TTL |
| NetworkService | server/src/service/v1/infrastructure/networkService.js |
580 | Type handlers |
| MonitorService | server/src/service/v1/business/monitorService.js |
277 | CRUD, validation |
| MonitorModule | server/src/db/v1/modules/monitorModule.js |
593 | DB queries |
| JobQueue | server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js |
177 | Job scheduling |
| MonitorController | server/src/controllers/v1/monitorController.js |
475 | HTTP handlers |
| MonitorRoute | server/src/routes/v1/monitorRoute.js |
61 | Endpoint definitions |
| Frontend Hooks | client/src/Hooks/v1/monitorHooks.js |
500+ | Data fetching |
| NetworkService (FE) | client/src/Utils/NetworkService.js |
1157 | API client |
| Form Hook | client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx |
97 | Form state |
DEPLOYMENT & DOCKER INTEGRATION
Docker-Compose Setup
Files: /docker/dev/docker-compose.yaml, /docker/prod/docker-compose.yaml
Volumes for Docker Monitoring:
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Required for Dockerode
Environment Variables
Backend (.env):
MONGODB_URI=mongodb://mongo:27017/checkmate
JWT_SECRET=your-secret-key
NODE_ENV=production|development
PORT=5000
Frontend (.env):
VITE_APP_API_BASE_URL=http://localhost:5000/api/v1