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": {
|
||||
"@influxdata/influxdb-client": "^1.33.2",
|
||||
"@types/mcping-js": "^1.5.4",
|
||||
"@types/node": "^20.10.6",
|
||||
"@types/node-cron": "^3.0.11",
|
||||
"axios": "^1.6.4",
|
||||
"dns": "^0.2.2",
|
||||
"mcpe-ping-fixed": "^0.0.3",
|
||||
"mcping-js": "^1.5.0",
|
||||
@ -22,7 +24,6 @@
|
||||
"ts-node": "^10.9.2",
|
||||
"tsup": "^8.0.1",
|
||||
"typescript": "^5.3.3",
|
||||
"winston": "^3.11.0",
|
||||
"@types/node": "^20.10.6"
|
||||
"winston": "^3.11.0"
|
||||
}
|
||||
}
|
||||
|
64
pnpm-lock.yaml
generated
64
pnpm-lock.yaml
generated
@ -17,6 +17,9 @@ dependencies:
|
||||
'@types/node-cron':
|
||||
specifier: ^3.0.11
|
||||
version: 3.0.11
|
||||
axios:
|
||||
specifier: ^1.6.4
|
||||
version: 1.6.4
|
||||
dns:
|
||||
specifier: ^0.2.2
|
||||
version: 0.2.2
|
||||
@ -570,10 +573,24 @@ packages:
|
||||
resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
|
||||
dev: false
|
||||
|
||||
/asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
dev: false
|
||||
|
||||
/aws-sign@0.2.0:
|
||||
resolution: {integrity: sha512-6P7/Ls5F6++DsKu7iacris7qq/AZSWaX+gT4dtSyUxM82ePxWxaP7Slo82ZO3ZTx6GSKxQHAQlmFvM8e+Dd8ZA==}
|
||||
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:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: false
|
||||
@ -762,6 +779,13 @@ packages:
|
||||
delayed-stream: 0.0.5
|
||||
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:
|
||||
resolution: {integrity: sha512-0fLycpl1UMTGX257hRsu/arL/cUbcvQM4zMKwvLvzXtfdezIV4yotPS2dYtknF+NmEfWSoCEF6+hj9XLm/6hEw==}
|
||||
engines: {node: '>= 0.4.x'}
|
||||
@ -900,6 +924,11 @@ packages:
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/depd@0.3.0:
|
||||
resolution: {integrity: sha512-Uyx3FgdvEYlpA3W4lf37Ide++2qOsjLlJ7dap0tbM63j/BxTCcxmyIOO6PXbKbOuNSko+fsDHzzx1DUeo1+3fA==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@ -1158,6 +1187,16 @@ packages:
|
||||
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
|
||||
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:
|
||||
resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
|
||||
engines: {node: '>=14'}
|
||||
@ -1179,6 +1218,15 @@ packages:
|
||||
mime: 1.2.11
|
||||
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:
|
||||
resolution: {integrity: sha512-ZGGi8GROK//ijm2gB33sUuN9TjN1tC/dvG4Bt4j6IWrVGpMmudUBCxx+Ir7qePsdREfkpQC4FL8W0jeSOsgv1w==}
|
||||
dev: false
|
||||
@ -1455,11 +1503,23 @@ packages:
|
||||
picomatch: 2.3.1
|
||||
dev: false
|
||||
|
||||
/mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/mime-types@1.0.2:
|
||||
resolution: {integrity: sha512-echfutj/t5SoTL4WZpqjA1DCud1XO0WQF3/GJ48YBmc4ZMhCK77QA6Z/w6VTQERLKuJ4drze3kw2TUT8xZXVNw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
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:
|
||||
resolution: {integrity: sha512-Ysa2F/nqTNGHhhm9MV8ure4+Hc+Y8AWiqUdHxsO7xu8zc92ND9f3kpALHjaP026Ft17UfxrMt95c50PLUeynBw==}
|
||||
dev: false
|
||||
@ -1713,6 +1773,10 @@ packages:
|
||||
ipaddr.js: 0.1.2
|
||||
dev: false
|
||||
|
||||
/proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
dev: false
|
||||
|
||||
/punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Influx from "./influx/influx";
|
||||
import ServerManager from "./server/serverManager";
|
||||
import WebsiteManager from "./website/websiteManager";
|
||||
|
||||
/**
|
||||
* The influx database instance.
|
||||
@ -7,3 +8,4 @@ import ServerManager from "./server/serverManager";
|
||||
export const influx = new Influx();
|
||||
|
||||
new ServerManager();
|
||||
new WebsiteManager();
|
||||
|
@ -41,7 +41,7 @@ export default class ServerManager {
|
||||
// ping all servers in parallel
|
||||
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…
Reference in New Issue
Block a user