diff --git a/server/model/monitor.js b/server/model/monitor.js
index 65bfb420c..69b685c77 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -5,7 +5,7 @@ const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MI
SQL_DATETIME_FORMAT
} = require("../../src/util");
const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery,
- redisPingAsync, mongodbPing, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal
+ redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal
} = require("../util-server");
const { R } = require("redbean-node");
const { BeanModel } = require("redbean-node/dist/bean-model");
@@ -822,15 +822,6 @@ class Monitor extends BeanModel {
bean.msg = await mysqlQuery(this.databaseConnectionString, this.databaseQuery || "SELECT 1", mysqlPassword);
bean.status = UP;
bean.ping = dayjs().valueOf() - startTime;
- } else if (this.type === "mongodb") {
- let startTime = dayjs().valueOf();
-
- await mongodbPing(this.databaseConnectionString);
-
- bean.msg = "";
- bean.status = UP;
- bean.ping = dayjs().valueOf() - startTime;
-
} else if (this.type === "radius") {
let startTime = dayjs().valueOf();
diff --git a/server/monitor-types/mongodb.js b/server/monitor-types/mongodb.js
new file mode 100644
index 000000000..fd3a1dc98
--- /dev/null
+++ b/server/monitor-types/mongodb.js
@@ -0,0 +1,65 @@
+const { MonitorType } = require("./monitor-type");
+const { UP } = require("../../src/util");
+const { MongoClient } = require("mongodb");
+const jsonata = require("jsonata");
+
+class MongodbMonitorType extends MonitorType {
+
+ name = "mongodb";
+
+ /**
+ * @inheritdoc
+ */
+ async check(monitor, heartbeat, _server) {
+ let command = { "ping": 1 };
+ if (monitor.databaseQuery) {
+ command = JSON.parse(monitor.databaseQuery);
+ }
+
+ let result = await this.runMongodbCommand(monitor.databaseConnectionString, command);
+
+ if (result["ok"] !== 1) {
+ throw new Error("MongoDB command failed");
+ } else {
+ heartbeat.msg = "Command executed successfully";
+ }
+
+ if (monitor.jsonPath) {
+ let expression = jsonata(monitor.jsonPath);
+ result = await expression.evaluate(result);
+ if (result) {
+ heartbeat.msg = "Command executed successfully and the jsonata expression produces a result.";
+ } else {
+ throw new Error("Queried value not found.");
+ }
+ }
+
+ if (monitor.expectedValue) {
+ if (result.toString() === monitor.expectedValue) {
+ heartbeat.msg = "Command executed successfully and expected value was found";
+ } else {
+ throw new Error("Query executed, but value is not equal to expected value, value was: [" + JSON.stringify(result) + "]");
+ }
+ }
+
+ heartbeat.status = UP;
+ }
+
+ /**
+ * Connect to and run MongoDB command on a MongoDB database
+ * @param {string} connectionString The database connection string
+ * @param {object} command MongoDB command to run on the database
+ * @returns {Promise<(string[] | object[] | object)>} Response from
+ * server
+ */
+ async runMongodbCommand(connectionString, command) {
+ let client = await MongoClient.connect(connectionString);
+ let result = await client.db().command(command);
+ await client.close();
+ return result;
+ }
+}
+
+module.exports = {
+ MongodbMonitorType,
+};
diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js
index bcf497b58..6ab5f6c26 100644
--- a/server/uptime-kuma-server.js
+++ b/server/uptime-kuma-server.js
@@ -113,6 +113,7 @@ class UptimeKumaServer {
UptimeKumaServer.monitorTypeList["tailscale-ping"] = new TailscalePing();
UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType();
UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType();
+ UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType();
// Allow all CORS origins (polling) in development
let cors = undefined;
@@ -516,3 +517,4 @@ const { RealBrowserMonitorType } = require("./monitor-types/real-browser-monitor
const { TailscalePing } = require("./monitor-types/tailscale-ping");
const { DnsMonitorType } = require("./monitor-types/dns");
const { MqttMonitorType } = require("./monitor-types/mqtt");
+const { MongodbMonitorType } = require("./monitor-types/mongodb");
diff --git a/server/util-server.js b/server/util-server.js
index 24d428694..d728b6c20 100644
--- a/server/util-server.js
+++ b/server/util-server.js
@@ -11,7 +11,6 @@ const mssql = require("mssql");
const { Client } = require("pg");
const postgresConParse = require("pg-connection-string").parse;
const mysql = require("mysql2");
-const { MongoClient } = require("mongodb");
const { NtlmClient } = require("axios-ntlm");
const { Settings } = require("./settings");
const grpc = require("@grpc/grpc-js");
@@ -437,24 +436,6 @@ exports.mysqlQuery = function (connectionString, query, password = undefined) {
});
};
-/**
- * Connect to and ping a MongoDB database
- * @param {string} connectionString The database connection string
- * @returns {Promise<(string[] | object[] | object)>} Response from
- * server
- */
-exports.mongodbPing = async function (connectionString) {
- let client = await MongoClient.connect(connectionString);
- let dbPing = await client.db().command({ ping: 1 });
- await client.close();
-
- if (dbPing["ok"] === 1) {
- return "UP";
- } else {
- throw Error("failed");
- }
-};
-
/**
* Query radius server
* @param {string} hostname Hostname of radius server
diff --git a/src/lang/en.json b/src/lang/en.json
index 2a3e6628c..aa597a5e3 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -902,6 +902,8 @@
"deleteRemoteBrowserMessage": "Are you sure want to delete this Remote Browser for all monitors?",
"GrafanaOncallUrl": "Grafana Oncall URL",
"Browser Screenshot": "Browser Screenshot",
+ "Command": "Command",
+ "mongodbCommandDescription": "Run a MongoDB command against the database. For information about the available commands check out the {documentation}",
"wayToGetSevenIOApiKey": "Visit the dashboard under app.seven.io > developer > api key > the green add button",
"senderSevenIO": "Sending number or name",
"receiverSevenIO": "Receiving number",
diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue
index e9f3ac832..38017778a 100644
--- a/src/pages/EditMonitor.vue
+++ b/src/pages/EditMonitor.vue
@@ -434,6 +434,32 @@
+
+
+