mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-23 14:54:05 +00:00
Add support for custom mongodb commands (#4445)
Co-authored-by: Sebastian Lang <sebastian.lang@damovo.com> Co-authored-by: Frank Elsinga <frank@elsinga.de>
This commit is contained in:
parent
e856cb6007
commit
a3ac954140
6 changed files with 96 additions and 29 deletions
|
@ -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();
|
||||
|
||||
|
|
65
server/monitor-types/mongodb.js
Normal file
65
server/monitor-types/mongodb.js
Normal file
|
@ -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,
|
||||
};
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -434,6 +434,32 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<!-- MongoDB -->
|
||||
<template v-if="monitor.type === 'mongodb'">
|
||||
<div class="my-3">
|
||||
<label for="mongodbCommand" class="form-label">{{ $t("Command") }}</label>
|
||||
<textarea id="mongodbCommand" v-model="monitor.databaseQuery" class="form-control" :placeholder="$t('Example:', [ '{ "ping": 1 }' ])"></textarea>
|
||||
<i18n-t tag="div" class="form-text" keypath="mongodbCommandDescription">
|
||||
<template #documentation>
|
||||
<a href="https://www.mongodb.com/docs/manual/reference/command/">{{ $t('documentationOf', ['MongoDB']) }}</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div class="my-3">
|
||||
<label for="jsonPath" class="form-label">{{ $t("Json Query") }}</label>
|
||||
<input id="jsonPath" v-model="monitor.jsonPath" type="text" class="form-control">
|
||||
|
||||
<i18n-t tag="div" class="form-text" keypath="jsonQueryDescription">
|
||||
<a href="https://jsonata.org/">jsonata.org</a>
|
||||
<a href="https://try.jsonata.org/">{{ $t('here') }}</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div class="my-3">
|
||||
<label for="expectedValue" class="form-label">{{ $t("Expected Value") }}</label>
|
||||
<input id="expectedValue" v-model="monitor.expectedValue" type="text" class="form-control">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Interval -->
|
||||
<div class="my-3">
|
||||
<label for="interval" class="form-label">{{ $t("Heartbeat Interval") }} ({{ $t("checkEverySecond", [ monitor.interval ]) }})</label>
|
||||
|
|
Loading…
Reference in a new issue