From 10c81bbfd3d8cf0d396fff2ce4759fcf21bd6a70 Mon Sep 17 00:00:00 2001 From: filippolauria Date: Fri, 31 Jan 2025 13:51:47 +0100 Subject: [PATCH 01/17] Added new columns to monitor table for configuring advanced ping behavior: - ping_count: number of packets to send - ping_deadline: maximum total duration - ping_timeout: time to wait for each response - ping_numeric: output IP addresses instead of hostnames --- db/knex_init_db.js | 14 ++++++++++++++ .../patch-add-ping-advanced-options.sql | 7 +++++++ 2 files changed, 21 insertions(+) create mode 100644 db/old_migrations/patch-add-ping-advanced-options.sql diff --git a/db/knex_init_db.js b/db/knex_init_db.js index 46bff4bfa..c5a542e29 100644 --- a/db/knex_init_db.js +++ b/db/knex_init_db.js @@ -548,6 +548,20 @@ ALTER TABLE monitor table.double("timeout").defaultTo(0).notNullable(); }); + /* + patch-add-ping-advanced-options.sql + ALTER TABLE monitor ADD ping_count INTEGER default 1 not null; + ALTER TABLE monitor ADD ping_numeric BOOLEAN default true not null; + ALTER TABLE monitor ADD ping_deadline INTEGER default 10 not null; + ALTER TABLE monitor ADD ping_timeout INTEGER default 2 not null; + */ + await knex.schema.table("monitor", function (table) { + table.integer("ping_count").defaultTo(1).notNullable(); + table.boolean("ping_numeric").defaultTo(true).notNullable(); + table.integer("ping_deadline").defaultTo(10).notNullable(); + table.integer("ping_timeout").defaultTo(2).notNullable(); + }); + /* patch-add-gamedig-given-port.sql ALTER TABLE monitor diff --git a/db/old_migrations/patch-add-ping-advanced-options.sql b/db/old_migrations/patch-add-ping-advanced-options.sql new file mode 100644 index 000000000..9ce76b072 --- /dev/null +++ b/db/old_migrations/patch-add-ping-advanced-options.sql @@ -0,0 +1,7 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +BEGIN TRANSACTION; +ALTER TABLE monitor ADD ping_count INTEGER default 1 not null; +ALTER TABLE monitor ADD ping_numeric BOOLEAN default true not null; +ALTER TABLE monitor ADD ping_deadline INTEGER default 10 not null; +ALTER TABLE monitor ADD ping_timeout INTEGER default 2 not null; +COMMIT; From ffd0157474b8d0563a842c797b75b0def1ebd52b Mon Sep 17 00:00:00 2001 From: filippolauria Date: Fri, 31 Jan 2025 13:58:30 +0100 Subject: [PATCH 02/17] added ping options patch to patchList --- server/database.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/database.js b/server/database.js index 0e6a7405d..415624b9f 100644 --- a/server/database.js +++ b/server/database.js @@ -111,7 +111,8 @@ class Database { "patch-notification-config.sql": true, "patch-fix-kafka-producer-booleans.sql": true, "patch-timeout.sql": true, - "patch-monitor-tls-info-add-fk.sql": true, // The last file so far converted to a knex migration file + "patch-monitor-tls-info-add-fk.sql": true, + "patch-add-ping-advanced-options.sql": true, // The last file so far converted to a knex migration file }; /** From 55075f10bd4bdd750f11b21c2543d7ed324ee4ab Mon Sep 17 00:00:00 2001 From: filippolauria Date: Fri, 31 Jan 2025 14:02:55 +0100 Subject: [PATCH 03/17] build: added constants for ping advanced options and rebuilt util.js Added MIN/MAX/DEFAULT constants for: - ping count - ping deadline - ping timeout - and packet size, too. --- src/util.js | 42 +++++++++++++++++++++++++++++++++++------- src/util.ts | 20 ++++++++++++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/util.js b/src/util.js index df89cf92b..a116d16ee 100644 --- a/src/util.js +++ b/src/util.js @@ -8,17 +8,34 @@ // Backend uses the compiled file util.js // Frontend uses util.ts */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); -exports.sleep = exports.flipStatus = exports.badgeConstants = exports.CONSOLE_STYLE_BgGray = exports.CONSOLE_STYLE_BgWhite = exports.CONSOLE_STYLE_BgCyan = exports.CONSOLE_STYLE_BgMagenta = exports.CONSOLE_STYLE_BgBlue = exports.CONSOLE_STYLE_BgYellow = exports.CONSOLE_STYLE_BgGreen = exports.CONSOLE_STYLE_BgRed = exports.CONSOLE_STYLE_BgBlack = exports.CONSOLE_STYLE_FgPink = exports.CONSOLE_STYLE_FgBrown = exports.CONSOLE_STYLE_FgViolet = exports.CONSOLE_STYLE_FgLightBlue = exports.CONSOLE_STYLE_FgLightGreen = exports.CONSOLE_STYLE_FgOrange = exports.CONSOLE_STYLE_FgGray = exports.CONSOLE_STYLE_FgWhite = exports.CONSOLE_STYLE_FgCyan = exports.CONSOLE_STYLE_FgMagenta = exports.CONSOLE_STYLE_FgBlue = exports.CONSOLE_STYLE_FgYellow = exports.CONSOLE_STYLE_FgGreen = exports.CONSOLE_STYLE_FgRed = exports.CONSOLE_STYLE_FgBlack = exports.CONSOLE_STYLE_Hidden = exports.CONSOLE_STYLE_Reverse = exports.CONSOLE_STYLE_Blink = exports.CONSOLE_STYLE_Underscore = exports.CONSOLE_STYLE_Dim = exports.CONSOLE_STYLE_Bright = exports.CONSOLE_STYLE_Reset = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isNode = exports.isDev = void 0; -exports.evaluateJsonQuery = exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = void 0; -exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = void 0; +exports.CONSOLE_STYLE_FgPink = exports.CONSOLE_STYLE_FgBrown = exports.CONSOLE_STYLE_FgViolet = exports.CONSOLE_STYLE_FgLightBlue = exports.CONSOLE_STYLE_FgLightGreen = exports.CONSOLE_STYLE_FgOrange = exports.CONSOLE_STYLE_FgGray = exports.CONSOLE_STYLE_FgWhite = exports.CONSOLE_STYLE_FgCyan = exports.CONSOLE_STYLE_FgMagenta = exports.CONSOLE_STYLE_FgBlue = exports.CONSOLE_STYLE_FgYellow = exports.CONSOLE_STYLE_FgGreen = exports.CONSOLE_STYLE_FgRed = exports.CONSOLE_STYLE_FgBlack = exports.CONSOLE_STYLE_Hidden = exports.CONSOLE_STYLE_Reverse = exports.CONSOLE_STYLE_Blink = exports.CONSOLE_STYLE_Underscore = exports.CONSOLE_STYLE_Dim = exports.CONSOLE_STYLE_Bright = exports.CONSOLE_STYLE_Reset = exports.PING_TIMEOUT_DEFAULT = exports.PING_TIMEOUT_MAX = exports.PING_TIMEOUT_MIN = exports.PING_COUNT_DEFAULT = exports.PING_COUNT_MAX = exports.PING_COUNT_MIN = exports.PING_DEADLINE_DEFAULT = exports.PING_DEADLINE_MAX = exports.PING_DEADLINE_MIN = exports.PING_DEFAULT_PACKET_SIZE = exports.PING_MAX_PACKET_SIZE = exports.PING_MIN_PACKET_SIZE = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isNode = exports.isDev = void 0; +exports.evaluateJsonQuery = exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.badgeConstants = exports.CONSOLE_STYLE_BgGray = exports.CONSOLE_STYLE_BgWhite = exports.CONSOLE_STYLE_BgCyan = exports.CONSOLE_STYLE_BgMagenta = exports.CONSOLE_STYLE_BgBlue = exports.CONSOLE_STYLE_BgYellow = exports.CONSOLE_STYLE_BgGreen = exports.CONSOLE_STYLE_BgRed = exports.CONSOLE_STYLE_BgBlack = void 0; const dayjs_1 = __importDefault(require("dayjs")); -const dayjs = require("dayjs"); -const jsonata = require("jsonata"); +const jsonata = __importStar(require("jsonata")); exports.isDev = process.env.NODE_ENV === "development"; exports.isNode = typeof process !== "undefined" && ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node); exports.appName = "Uptime Kuma"; @@ -35,6 +52,18 @@ exports.SQL_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss"; exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm"; exports.MAX_INTERVAL_SECOND = 2073600; exports.MIN_INTERVAL_SECOND = 20; +exports.PING_MIN_PACKET_SIZE = 1; +exports.PING_MAX_PACKET_SIZE = 65500; +exports.PING_DEFAULT_PACKET_SIZE = 56; +exports.PING_DEADLINE_MIN = 0; +exports.PING_DEADLINE_MAX = 300; +exports.PING_DEADLINE_DEFAULT = 0; +exports.PING_COUNT_MIN = 1; +exports.PING_COUNT_MAX = 100; +exports.PING_COUNT_DEFAULT = 3; +exports.PING_TIMEOUT_MIN = 0; +exports.PING_TIMEOUT_MAX = 60; +exports.PING_TIMEOUT_DEFAULT = 0; exports.CONSOLE_STYLE_Reset = "\x1b[0m"; exports.CONSOLE_STYLE_Bright = "\x1b[1m"; exports.CONSOLE_STYLE_Dim = "\x1b[2m"; @@ -66,7 +95,6 @@ exports.CONSOLE_STYLE_BgMagenta = "\x1b[45m"; exports.CONSOLE_STYLE_BgCyan = "\x1b[46m"; exports.CONSOLE_STYLE_BgWhite = "\x1b[47m"; exports.CONSOLE_STYLE_BgGray = "\x1b[100m"; - const consoleModuleColors = [ exports.CONSOLE_STYLE_FgCyan, exports.CONSOLE_STYLE_FgGreen, @@ -458,4 +486,4 @@ async function evaluateJsonQuery(data, jsonPath, jsonPathOperator, expectedValue throw new Error(`Error evaluating JSON query: ${err.message}. Response from server was: ${response}`); } } -exports.evaluateJsonQuery = evaluateJsonQuery; \ No newline at end of file +exports.evaluateJsonQuery = evaluateJsonQuery; diff --git a/src/util.ts b/src/util.ts index b3bab4fff..4d215e94e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -39,6 +39,26 @@ export const SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm"; export const MAX_INTERVAL_SECOND = 2073600; // 24 days export const MIN_INTERVAL_SECOND = 20; // 20 seconds +// Packet Size limits +export const PING_PACKET_SIZE_MIN = 1; +export const PING_PACKET_SIZE_MAX = 65500; +export const PING_PACKET_SIZE_DEFAULT = 56; + +// Deadline limits (in seconds) +export const PING_DEADLINE_MIN = 1; +export const PING_DEADLINE_MAX = 300; +export const PING_DEADLINE_DEFAULT = 10; + +// Ping count limits +export const PING_COUNT_MIN = 1; +export const PING_COUNT_MAX = 100; +export const PING_COUNT_DEFAULT = 1; + +// Timeout limits (in seconds) +export const PING_TIMEOUT_MIN = 1; +export const PING_TIMEOUT_MAX = 60; +export const PING_TIMEOUT_DEFAULT = 2; + // Console colors // https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color export const CONSOLE_STYLE_Reset = "\x1b[0m"; From 4bd775e4bef9a049fb38d574a53aedc924e55800 Mon Sep 17 00:00:00 2001 From: filippolauria Date: Fri, 31 Jan 2025 14:08:07 +0100 Subject: [PATCH 04/17] added advanced ping options to server and monitor and also added validation using ping MIN/MAX constants in monitor --- server/model/monitor.js | 33 ++++++++++++++++++++++++++++++++- server/server.js | 6 ++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 3ad8cfafc..67c295f68 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -2,7 +2,8 @@ const dayjs = require("dayjs"); const axios = require("axios"); const { Prometheus } = require("../prometheus"); const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, - SQL_DATETIME_FORMAT, evaluateJsonQuery + SQL_DATETIME_FORMAT, evaluateJsonQuery, PING_PACKET_SIZE_MIN, PING_PACKET_SIZE_MAX, + PING_DEADLINE_MIN, PING_DEADLINE_MAX, PING_COUNT_MIN, PING_COUNT_MAX, PING_TIMEOUT_MIN, PING_TIMEOUT_MAX } = require("../../src/util"); const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery, redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal @@ -155,6 +156,12 @@ class Monitor extends BeanModel { snmpVersion: this.snmpVersion, rabbitmqNodes: JSON.parse(this.rabbitmqNodes), conditions: JSON.parse(this.conditions), + + // ping advanced options + ping_numeric: this.isPingNumeric(), + ping_count: this.ping_count, + ping_deadline: this.ping_deadline, + ping_timeout: this.ping_timeout, }; if (includeSensitiveData) { @@ -247,6 +254,14 @@ class Monitor extends BeanModel { return Boolean(this.expiryNotification); } + /** + * Check if ping should use numeric output only + * @returns {boolean} True if IP addresses will be output instead of symbolic hostnames + */ + isPingNumeric() { + return Boolean(this.ping_numeric); + } + /** * Parse to boolean * @returns {boolean} Should TLS errors be ignored? @@ -1500,6 +1515,22 @@ class Monitor extends BeanModel { if (this.interval < MIN_INTERVAL_SECOND) { throw new Error(`Interval cannot be less than ${MIN_INTERVAL_SECOND} seconds`); } + + if (this.packetSize && (this.packetSize < PING_PACKET_SIZE_MIN || this.packetSize > PING_PACKET_SIZE_MAX)) { + throw new Error(`Packet size must be between ${PING_PACKET_SIZE_MIN} and ${PING_PACKET_SIZE_MAX}`); + } + + if (this.ping_deadline && (this.ping_deadline < PING_DEADLINE_MIN || this.ping_deadline > PING_DEADLINE_MAX)) { + throw new Error(`Deadline must be between ${PING_DEADLINE_MIN} and ${PING_DEADLINE_MAX} seconds`); + } + + if (this.ping_count && (this.ping_count < PING_COUNT_MIN || this.ping_count > PING_COUNT_MAX)) { + throw new Error(`Echo requests count must be between ${PING_COUNT_MIN} and ${PING_COUNT_MAX}`); + } + + if (this.ping_timeout && (this.ping_timeout < PING_TIMEOUT_MIN || this.ping_timeout > PING_TIMEOUT_MAX)) { + throw new Error(`Timeout must be between ${PING_TIMEOUT_MIN} and ${PING_TIMEOUT_MAX} seconds`); + } } /** diff --git a/server/server.js b/server/server.js index ec5ad49f6..38b93acf9 100644 --- a/server/server.js +++ b/server/server.js @@ -875,6 +875,12 @@ let needSetup = false; bean.rabbitmqPassword = monitor.rabbitmqPassword; bean.conditions = JSON.stringify(monitor.conditions); + // ping advanced options + bean.ping_numeric = monitor.ping_numeric; + bean.ping_count = monitor.ping_count; + bean.ping_deadline = monitor.ping_deadline; + bean.ping_timeout = monitor.ping_timeout; + bean.validate(); await R.store(bean); From e1bdc53ba5e8e0c9fcb6fbdefc5b6146e1ee2f1e Mon Sep 17 00:00:00 2001 From: filippolauria Date: Fri, 31 Jan 2025 14:11:12 +0100 Subject: [PATCH 05/17] refactor: enhanced ping function with advanced options and docs - Added advanced parameters (count, deadline, timeout) - Updated parameter names for clarity - Used constants for default values - Improved method and parameter documentation --- server/util-server.js | 57 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/server/util-server.js b/server/util-server.js index 5ebc62ac5..187872589 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -1,7 +1,11 @@ const tcpp = require("tcp-ping"); const ping = require("@louislam/ping"); const { R } = require("redbean-node"); -const { log, genSecret, badgeConstants } = require("../src/util"); +const { + log, genSecret, badgeConstants, + PING_PACKET_SIZE_DEFAULT, PING_DEADLINE_DEFAULT, + PING_COUNT_DEFAULT, PING_TIMEOUT_DEFAULT +} = require("../src/util"); const passwordHash = require("./password-hash"); const { Resolver } = require("dns"); const iconv = require("iconv-lite"); @@ -118,20 +122,33 @@ exports.tcping = function (hostname, port) { /** * Ping the specified machine - * @param {string} hostname Hostname / address of machine - * @param {number} size Size of packet to send + * @param {string} dest_address Hostname / IP address of machine to ping + * @param {number} count Number of packets to send before stopping + * @param {string} source_address Source address for sending/receiving echo requests + * @param {boolean} numeric If true, IP addresses will be output instead of symbolic hostnames + * @param {number} size Size (in bytes) of echo request to send + * @param {number} deadline Maximum time in seconds before ping stops, regardless of packets sent + * @param {number} timeout Maximum time in seconds to wait for each response * @returns {Promise} Time for ping in ms rounded to nearest integer */ -exports.ping = async (hostname, size = 56) => { +exports.ping = async ( + dest_address, + count = PING_COUNT_DEFAULT, + source_address = '', + numeric = true, + size = PING_PACKET_SIZE_DEFAULT, + deadline = PING_DEADLINE_DEFAULT, + timeout = PING_TIMEOUT_DEFAULT, +) => { try { - return await exports.pingAsync(hostname, false, size); + return await exports.pingAsync(dest_address, false, count, source_address, numeric, size, deadline, timeout); } catch (e) { // If the host cannot be resolved, try again with ipv6 log.debug("ping", "IPv6 error message: " + e.message); // As node-ping does not report a specific error for this, try again if it is an empty message with ipv6 no matter what. if (!e.message) { - return await exports.pingAsync(hostname, true, size); + return await exports.pingAsync(dest_address, true, count, source_address, numeric, size, deadline, timeout); } else { throw e; } @@ -140,18 +157,34 @@ exports.ping = async (hostname, size = 56) => { /** * Ping the specified machine - * @param {string} hostname Hostname / address of machine to ping + * @param {string} dest_address Hostname / IP address of machine to ping * @param {boolean} ipv6 Should IPv6 be used? - * @param {number} size Size of ping packet to send + * @param {number} count Number of packets to send before stopping + * @param {string} source_address Source address for sending/receiving echo requests + * @param {boolean} numeric If true, IP addresses will be output instead of symbolic hostnames + * @param {number} size Size (in bytes) of echo request to send + * @param {number} deadline Maximum time in seconds before ping stops, regardless of packets sent + * @param {number} timeout Maximum time in seconds to wait for each response * @returns {Promise} Time for ping in ms rounded to nearest integer */ -exports.pingAsync = function (hostname, ipv6 = false, size = 56) { +exports.pingAsync = function ( + dest_address, + ipv6 = false, + count = PING_COUNT_DEFAULT, + source_address = '', + numeric = true, + size = PING_PACKET_SIZE_DEFAULT, + deadline = PING_DEADLINE_DEFAULT, + timeout = PING_TIMEOUT_DEFAULT, +) { return new Promise((resolve, reject) => { - ping.promise.probe(hostname, { + ping.promise.probe(dest_address, { v6: ipv6, - min_reply: 1, - deadline: 10, + min_reply: count, + sourceAddr: source_address, packetSize: size, + deadline: deadline, + timeout: timeout }).then((res) => { // If ping failed, it will set field to unknown if (res.alive) { From 7371cefc27cb7169427c40791bd2e105439a3d46 Mon Sep 17 00:00:00 2001 From: filippolauria Date: Fri, 31 Jan 2025 14:12:54 +0100 Subject: [PATCH 06/17] added UI for advanced ping configuration Added form fields to configure: - packet count - timeout - deadline - numeric output option in monitor creation/edit view --- src/pages/EditMonitor.vue | 82 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index a83f91cab..3d3f3ca13 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -660,12 +660,54 @@ - + +
+ + +
+ {{ $t("Number of packets to send before stopping") }} +
+
+ + +
+ + +
+ {{ $t("If checked, IP addresses will be output instead of symbolic hostnames") }} +
+
+ +
- +
+ +
+ + +
+ {{ $t("Total time in seconds before ping stops, regardless of packets sent") }} +
+
+ + +
+ + +
+ {{ $t("Maximum time in seconds to wait for each response") }} +
+
+ +