From eaa935cba06ec78b5bcdf43ac56f378f4ab7fe84 Mon Sep 17 00:00:00 2001 From: Matt Visnovsky Date: Thu, 6 Jun 2024 10:09:35 -0600 Subject: [PATCH] Also return result of the evaluation -Maximum compatibility with @chakflying's existing json-query monitor code. --- server/model/monitor.js | 6 +++--- server/monitor-types/snmp.js | 8 ++++---- src/util.js | 7 +++++-- src/util.ts | 35 +++++++++++++++++++++-------------- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 85db89222..bd155128f 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -609,13 +609,13 @@ class Monitor extends BeanModel { } } - const result = await evaluateJsonQuery(data, this.jsonPath, this.jsonPathOperator, this.expectedValue); + const { status, evaluation } = await evaluateJsonQuery(data, this.jsonPath, this.jsonPathOperator, this.expectedValue); - if (result) { + if (status) { bean.msg += ", expected value is found"; bean.status = UP; } else { - throw new Error(`${bean.msg}, but value is not equal to expected value, value was: [${result}]`); + throw new Error(`${bean.msg}, but value is not equal to expected value, value was: [${evaluation}]`); } } diff --git a/server/monitor-types/snmp.js b/server/monitor-types/snmp.js index 1cad575d8..f3f67bc46 100644 --- a/server/monitor-types/snmp.js +++ b/server/monitor-types/snmp.js @@ -44,12 +44,12 @@ class SNMPMonitorType extends MonitorType { // We restrict querying to one OID per monitor, therefore `varbinds[0]` will always contain the value we're interested in. const value = varbinds[0].value; - const result = await evaluateJsonQuery(value, monitor.jsonPath, monitor.jsonPathOperator, monitor.expectedValue); + const { status, evaluation } = await evaluateJsonQuery(value, monitor.jsonPath, monitor.jsonPathOperator, monitor.expectedValue); - heartbeat.status = result ? UP : DOWN; - heartbeat.msg = `SNMP value ${result ? "passes" : "does not pass"} `; + heartbeat.status = status ? UP : DOWN; + heartbeat.msg = `SNMP value ${status ? "passes" : "does not pass"} `; heartbeat.msg += (monitor.jsonPathOperator === "custom") - ? `custom query. Query result: ${result}. Expected Value: ${monitor.expectedValue}.` + ? `custom query. Query result: ${evaluation}. Expected Value: ${monitor.expectedValue}.` : `comparison: ${value.toString()} ${monitor.jsonPathOperator} ${monitor.expectedValue}.`; } catch (err) { diff --git a/src/util.js b/src/util.js index 747747519..5340ff7c5 100644 --- a/src/util.js +++ b/src/util.js @@ -440,9 +440,12 @@ async function evaluateJsonQuery(data, jsonPath, jsonPathOperator, expectedValue if (evaluation === undefined) { throw new Error("Query evaluation returned undefined. Check your query syntax and the structure of the response data."); } - const result = (jsonPathOperator === "custom") + const status = (jsonPathOperator === "custom") ? evaluation.toString() === expected.toString() : evaluation; - return result; + return { + status, + evaluation + }; } exports.evaluateJsonQuery = evaluateJsonQuery; diff --git a/src/util.ts b/src/util.ts index 094a59f80..5af0088e4 100644 --- a/src/util.ts +++ b/src/util.ts @@ -651,20 +651,18 @@ export function intHash(str : string, length = 10) : number { * @param jsonPath The JSON path or custom JSON query expression. * @param jsonPathOperator The operator to use for comparison. * @param expectedValue The expected value to compare against. - * @returns The result of the evaluation. + * @returns An object containing the status and the evaluation result. * @throws Error if the evaluation returns undefined. */ -export async function evaluateJsonQuery(data: any, jsonPath: string, jsonPathOperator: string, expectedValue: any): Promise { - +export async function evaluateJsonQuery(data: any, jsonPath: string, jsonPathOperator: string, expectedValue: any): Promise<{ status: boolean; evaluation: any }> { // Check if inputs are numeric. If not, re-parse as strings. This ensures comparisons are handled correctly. const expected = isNaN(expectedValue) ? expectedValue.toString() : parseFloat(expectedValue); - let response = isNaN(data) ? data.toString() : parseFloat(data); + let response: any; try { - // Attempt to parse data as JSON - response = JSON.parse(response); - } catch (_) { - // Failed to parse as JSON, continue with the original value + response = JSON.parse(data); + } catch { + response = typeof data === "number" || typeof data === "object" ? data : data.toString(); } let jsonQueryExpression; @@ -690,18 +688,27 @@ export async function evaluateJsonQuery(data: any, jsonPath: string, jsonPathOpe // Evaluate the JSON Query Expression const expression = jsonata(jsonQueryExpression); - const evaluation = await expression.evaluate({ - value: response, - control: expected - }); + + let evaluation; + if (jsonPathOperator === "custom") { + evaluation = await expression.evaluate(response); + } else { + evaluation = await expression.evaluate({ + value: response, + control: expectedValue + }); + } if (evaluation === undefined) { throw new Error("Query evaluation returned undefined. Check your query syntax and the structure of the response data."); } - const result = (jsonPathOperator === "custom") + const status = (jsonPathOperator === "custom") ? evaluation.toString() === expected.toString() : evaluation; - return result; + return { + status, + evaluation + }; }