add website tracking
This commit is contained in:
parent
358bb6272c
commit
ff11240334
14
data/websites.json
Normal file
14
data/websites.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Minecraft.net",
|
||||||
|
"url": "https://minecraft.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Minecraft Textures",
|
||||||
|
"url": "https://textures.minecraft.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Minecraft Session Server",
|
||||||
|
"url": "https://session.minecraft.net"
|
||||||
|
}
|
||||||
|
]
|
@ -14,7 +14,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@influxdata/influxdb-client": "^1.33.2",
|
"@influxdata/influxdb-client": "^1.33.2",
|
||||||
"@types/mcping-js": "^1.5.4",
|
"@types/mcping-js": "^1.5.4",
|
||||||
|
"@types/node": "^20.10.6",
|
||||||
"@types/node-cron": "^3.0.11",
|
"@types/node-cron": "^3.0.11",
|
||||||
|
"axios": "^1.6.4",
|
||||||
"dns": "^0.2.2",
|
"dns": "^0.2.2",
|
||||||
"mcpe-ping-fixed": "^0.0.3",
|
"mcpe-ping-fixed": "^0.0.3",
|
||||||
"mcping-js": "^1.5.0",
|
"mcping-js": "^1.5.0",
|
||||||
@ -22,7 +24,6 @@
|
|||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"tsup": "^8.0.1",
|
"tsup": "^8.0.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"winston": "^3.11.0",
|
"winston": "^3.11.0"
|
||||||
"@types/node": "^20.10.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
pnpm-lock.yaml
generated
64
pnpm-lock.yaml
generated
@ -17,6 +17,9 @@ dependencies:
|
|||||||
'@types/node-cron':
|
'@types/node-cron':
|
||||||
specifier: ^3.0.11
|
specifier: ^3.0.11
|
||||||
version: 3.0.11
|
version: 3.0.11
|
||||||
|
axios:
|
||||||
|
specifier: ^1.6.4
|
||||||
|
version: 1.6.4
|
||||||
dns:
|
dns:
|
||||||
specifier: ^0.2.2
|
specifier: ^0.2.2
|
||||||
version: 0.2.2
|
version: 0.2.2
|
||||||
@ -570,10 +573,24 @@ packages:
|
|||||||
resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
|
resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/asynckit@0.4.0:
|
||||||
|
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/aws-sign@0.2.0:
|
/aws-sign@0.2.0:
|
||||||
resolution: {integrity: sha512-6P7/Ls5F6++DsKu7iacris7qq/AZSWaX+gT4dtSyUxM82ePxWxaP7Slo82ZO3ZTx6GSKxQHAQlmFvM8e+Dd8ZA==}
|
resolution: {integrity: sha512-6P7/Ls5F6++DsKu7iacris7qq/AZSWaX+gT4dtSyUxM82ePxWxaP7Slo82ZO3ZTx6GSKxQHAQlmFvM8e+Dd8ZA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/axios@1.6.4:
|
||||||
|
resolution: {integrity: sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A==}
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: 1.15.4
|
||||||
|
form-data: 4.0.0
|
||||||
|
proxy-from-env: 1.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
dev: false
|
||||||
|
|
||||||
/balanced-match@1.0.2:
|
/balanced-match@1.0.2:
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -762,6 +779,13 @@ packages:
|
|||||||
delayed-stream: 0.0.5
|
delayed-stream: 0.0.5
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/combined-stream@1.0.8:
|
||||||
|
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
dependencies:
|
||||||
|
delayed-stream: 1.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/commander@0.6.1:
|
/commander@0.6.1:
|
||||||
resolution: {integrity: sha512-0fLycpl1UMTGX257hRsu/arL/cUbcvQM4zMKwvLvzXtfdezIV4yotPS2dYtknF+NmEfWSoCEF6+hj9XLm/6hEw==}
|
resolution: {integrity: sha512-0fLycpl1UMTGX257hRsu/arL/cUbcvQM4zMKwvLvzXtfdezIV4yotPS2dYtknF+NmEfWSoCEF6+hj9XLm/6hEw==}
|
||||||
engines: {node: '>= 0.4.x'}
|
engines: {node: '>= 0.4.x'}
|
||||||
@ -900,6 +924,11 @@ packages:
|
|||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/delayed-stream@1.0.0:
|
||||||
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
|
engines: {node: '>=0.4.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/depd@0.3.0:
|
/depd@0.3.0:
|
||||||
resolution: {integrity: sha512-Uyx3FgdvEYlpA3W4lf37Ide++2qOsjLlJ7dap0tbM63j/BxTCcxmyIOO6PXbKbOuNSko+fsDHzzx1DUeo1+3fA==}
|
resolution: {integrity: sha512-Uyx3FgdvEYlpA3W4lf37Ide++2qOsjLlJ7dap0tbM63j/BxTCcxmyIOO6PXbKbOuNSko+fsDHzzx1DUeo1+3fA==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@ -1158,6 +1187,16 @@ packages:
|
|||||||
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
|
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/follow-redirects@1.15.4:
|
||||||
|
resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==}
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
peerDependencies:
|
||||||
|
debug: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
debug:
|
||||||
|
optional: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/foreground-child@3.1.1:
|
/foreground-child@3.1.1:
|
||||||
resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
|
resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@ -1179,6 +1218,15 @@ packages:
|
|||||||
mime: 1.2.11
|
mime: 1.2.11
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/form-data@4.0.0:
|
||||||
|
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
dependencies:
|
||||||
|
asynckit: 0.4.0
|
||||||
|
combined-stream: 1.0.8
|
||||||
|
mime-types: 2.1.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fresh@0.2.2:
|
/fresh@0.2.2:
|
||||||
resolution: {integrity: sha512-ZGGi8GROK//ijm2gB33sUuN9TjN1tC/dvG4Bt4j6IWrVGpMmudUBCxx+Ir7qePsdREfkpQC4FL8W0jeSOsgv1w==}
|
resolution: {integrity: sha512-ZGGi8GROK//ijm2gB33sUuN9TjN1tC/dvG4Bt4j6IWrVGpMmudUBCxx+Ir7qePsdREfkpQC4FL8W0jeSOsgv1w==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -1455,11 +1503,23 @@ packages:
|
|||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/mime-db@1.52.0:
|
||||||
|
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mime-types@1.0.2:
|
/mime-types@1.0.2:
|
||||||
resolution: {integrity: sha512-echfutj/t5SoTL4WZpqjA1DCud1XO0WQF3/GJ48YBmc4ZMhCK77QA6Z/w6VTQERLKuJ4drze3kw2TUT8xZXVNw==}
|
resolution: {integrity: sha512-echfutj/t5SoTL4WZpqjA1DCud1XO0WQF3/GJ48YBmc4ZMhCK77QA6Z/w6VTQERLKuJ4drze3kw2TUT8xZXVNw==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/mime-types@2.1.35:
|
||||||
|
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
dependencies:
|
||||||
|
mime-db: 1.52.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mime@1.2.11:
|
/mime@1.2.11:
|
||||||
resolution: {integrity: sha512-Ysa2F/nqTNGHhhm9MV8ure4+Hc+Y8AWiqUdHxsO7xu8zc92ND9f3kpALHjaP026Ft17UfxrMt95c50PLUeynBw==}
|
resolution: {integrity: sha512-Ysa2F/nqTNGHhhm9MV8ure4+Hc+Y8AWiqUdHxsO7xu8zc92ND9f3kpALHjaP026Ft17UfxrMt95c50PLUeynBw==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -1713,6 +1773,10 @@ packages:
|
|||||||
ipaddr.js: 0.1.2
|
ipaddr.js: 0.1.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/proxy-from-env@1.1.0:
|
||||||
|
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/punycode@2.3.1:
|
/punycode@2.3.1:
|
||||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Influx from "./influx/influx";
|
import Influx from "./influx/influx";
|
||||||
import ServerManager from "./server/serverManager";
|
import ServerManager from "./server/serverManager";
|
||||||
|
import WebsiteManager from "./website/websiteManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The influx database instance.
|
* The influx database instance.
|
||||||
@ -7,3 +8,4 @@ import ServerManager from "./server/serverManager";
|
|||||||
export const influx = new Influx();
|
export const influx = new Influx();
|
||||||
|
|
||||||
new ServerManager();
|
new ServerManager();
|
||||||
|
new WebsiteManager();
|
||||||
|
@ -41,7 +41,7 @@ export default class ServerManager {
|
|||||||
// ping all servers in parallel
|
// ping all servers in parallel
|
||||||
await Promise.all(this.servers.map((server) => server.pingServer()));
|
await Promise.all(this.servers.map((server) => server.pingServer()));
|
||||||
|
|
||||||
logger.info("Finished pinging servers");
|
logger.info("Finished pinging servers!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
64
src/website/website.ts
Normal file
64
src/website/website.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { Point } from "@influxdata/influxdb-client";
|
||||||
|
import axios from "axios";
|
||||||
|
import { influx } from "..";
|
||||||
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
|
import Config from "../../data/config.json";
|
||||||
|
|
||||||
|
type WebsiteOptions = {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class Website {
|
||||||
|
/**
|
||||||
|
* The name of the website.
|
||||||
|
*/
|
||||||
|
private name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The url of the website.
|
||||||
|
*/
|
||||||
|
private url: string;
|
||||||
|
|
||||||
|
constructor({ name, url }: WebsiteOptions) {
|
||||||
|
this.name = name;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pings a website and gets the response.
|
||||||
|
*
|
||||||
|
* @returns the response
|
||||||
|
*/
|
||||||
|
public async pingWebsite(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const before = Date.now();
|
||||||
|
const response = await axios.get(this.url, {
|
||||||
|
validateStatus: () => true, // Don't throw a error on non-200 status codes
|
||||||
|
timeout: Config.pinger.timeout,
|
||||||
|
});
|
||||||
|
if (response.status === 500) {
|
||||||
|
throw new Error("Server returned 500 status code");
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseTime = Date.now() - before;
|
||||||
|
|
||||||
|
influx.writePoint(
|
||||||
|
new Point("websiteStatus")
|
||||||
|
.tag("name", this.name)
|
||||||
|
.booleanField("online", true)
|
||||||
|
.intField("responseTime", responseTime)
|
||||||
|
.timestamp(Date.now())
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`Failed to ping ${this.name}:`, err);
|
||||||
|
influx.writePoint(
|
||||||
|
new Point("websiteStatus")
|
||||||
|
.tag("name", this.name)
|
||||||
|
.booleanField("online", false)
|
||||||
|
.timestamp(Date.now())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
src/website/websiteManager.ts
Normal file
47
src/website/websiteManager.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import cron from "node-cron";
|
||||||
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
|
import Config from "../../data/config.json";
|
||||||
|
import Websites from "../../data/websites.json";
|
||||||
|
import Website from "./website";
|
||||||
|
|
||||||
|
export default class WebsiteManager {
|
||||||
|
private websites: Website[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
logger.info("Loading websites...");
|
||||||
|
for (const configWebsite of Websites) {
|
||||||
|
const website = new Website({
|
||||||
|
name: configWebsite.name,
|
||||||
|
url: configWebsite.url,
|
||||||
|
});
|
||||||
|
this.websites.push(website);
|
||||||
|
}
|
||||||
|
logger.info(`Loaded ${this.websites.length} websites!`);
|
||||||
|
|
||||||
|
cron.schedule(Config.pinger.pingCron, () => {
|
||||||
|
this.pingWebsites();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ping all websites to update their status.
|
||||||
|
*/
|
||||||
|
private async pingWebsites(): Promise<void> {
|
||||||
|
logger.info(`Pinging websites ${this.websites.length}`);
|
||||||
|
|
||||||
|
// ping all websites in parallel
|
||||||
|
await Promise.all(this.websites.map((website) => website.pingWebsite()));
|
||||||
|
|
||||||
|
logger.info("Finished pinging websites!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the websites.
|
||||||
|
*
|
||||||
|
* @returns the websites
|
||||||
|
*/
|
||||||
|
public getWebsites(): Website[] {
|
||||||
|
return this.websites;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user