Make ping true ping

This commit is contained in:
shamoon 2023-10-19 14:40:12 -07:00
parent 0136562dd3
commit ef5c1d4826
8 changed files with 73 additions and 48 deletions

View File

@ -101,30 +101,50 @@ To use a local icon, first create a Docker mount to `/app/public/icons` and then
## Ping
Services may have an optional `ping` property that allows you to monitor the availability of an endpoint you chose and have the response time displayed. You do not need to set your ping URL equal to your href URL.
!!! note
The ping feature works by making an http `HEAD` request to the URL, and falls back to `GET` in case that fails. It will not, for example, login if the URL requires auth or is behind e.g. Authelia. In the case of a reverse proxy and/or auth this usually requires the use of an 'internal' URL to make the ping feature correctly display status.
Services may have an optional `ping` property that allows you to monitor the availability of an external host. As of v0.7.5, the ping feature uses the true ping command on the underlying host.
```yaml
- Group A:
- Sonarr:
icon: sonarr.png
href: http://sonarr.host/
ping: http://sonarr.host/
ping: sonarr.host
- Group B:
- Radarr:
icon: radarr.png
href: http://radarr.host/
ping: http://some.other.host/
ping: some.other.host
```
<img width="1038" alt="Ping" src="https://github.com/gethomepage/homepage/assets/88257202/7bc13bd3-0d0b-44e3-888c-a20e069a3233">
You can also apply different styles to the ping indicator by using the `statusStyle` property, see [settings](settings.md#status-style).
## Site Monitor
Services may have an optional `siteMonitor` property (formerly `ping`) that allows you to monitor the availability of a URL you chose and have the response time displayed. You do not need to set your monitor URL equal to your href or ping URL.
!!! note
The site monitor feature works by making an http `HEAD` request to the URL, and falls back to `GET` in case that fails. It will not, for example, login if the URL requires auth or is behind e.g. Authelia. In the case of a reverse proxy and/or auth this usually requires the use of an 'internal' URL to make the site monitor feature correctly display status.
```yaml
- Group A:
- Sonarr:
icon: sonarr.png
href: http://sonarr.host/
siteMonitor: http://sonarr.host/
- Group B:
- Radarr:
icon: radarr.png
href: http://radarr.host/
siteMonitor: http://some.other.host/
```
You can also apply different styles to the site monitor indicator by using the `statusStyle` property, see [settings](settings.md#status-style).
## Docker Integration
Services may be connected to a Docker container, either running on the local machine, or a remote machine.

View File

@ -382,11 +382,11 @@ If you have both set the per-service settings take precedence.
## Status Style
You can choose from the following styles for docker or k8s status and ping: `dot` or `basic`
You can choose from the following styles for docker or k8s status, site monitor and ping: `dot` or `basic`
- The default is no value, and displays the ping response time in ms and the docker / k8s container status
- `dot` shows a green dot for a successful ping or healthy status.
- `basic` shows either UP or DOWN for ping
- The default is no value, and displays the montior and ping response time in ms and the docker / k8s container status
- `dot` shows a green dot for a successful monitor ping or healthy status.
- `basic` shows either UP or DOWN for monitor & ping
For example:

9
package-lock.json generated
View File

@ -23,6 +23,7 @@
"minecraft-ping-js": "^1.0.2",
"next": "^12.3.1",
"next-i18next": "^12.0.1",
"ping": "^0.4.4",
"pretty-bytes": "^6.0.0",
"raw-body": "^2.5.1",
"react": "^18.2.0",
@ -4861,6 +4862,14 @@
"node": ">=0.10.0"
}
},
"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",

View File

@ -25,6 +25,7 @@
"minecraft-ping-js": "^1.0.2",
"next": "^12.3.1",
"next-i18next": "^12.0.1",
"ping": "^0.4.4",
"pretty-bytes": "^6.0.0",
"raw-body": "^2.5.1",
"react": "^18.2.0",

View File

@ -50,6 +50,9 @@ dependencies:
next-i18next:
specifier: ^12.0.1
version: 12.1.0(next@12.3.4)(react-dom@18.2.0)(react@18.2.0)
ping:
specifier: ^0.4.4
version: 0.4.4
pretty-bytes:
specifier: ^6.0.0
version: 6.1.0
@ -3103,6 +3106,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/ping@0.4.4:
resolution: {integrity: sha512-56ZMC0j7SCsMMLdOoUg12VZCfj/+ZO+yfOSjaNCRrmZZr6GLbN2X/Ui56T15dI8NhiHckaw5X2pvyfAomanwqQ==}
engines: {node: '>=4.0.0'}
dev: false
/pirates@4.0.5:
resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==}
engines: {node: '>= 6'}

View File

@ -9,7 +9,7 @@ export default function Ping({ group, service, style }) {
let colorClass = "text-black/20 dark:text-white/40 opacity-20";
let backgroundClass = "bg-theme-500/10 dark:bg-theme-900/50 px-1.5 py-0.5";
let statusTitle = t("ping.http_status");
let statusTitle = t("ping.ping");
let statusText = "";
if (error) {
@ -19,18 +19,13 @@ export default function Ping({ group, service, style }) {
} else if (!data) {
statusText = t("ping.ping");
statusTitle += ` ${t("ping.not_available")}`;
} else if (data.status > 403) {
} else if (!data.alive) {
colorClass = "text-rose-500/80";
statusTitle += ` ${data.status}`;
if (style === "basic") {
statusText = t("ping.down");
} else {
statusText = data.status;
}
} else if (data) {
const ping = t("common.ms", { value: data.latency, style: "unit", unit: "millisecond", maximumFractionDigits: 0 });
statusTitle += ` ${data.status} (${ping})`;
statusTitle += ` ${t("ping.down")}`;
statusText = t("ping.down");
} else if (data.alive) {
const ping = t("common.ms", { value: data.time, style: "unit", unit: "millisecond", maximumFractionDigits: 0 });
statusTitle += ` ${t("ping.up")} (${ping})`;
colorClass = "text-emerald-500/80";
if (style === "basic") {

View File

@ -1,8 +1,7 @@
import { performance } from "perf_hooks";
import { promise as ping } from "ping";
import { getServiceItem } from "utils/config/service-helpers";
import createLogger from "utils/logger";
import { httpProxy } from "utils/proxy/http";
const logger = createLogger("ping");
@ -16,35 +15,28 @@ export default async function handler(req, res) {
});
}
const { ping: pingURL } = serviceItem;
const { ping: pingHostOrURL } = serviceItem;
if (!pingURL) {
logger.debug("No ping URL specified");
if (!pingHostOrURL) {
logger.debug("No ping host specified");
return res.status(400).send({
error: "No ping URL given",
error: "No ping host given",
});
}
let hostname = pingHostOrURL;
try {
let startTime = performance.now();
let [status] = await httpProxy(pingURL, {
method: "HEAD",
});
let endTime = performance.now();
if (status > 403) {
// try one more time as a GET in case HEAD is rejected for whatever reason
startTime = performance.now();
[status] = await httpProxy(pingURL);
endTime = performance.now();
}
return res.status(200).json({
status,
latency: endTime - startTime,
});
// maintain backwards compatibility with old ping where may be http://...
hostname = new URL(pingHostOrURL).hostname;
} catch (e) {
logger.debug("Error attempting ping: %s", JSON.stringify(e));
// eslint-disable-line no-empty
}
try {
const response = await ping.probe(hostname);
return res.status(200).json(response);
} catch (e) {
logger.debug("Error attempting ping: %s", e);
return res.status(400).send({
error: "Error attempting ping, see logs.",
});

View File

@ -44,7 +44,7 @@ export default async function handler(req, res) {
latency: endTime - startTime,
});
} catch (e) {
logger.debug("Error attempting http monitor: %s", JSON.stringify(e));
logger.debug("Error attempting http monitor: %s", e);
return res.status(400).send({
error: "Error attempting http monitor, see logs.",
});