diff --git a/db/knex_migrations/2024-03-25-0000-json-data-operators.js b/db/knex_migrations/2024-03-25-0000-json-data-operators.js
new file mode 100644
index 00000000..4cf0f808
--- /dev/null
+++ b/db/knex_migrations/2024-03-25-0000-json-data-operators.js
@@ -0,0 +1,22 @@
+exports.up = function (knex) {
+ return knex.schema
+ .alterTable("monitor", (table) => {
+ table.string("json_path_operator");
+ })
+ .then(() =>
+ knex("monitor")
+ .where({
+ type: "json-query"
+ })
+ .update({
+ "json_path_operator": "=="
+ })
+ );
+};
+
+exports.down = function (knex) {
+ return knex.schema
+ .alterTable("monitor", (table) => {
+ table.dropColumn("json_path_operator");
+ });
+};
diff --git a/db/knex_migrations/README.md b/db/knex_migrations/README.md
index d2b8470b..9d34dee8 100644
--- a/db/knex_migrations/README.md
+++ b/db/knex_migrations/README.md
@@ -38,12 +38,12 @@ exports.up = function(knex) {
table.increments('id');
table.decimal('price').notNullable();
table.string('name', 1000).notNullable();
- }).then(() => {
+ }).then(() =>
knex("products").insert([
{ price: 10, name: "Apple" },
{ price: 20, name: "Orange" },
]);
- });
+ );
};
exports.down = function(knex) {
diff --git a/server/model/monitor.js b/server/model/monitor.js
index 1667b83a..f74f73ed 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -153,6 +153,7 @@ class Monitor extends BeanModel {
gamedigGivenPortOnly: this.getGameDigGivenPortOnly(),
httpBodyEncoding: this.httpBodyEncoding,
jsonPath: this.jsonPath,
+ jsonPathOperator: this.jsonPathOperator,
expectedValue: this.expectedValue,
kafkaProducerTopic: this.kafkaProducerTopic,
kafkaProducerBrokers: JSON.parse(this.kafkaProducerBrokers),
@@ -607,7 +608,7 @@ class Monitor extends BeanModel {
let result = await expression.evaluate(data);
- if (result.toString() === this.expectedValue) {
+ if (this.isJsonPathMatching(result)) {
bean.msg += ", expected value is found";
bean.status = UP;
} else {
@@ -1615,6 +1616,25 @@ class Monitor extends BeanModel {
return oAuthAccessToken;
}
+ /**
+ * Evaluates the provided value with the expected value based on the defined operator. Fallback is the equals operator
+ * @param {any} value
+ * @returns {boolean} Is the JsonPath matching the expected value with the defined operator?
+ */
+ isJsonPathMatching(value) {
+ const operators = {
+ "==": (value) => value == this.expectedValue,
+ "!=": (value) => value != this.expectedValue,
+ "<": (value) => value < this.expectedValue,
+ "<=": (value) => value <= this.expectedValue,
+ ">": (value) => value > this.expectedValue,
+ ">=": (value) => value >= this.expectedValue,
+ };
+
+ const operator = operators[this.jsonPathOperator] ?? operators["=="];
+
+ return operator(value?.toString());
+ }
}
module.exports = Monitor;
diff --git a/server/monitor-types/mqtt.js b/server/monitor-types/mqtt.js
index 9b2db43d..fd9238d4 100644
--- a/server/monitor-types/mqtt.js
+++ b/server/monitor-types/mqtt.js
@@ -41,7 +41,7 @@ class MqttMonitorType extends MonitorType {
let result = await expression.evaluate(parsedMessage);
- if (result?.toString() === monitor.expectedValue) {
+ if (monitor.isJsonPathMatching(result)) {
heartbeat.msg = "Message received, expected value is found";
heartbeat.status = UP;
} else {
diff --git a/server/server.js b/server/server.js
index 753f88b8..60f9359e 100644
--- a/server/server.js
+++ b/server/server.js
@@ -818,8 +818,9 @@ let needSetup = false;
bean.radiusCallingStationId = monitor.radiusCallingStationId;
bean.radiusSecret = monitor.radiusSecret;
bean.httpBodyEncoding = monitor.httpBodyEncoding;
- bean.expectedValue = monitor.expectedValue;
bean.jsonPath = monitor.jsonPath;
+ bean.jsonPathOperator = monitor.jsonPathOperator;
+ bean.expectedValue = monitor.expectedValue;
bean.kafkaProducerTopic = monitor.kafkaProducerTopic;
bean.kafkaProducerBrokers = JSON.stringify(monitor.kafkaProducerBrokers);
bean.kafkaProducerAllowAutoTopicCreation = monitor.kafkaProducerAllowAutoTopicCreation;
diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json
index 0d233636..04bc9ad4 100644
--- a/src/lang/de-DE.json
+++ b/src/lang/de-DE.json
@@ -817,6 +817,13 @@
"filterActivePaused": "Pausiert",
"Expected Value": "Erwarteter Wert",
"Json Query": "Json-Abfrage",
+ "Json Query Operator": "Json-Abfrage Operator",
+ "Json Query Equals": "Wert muss gleich sein",
+ "Json Query Not Equals": "Wert muss unterschiedlich sein",
+ "Json Query Less Than": "Wert muss kleiner sein",
+ "Json Query Less Than Or Equals": "Wert muss kleiner oder gleich sein",
+ "Json Query Greater Than": "Wert muss größer sein",
+ "Json Query Greater Than Or Equals": "Wert muss größer oder gleich sein",
"jsonQueryDescription": "Führe eine JSON-Abfrage gegen die Antwort durch und prüfe den erwarteten Wert (der Rückgabewert wird zum Vergleich in eine Zeichenkette umgewandelt). Auf {0} findest du die Dokumentation zur Abfragesprache. {1} kannst du Abfragen üben.",
"tailscalePingWarning": "Um den Tailscale Ping Monitor nutzen zu können, musst du Uptime Kuma ohne Docker installieren und den Tailscale Client auf dem Server installieren.",
"Server URL should not contain the nfty topic": "Die Server-URL sollte das nfty-Thema nicht enthalten",
diff --git a/src/lang/en.json b/src/lang/en.json
index 11190a08..d3afb30c 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -60,6 +60,13 @@
"Invert Keyword": "Invert Keyword",
"Expected Value": "Expected Value",
"Json Query": "Json Query",
+ "Json Query Operator": "Json Query Operator",
+ "Json Query Equals": "value must be equal",
+ "Json Query Not Equals": "value must not be equal",
+ "Json Query Less Than": "value must be less",
+ "Json Query Less Than Or Equals": "value must be less or equal",
+ "Json Query Greater Than": "value must be greater",
+ "Json Query Greater Than Or Equals": "value must be greater or equal",
"Friendly Name": "Friendly Name",
"URL": "URL",
"Hostname": "Hostname",
diff --git a/src/pages/Details.vue b/src/pages/Details.vue
index 8582b82c..92c6d85e 100644
--- a/src/pages/Details.vue
+++ b/src/pages/Details.vue
@@ -29,6 +29,8 @@
{{ $t("Json Query") }}: {{ monitor.jsonPath }}
+ {{ $t("Json Query Operator") }}: {{ monitor.jsonPathOperator }}
+
{{ $t("Expected Value") }}: {{ monitor.expectedValue }}
[{{ monitor.dns_resolve_type }}] {{ monitor.hostname }}
diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue
index e9f3ac83..e4ab629a 100644
--- a/src/pages/EditMonitor.vue
+++ b/src/pages/EditMonitor.vue
@@ -179,6 +179,16 @@
+
+
+
@@ -375,6 +385,16 @@
+
+
+