How to Create a Custom Monitor Type Plugin for Uptime Kuma
Yes, you can create custom monitor type plugins for Uptime Kuma by extending the MonitorType base class, implementing the required check method, and registering your implementation in UptimeKumaServer.monitorTypeList located in server/uptime-kuma-server.js.
Uptime Kuma is an open-source monitoring tool that exposes a class-based extension system for adding new monitoring capabilities. Whether you need to query a proprietary API or implement a specialized health check, you can build a custom monitor type that integrates natively with the existing UI and heartbeat engine without modifying core files beyond the registration step.
Understanding the Monitor Type Architecture
Uptime Kuma’s monitoring engine relies on a registry pattern that maps string identifiers to instantiated monitor classes. The architecture consists of three primary layers:
MonitorTypebase class (server/monitor-types/monitor-type.js): Defines the contract for all monitor types, including the abstractcheckmethod and UI metadata properties likename,type, anddescription.UptimeKumaServer.monitorTypeList(server/uptime-kuma-server.js): A global registry object that stores instantiated monitor types. The server constructor populates this list at startup.- Real-time UI synchronization (
server/client.js): ThesendMonitorTypeListfunction serializes the registry and emits it to connected clients via WebSocket, allowing the frontend (src/mixins/socket.js) to dynamically populate the "Add Monitor" dropdown without requiring static frontend builds.
When a heartbeat cycle executes, the server retrieves the monitor’s type string from the database, looks up the corresponding class in monitorTypeList, and invokes the check method with the monitor record and a fresh heartbeat object.
Step-by-Step: Creating a Custom Monitor Plugin
Step 1: Extend the MonitorType Base Class
Create a new file under server/monitor-types/ that imports the base class and status constants. Every custom monitor must export a class that extends MonitorType.
// server/monitor-types/custom-api.js
const { MonitorType } = require("./monitor-type");
const { UP, DOWN } = require("../../src/util");
const axios = require("axios");
class CustomApiMonitor extends MonitorType {
name = "Custom API Check";
type = "custom-api";
description = "Monitor a custom REST endpoint with Bearer token authentication.";
supportsConditions = true;
conditionVariables = [
{ name: "responseTime", type: "number", label: "Response Time (ms)" }
];
allowCustomStatus = false;
}
module.exports = { CustomApiMonitor };
Step 2: Implement the Check Method
The check method is the only required override. It receives two arguments: the monitor object (containing database fields like url and interval) and the heartbeat object (which you populate with status, message, and timing data).
async check(monitor, heartbeat) {
const start = Date.now();
try {
const response = await axios.get(monitor.url, {
headers: { "Authorization": `Bearer ${monitor.apiToken}` },
timeout: monitor.timeout || 15000
});
const duration = Date.now() - start;
if (response.status === 200) {
heartbeat.status = UP;
heartbeat.msg = "Service healthy";
heartbeat.time = duration;
// Expose variables for conditions if supportsConditions is true
heartbeat.responseTime = duration;
} else {
throw new Error(`Unexpected status code: ${response.status}`);
}
} catch (error) {
heartbeat.status = DOWN;
heartbeat.msg = error.message || "Connection failed";
}
}
Key implementation details:
- Set
heartbeat.statustoUP,DOWN, orPENDING(imported fromsrc/util.js). - Set
heartbeat.timeto record response duration in milliseconds. - If
allowCustomStatusisfalse(default), the framework expectsUPfor success; any thrown error orDOWNstatus triggers a failure. - Throwing an exception automatically results in a
DOWNstatus if unhandled.
Step 3: Register Your Monitor Type
Open server/uptime-kuma-server.js and locate the constructor where monitorTypeList is populated. Import your class and instantiate it:
const { CustomApiMonitor } = require("./monitor-types/custom-api");
// Inside the UptimeKumaServer constructor, after existing registrations:
UptimeKumaServer.monitorTypeList["custom-api"] = new CustomApiMonitor();
The string key ("custom-api") must match the type property defined in your class. Once registered, the server automatically includes your monitor in the list sent to clients via client.sendMonitorTypeList.
Step 4: Configure UI Behavior
Control how your monitor appears and behaves in the dashboard by setting these boolean and array properties:
supportsConditions: Set totrueif you want your monitor to appear in conditional logic (e.g., "alert when response time > 500ms").conditionVariables: An array of objects defining variables available for conditions. Each object requiresname,type("number"or"string"), andlabel.allowCustomStatus: Set totrueonly if your monitor sets non-standard status strings beyondUP/DOWN/PENDING.
If supportsConditions is false, the UI displays only standard fields (name, URL, interval) and omits condition configuration panels.
Complete Working Example: HTTP Status Monitor
Here is a production-ready example that monitors a JSON endpoint and validates the response structure:
// server/monitor-types/json-validator.js
const { MonitorType } = require("./monitor-type");
const { UP, DOWN } = require("../../src/util");
const axios = require("axios");
class JsonValidatorMonitor extends MonitorType {
name = "JSON Validator";
type = "json-validator";
description = "Verify that a JSON endpoint returns expected schema fields.";
supportsConditions = false;
conditionVariables = [];
allowCustomStatus = false;
async check(monitor, heartbeat) {
const startTime = Date.now();
try {
const res = await axios.get(monitor.url, {
timeout: monitor.timeout || 10000,
validateStatus: () => true // Handle status codes manually
});
heartbeat.time = Date.now() - startTime;
if (res.status !== 200) {
throw new Error(`HTTP ${res.status}`);
}
// Validate required JSON field exists
if (!res.data || !res.data.status) {
throw new Error("Missing 'status' field in JSON response");
}
if (res.data.status === "healthy") {
heartbeat.status = UP;
heartbeat.msg = "Schema valid and status healthy";
} else {
heartbeat.status = DOWN;
heartbeat.msg = `Service reports status: ${res.data.status}`;
}
} catch (err) {
heartbeat.status = DOWN;
heartbeat.msg = err.message;
}
}
}
module.exports = { JsonValidatorMonitor };
Register this in server/uptime-kuma-server.js:
const { JsonValidatorMonitor } = require("./monitor-types/json-validator");
UptimeKumaServer.monitorTypeList["json-validator"] = new JsonValidatorMonitor();
After restarting the Uptime Kuma server, "JSON Validator" appears immediately in the monitor type dropdown.
Key Files for Plugin Development
server/monitor-types/monitor-type.js: The abstract base class defining thecheckmethod signature and UI metadata properties.server/monitor-types/*.js(e.g.,tcp.js,dns.js): Reference implementations showing database interaction and heartbeat population patterns.server/uptime-kuma-server.js: Contains themonitorTypeListregistry where you must instantiate and register your plugin.server/client.js: ImplementssendMonitorTypeList, which serializes your monitor’s metadata for the frontend.src/mixins/socket.js: Frontend handler that receives the monitor type list and updates the UI state.src/util.js: Exports status constants (UP,DOWN,PENDING) used to set heartbeat results.
Summary
- Extend
MonitorType: Create a new file inserver/monitor-types/that inherits from the base class and implements theasync check(monitor, heartbeat)method. - Register in
UptimeKumaServer.monitorTypeList: Import and instantiate your class inserver/uptime-kuma-server.jsusing a unique string key. - Set UI flags: Configure
supportsConditions,conditionVariables, andallowCustomStatusto control frontend behavior without modifying React components. - Return standard statuses: Import
UPandDOWNfromsrc/util.jsand assign them toheartbeat.status, settingheartbeat.timefor latency tracking. - Automatic UI integration: The frontend receives new monitor types via WebSocket at runtime, so your custom type appears in the "Add Monitor" dialog immediately after server restart.
Frequently Asked Questions
Do I need to modify the frontend code to add a custom monitor type?
No. Uptime Kuma’s frontend receives the monitor type list dynamically through the WebSocket connection handled in src/mixins/socket.js. As long as you register your class in UptimeKumaServer.monitorTypeList and set the appropriate metadata properties (name, type, description), the "Add Monitor" dropdown will automatically include your custom type. You only need frontend modifications if you require custom input fields beyond the standard URL, interval, and notification options.
What methods are absolutely required when creating a monitor type?
You must implement only the check method. This async method accepts monitor (the database record) and heartbeat (the response object) as arguments. You must populate heartbeat.status with either UP or DOWN (constants from src/util.js), and optionally set heartbeat.msg for the status message and heartbeat.time for response duration. The base class handles all other lifecycle management.
How do I add custom condition variables for alerting logic?
Set supportsConditions = true in your class definition, then populate the conditionVariables array with objects containing name, type ("number" or "string"), and label. Inside your check method, assign values to the heartbeat object using these variable names (e.g., heartbeat.responseTime = duration). The UI will then allow users to create rules like "alert when responseTime > 500" without additional frontend code.
Can I use third-party npm packages in my custom monitor?
Yes. Since custom monitor types are standard Node.js modules loaded by server/uptime-kuma-server.js, you can require() any package available in the project’s node_modules or install new dependencies. Ensure you handle exceptions properly within your check method to prevent unhandled promise rejections, as errors thrown will result in a DOWN status unless caught and handled manually.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →