From 95c6cee3e24b3529522ef1ec7fb815f7a32f25e5 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Thu, 25 May 2023 23:44:20 +0100 Subject: [PATCH] add retry on probe --- Probe/Dockerfile.tpl | 3 + .../Utils/Monitors/MonitorTypes/ApiMonitor.ts | 12 ++- .../Monitors/MonitorTypes/PingMonitor.ts | 97 ++++++++----------- .../Monitors/MonitorTypes/WebsiteMonitor.ts | 14 ++- Probe/package-lock.json | 15 +++ Probe/package.json | 2 + 6 files changed, 85 insertions(+), 58 deletions(-) diff --git a/Probe/Dockerfile.tpl b/Probe/Dockerfile.tpl index c7f20364cd6..46fede3c22e 100644 --- a/Probe/Dockerfile.tpl +++ b/Probe/Dockerfile.tpl @@ -12,12 +12,15 @@ RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm co RUN apk update && apk add bash && apk add curl + # Install python RUN apk update && apk add --no-cache --virtual .gyp python3 make g++ #Use bash shell by default SHELL ["/bin/bash", "-c"] +# Install iputils +RUN apk add iputils RUN mkdir /usr/src diff --git a/Probe/Utils/Monitors/MonitorTypes/ApiMonitor.ts b/Probe/Utils/Monitors/MonitorTypes/ApiMonitor.ts index 357ca087c4f..d1298e71397 100644 --- a/Probe/Utils/Monitors/MonitorTypes/ApiMonitor.ts +++ b/Probe/Utils/Monitors/MonitorTypes/ApiMonitor.ts @@ -27,7 +27,8 @@ export default class ApiMonitor { requestHeaders?: Headers | undefined; requestBody?: JSONObject | undefined; requestType?: HTTPMethod | undefined; - } + }, + retry?: number | undefined ): Promise { try { const startTime: [number, number] = process.hrtime(); @@ -56,6 +57,15 @@ export default class ApiMonitor { requestBody: options.requestBody || {}, }; } catch (err) { + if (!retry) { + retry = 0; // default value + } + + if (retry < 5) { + retry++; + return await this.ping(url, options, retry); + } + return { url: url, isOnline: false, diff --git a/Probe/Utils/Monitors/MonitorTypes/PingMonitor.ts b/Probe/Utils/Monitors/MonitorTypes/PingMonitor.ts index 395011cc31b..111962f7cc1 100644 --- a/Probe/Utils/Monitors/MonitorTypes/PingMonitor.ts +++ b/Probe/Utils/Monitors/MonitorTypes/PingMonitor.ts @@ -3,12 +3,12 @@ import URL from 'Common/Types/API/URL'; import IPv4 from 'Common/Types/IP/IPv4'; import IPv6 from 'Common/Types/IP/IPv6'; import PositiveNumber from 'Common/Types/PositiveNumber'; -import net, { Socket } from 'net'; +import ping from 'ping'; // TODO - make sure it work for the IPV6 export interface PingResponse { isOnline: boolean; - responseTimeInMS?: PositiveNumber; + responseTimeInMS?: PositiveNumber | undefined; } export interface PingOptions { @@ -18,62 +18,47 @@ export interface PingOptions { export default class PingMonitor { public static async ping( host: Hostname | IPv4 | IPv6 | URL, - pingOptions?: PingOptions + pingOptions?: PingOptions, + retry?: number | undefined ): Promise { - return new Promise( - (resolve: Function, _reject: Function) => { - const timeout: number = - pingOptions?.timeout?.toNumber() || 5000; - const startTime: [number, number] = process.hrtime(); - let responseTimeInMS: PositiveNumber; - let connectionOptions: net.NetConnectOpts; - if (host instanceof Hostname) { - connectionOptions = { - host: host.hostname, - port: host.port.toNumber(), - timeout, - }; - } else if (host instanceof URL) { - connectionOptions = { - host: host.hostname.hostname, - port: - host.hostname.port?.toNumber() || - (host.isHttps() ? 443 : 80), - timeout, - }; - } else { - connectionOptions = { - host: host.toString(), - port: 80, - timeout, - }; + let hostAddress: string = ''; + if (host instanceof Hostname) { + hostAddress = host.hostname; + } else if (host instanceof URL) { + hostAddress = host.hostname.hostname; + } else { + hostAddress = host.toString(); + } + + try { + const res: ping.PingResponse = await ping.promise.probe( + hostAddress, + { + timeout: Math.ceil( + (pingOptions?.timeout?.toNumber() || 5000) / 1000 + ), } - const socket: Socket = net.connect(connectionOptions); - socket.on('connect', () => { - const endTime: [number, number] = process.hrtime(startTime); - responseTimeInMS = new PositiveNumber( - (endTime[0] * 1000000000 + endTime[1]) / 1000000 - ); - }); - socket.on('timeout', () => { - resolve({ - isOnline: false, - }); - }); - socket.on('connect', () => { - socket.end(() => { - resolve({ - isOnline: true, - responseTimeInMS, - }); - }); - }); - socket.on('error', () => { - resolve({ - isOnline: false, - }); - }); + ); + + return { + isOnline: res.alive, + responseTimeInMS: res.time + ? new PositiveNumber(Math.ceil(res.time as any)) + : undefined, + }; + } catch (err) { + if (!retry) { + retry = 0; // default value } - ); + + if (retry < 5) { + retry++; + return await this.ping(host, pingOptions, retry); + } + + return { + isOnline: false, + }; + } } } diff --git a/Probe/Utils/Monitors/MonitorTypes/WebsiteMonitor.ts b/Probe/Utils/Monitors/MonitorTypes/WebsiteMonitor.ts index b33fec8b307..0d61e1c79e1 100644 --- a/Probe/Utils/Monitors/MonitorTypes/WebsiteMonitor.ts +++ b/Probe/Utils/Monitors/MonitorTypes/WebsiteMonitor.ts @@ -18,7 +18,10 @@ export interface ProbeWebsiteResponse { } export default class WebsiteMonitor { - public static async ping(url: URL): Promise { + public static async ping( + url: URL, + retry?: number | undefined + ): Promise { try { const startTime: [number, number] = process.hrtime(); const result: WebsiteResponse = await WebsiteRequest.get(url, {}); @@ -38,6 +41,15 @@ export default class WebsiteMonitor { responseHeaders: result.responseHeaders, }; } catch (err) { + if (!retry) { + retry = 0; // default value + } + + if (retry < 5) { + retry++; + return await this.ping(url, retry); + } + if (err instanceof AxiosError) { return { url: url, diff --git a/Probe/package-lock.json b/Probe/package-lock.json index 119fc981fc5..9feea8af6c8 100644 --- a/Probe/package-lock.json +++ b/Probe/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@types/ping": "^0.4.1", "axios": "^1.4.0", "Common": "file:../Common", "CommonServer": "file:../CommonServer", @@ -16,6 +17,7 @@ "jsrsasign": "^10.6.1", "Model": "file:../Model", "node-cron": "^3.0.2", + "ping": "^0.4.4", "saml2-js": "^4.0.1", "ts-node": "^10.9.1" }, @@ -1268,6 +1270,11 @@ "integrity": "sha512-9PuLtBboc/+JJ7FshmJWv769gDonTpItN0Ol5TMwclpSQNjVyB2SRxSKBcTtbSysSL5R7Oea06kTTFNciCoYwA==", "dev": true }, + "node_modules/@types/ping": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/ping/-/ping-0.4.1.tgz", + "integrity": "sha512-q/D+xQvoqrHvntvz2A0Pb0ImYwnN3zakluUp8O2qoogGoVMVbdY2K/ulxHcCh9TzYzVoojayHBa9gYQDIZ4v0A==" + }, "node_modules/@types/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", @@ -3935,6 +3942,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/ping": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/ping/-/ping-0.4.4.tgz", + "integrity": "sha512-56ZMC0j7SCsMMLdOoUg12VZCfj/+ZO+yfOSjaNCRrmZZr6GLbN2X/Ui56T15dI8NhiHckaw5X2pvyfAomanwqQ==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", diff --git a/Probe/package.json b/Probe/package.json index 6ee623e9a07..fe06f22f14b 100644 --- a/Probe/package.json +++ b/Probe/package.json @@ -14,6 +14,7 @@ "author": "", "license": "ISC", "dependencies": { + "@types/ping": "^0.4.1", "axios": "^1.4.0", "Common": "file:../Common", "CommonServer": "file:../CommonServer", @@ -21,6 +22,7 @@ "jsrsasign": "^10.6.1", "Model": "file:../Model", "node-cron": "^3.0.2", + "ping": "^0.4.4", "saml2-js": "^4.0.1", "ts-node": "^10.9.1" },