Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat: json-query monitor added #3253

Merged
merged 22 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e747b98
✨ feat: json-query monitor added
mhkarimi1383 Jun 12, 2023
a53d665
Merge branch 'louislam:master' into feat-add-json-query
mhkarimi1383 Jun 12, 2023
54b9b8f
🐛 fix: import warning error
mhkarimi1383 Jun 12, 2023
01dc5d7
🐛 fix: br tag and remove comment
mhkarimi1383 Jun 12, 2023
6d90890
🐛 fix: supporting compare string with other types
mhkarimi1383 Jun 12, 2023
09282e0
🐛 fix: switch to a better lib for json query
mhkarimi1383 Jun 12, 2023
6957dee
🐛 fix: better description on json query and using `v-html` in jsonQue…
mhkarimi1383 Jun 12, 2023
3e8f9f0
🐛 fix: result variable in error message
mhkarimi1383 Jun 12, 2023
51f9d3f
🐛 fix: typos in json query description
mhkarimi1383 Jun 13, 2023
be145da
Merge branch 'master' into feat-add-json-query
mhkarimi1383 Jun 26, 2023
3dc45c7
Merge branch 'master' into feat-add-json-query
mhkarimi1383 Jun 26, 2023
2bcc7e9
📝 docs: `HTTP(s) Json Query` added to monitor list in `README.md`
mhkarimi1383 Jun 26, 2023
5dfef1a
🐛 fix: needed white space in `README.md`
mhkarimi1383 Jun 27, 2023
55cbd6e
Merge branch 'master' into feat-add-json-query
mhkarimi1383 Jun 27, 2023
b8bcb6f
Nostr dm notifications (#3051)
zappityzap Jun 27, 2023
d51209a
Merge branch 'master' into feat-add-json-query
mhkarimi1383 Jun 27, 2023
161af1b
Drop nostr
louislam Jun 29, 2023
fafd976
Merge remote-tracking branch 'origin/master' into feat-add-json-query
louislam Jun 29, 2023
de53a8f
Merge branch 'master' into feat-add-json-query
mhkarimi1383 Jul 7, 2023
7f77bc7
Merge remote-tracking branch 'origin/master' into feat-add-json-query
louislam Jul 13, 2023
86fc3a7
Rebuild package-lock.json
louislam Jul 13, 2023
abce468
Lint
louislam Jul 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions db/patch-added-json-query.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;

ALTER TABLE monitor
ADD json_path TEXT;

ALTER TABLE monitor
ADD expected_value VARCHAR(255);

COMMIT;
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"https-proxy-agent": "~5.0.1",
"iconv-lite": "~0.6.3",
"jsesc": "~3.0.2",
"json-query": "^2.2.2",
"jsonwebtoken": "~9.0.0",
"jwt-decode": "~3.1.2",
"limiter": "~2.1.0",
Expand Down
1 change: 1 addition & 0 deletions server/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class Database {
"patch-monitor-tls.sql": true,
"patch-maintenance-cron.sql": true,
"patch-add-parent-monitor.sql": true,
"patch-added-json-query.sql": true
};

/**
Expand Down
27 changes: 24 additions & 3 deletions server/model/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const { CacheableDnsHttpAgent } = require("../cacheable-dns-http-agent");
const { DockerHost } = require("../docker");
const { UptimeCacheList } = require("../uptime-cache-list");
const Gamedig = require("gamedig");
const jsonQuery = require("json-query");

/**
* status:
Expand Down Expand Up @@ -117,7 +118,9 @@ class Monitor extends BeanModel {
radiusCalledStationId: this.radiusCalledStationId,
radiusCallingStationId: this.radiusCallingStationId,
game: this.game,
httpBodyEncoding: this.httpBodyEncoding
httpBodyEncoding: this.httpBodyEncoding,
jsonPath: this.jsonPath,
expectedValue: this.expectedValue,
};

if (includeSensitiveData) {
Expand Down Expand Up @@ -303,7 +306,7 @@ class Monitor extends BeanModel {
bean.msg = "Group empty";
}

} else if (this.type === "http" || this.type === "keyword") {
} else if (this.type === "http" || this.type === "keyword" || this.type === "json-query") {
// Do not do any queries/high loading things before the "bean.ping"
let startTime = dayjs().valueOf();

Expand Down Expand Up @@ -431,7 +434,7 @@ class Monitor extends BeanModel {

if (this.type === "http") {
bean.status = UP;
} else {
} else if (this.type === "keyword") {

let data = res.data;

Expand All @@ -451,6 +454,24 @@ class Monitor extends BeanModel {
throw new Error(bean.msg + ", but keyword is not in [" + data + "]");
}

} else if (this.type === "json-query") {
let data = res.data;

// convert data to object
if (typeof data === "string") {
data = JSON.parse(data);
}

let result = jsonQuery(this.jsonPath, {
data: data,
});

if (result.value.toString() === this.expectedValue) {
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.value + "]");
}
}

} else if (this.type === "port") {
Expand Down
2 changes: 1 addition & 1 deletion server/notification-providers/smtp.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class SMTP extends NotificationProvider {
if (monitorJSON !== null) {
monitorName = monitorJSON["name"];

if (monitorJSON["type"] === "http" || monitorJSON["type"] === "keyword") {
if (monitorJSON["type"] === "http" || monitorJSON["type"] === "keyword" || monitorJSON["type"] === "json-query") {
monitorHostnameOrURL = monitorJSON["url"];
} else {
monitorHostnameOrURL = monitorJSON["hostname"];
Expand Down
2 changes: 2 additions & 0 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,8 @@ let needSetup = false;
bean.radiusCallingStationId = monitor.radiusCallingStationId;
bean.radiusSecret = monitor.radiusSecret;
bean.httpBodyEncoding = monitor.httpBodyEncoding;
bean.expectedValue = monitor.expectedValue;
bean.jsonPath = monitor.jsonPath;

bean.validate();

Expand Down
2 changes: 1 addition & 1 deletion src/components/MonitorSettingDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export default {
// We must check if there are any elements in monitorList to
// prevent undefined errors if it hasn't been loaded yet
if (this.$parent.editMode && ignoreSendUrl && Object.keys(this.$root.monitorList).length) {
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword";
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword" || this.$root.monitorList[monitor.element.id].type === "json-query";
}
return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://" && !this.editMode;
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/PublicGroupList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export default {
// We must check if there are any elements in monitorList to
// prevent undefined errors if it hasn't been loaded yet
if (this.$parent.editMode && ignoreSendUrl && Object.keys(this.$root.monitorList).length) {
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword";
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword" || this.$root.monitorList[monitor.element.id].type === "json-query";
}
return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://" && !this.editMode;
},
Expand Down
3 changes: 3 additions & 0 deletions src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
"Ping": "Ping",
"Monitor Type": "Monitor Type",
"Keyword": "Keyword",
"Expected Value": "Expected Value",
"Json Query": "Json Query",
"Friendly Name": "Friendly Name",
"URL": "URL",
"Hostname": "Hostname",
Expand Down Expand Up @@ -514,6 +516,7 @@
"passwordNotMatchMsg": "The repeat password does not match.",
"notificationDescription": "Notifications must be assigned to a monitor to function.",
"keywordDescription": "Search keyword in plain HTML or JSON response. The search is case-sensitive.",
"jsonQueryDescription": "Do a json Query against the response and check for expected value.",
mhkarimi1383 marked this conversation as resolved.
Show resolved Hide resolved
"backupDescription": "You can backup all monitors and notifications into a JSON file.",
"backupDescription2": "Note: history and event data is not included.",
"backupDescription3": "Sensitive data such as notification tokens are included in the export file; please store export securely.",
Expand Down
10 changes: 8 additions & 2 deletions src/pages/Details.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@
<Tag v-for="tag in monitor.tags" :key="tag.id" :item="tag" :size="'sm'" />
</div>
<p class="url">
<a v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'mp-health' " :href="monitor.url" target="_blank" rel="noopener noreferrer">{{ filterPassword(monitor.url) }}</a>
<a v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'mp-health' " :href="monitor.url" target="_blank" rel="noopener noreferrer">{{ filterPassword(monitor.url) }}</a>
<span v-if="monitor.type === 'port'">TCP Port {{ monitor.hostname }}:{{ monitor.port }}</span>
<span v-if="monitor.type === 'ping'">Ping: {{ monitor.hostname }}</span>
<span v-if="monitor.type === 'keyword'">
<br>
<span>{{ $t("Keyword") }}:</span> <span class="keyword">{{ monitor.keyword }}</span>
</span>
<span v-if="monitor.type === 'json-query'">
<br>
<span>{{ $t("Json Query") }}:</span> <span class="keyword">{{ monitor.jsonPath }}</span>
<br>
<span>{{ $t("Expected Value") }}:</span> <span class="keyword">{{ monitor.expectedValue }}</span>
</span>
<span v-if="monitor.type === 'dns'">[{{ monitor.dns_resolve_type }}] {{ monitor.hostname }}
<br>
<span>{{ $t("Last Result") }}:</span> <span class="keyword">{{ monitor.dns_last_result }}</span>
Expand Down Expand Up @@ -411,7 +417,7 @@ export default {
translationPrefix = "Avg. ";
}

if (this.monitor.type === "http" || this.monitor.type === "keyword") {
if (this.monitor.type === "http" || this.monitor.type === "keyword" || this.monitor.type === "json-query") {
return this.$t(translationPrefix + "Response");
}

Expand Down
27 changes: 21 additions & 6 deletions src/pages/EditMonitor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<option value="keyword">
HTTP(s) - {{ $t("Keyword") }}
</option>
<option value="json-query">
HTTP(s) - {{ $t("Json Query") }}
</option>
<option value="grpc-keyword">
gRPC(s) - {{ $t("Keyword") }}
</option>
Expand Down Expand Up @@ -102,7 +105,7 @@
</div>

<!-- URL -->
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'browser' " class="my-3">
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'browser' " class="my-3">
<label for="url" class="form-label">{{ $t("URL") }}</label>
<input id="url" v-model="monitor.url" type="url" class="form-control" pattern="https?://.+" required>
</div>
Expand Down Expand Up @@ -132,6 +135,18 @@
</div>
</div>

<!-- Json Query -->
<div v-if="monitor.type === 'json-query'" 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" required>
<div class="form-text">
{{ $t("jsonQueryDescription") }}
</div>

<label for="expectedValue" class="form-label">{{ $t("Expected Value") }}</label>
<input id="expectedValue" v-model="monitor.expectedValue" type="text" class="form-control" required>
</div>

<!-- Game -->
<!-- GameDig only -->
<div v-if="monitor.type === 'gamedig'" class="my-3">
Expand Down Expand Up @@ -361,7 +376,7 @@

<h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2>

<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' " class="my-3 form-check">
<input id="expiry-notification" v-model="monitor.expiryNotification" class="form-check-input" type="checkbox">
<label class="form-check-label" for="expiry-notification">
{{ $t("Certificate Expiry Notification") }}
Expand All @@ -370,7 +385,7 @@
</div>
</div>

<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' " class="my-3 form-check">
<input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value="">
<label class="form-check-label" for="ignore-tls">
{{ $t("ignoreTLSError") }}
Expand Down Expand Up @@ -462,7 +477,7 @@
</button>

<!-- Proxies -->
<div v-if="monitor.type === 'http' || monitor.type === 'keyword'">
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query'">
<h2 class="mt-5 mb-2">{{ $t("Proxy") }}</h2>
<p v-if="$root.proxyList.length === 0">
{{ $t("Not available, please setup.") }}
Expand Down Expand Up @@ -490,7 +505,7 @@
</div>

<!-- HTTP Options -->
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' ">
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' ">
<h2 class="mt-5 mb-2">{{ $t("HTTP Options") }}</h2>

<!-- Method -->
Expand Down Expand Up @@ -1108,7 +1123,7 @@ message HealthCheckResponse {
this.monitor.body = JSON.stringify(JSON.parse(this.monitor.body), null, 4);
}

if (this.monitor.type && this.monitor.type !== "http" && this.monitor.type !== "keyword") {
if (this.monitor.type && this.monitor.type !== "http" && (this.monitor.type !== "keyword" || this.monitor.type !== "json-query")) {
this.monitor.httpBodyEncoding = null;
}

Expand Down