summary refs log tree commit diff
path: root/slowcord/status/src/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'slowcord/status/src/index.ts')
-rw-r--r--slowcord/status/src/index.ts126
1 files changed, 126 insertions, 0 deletions
diff --git a/slowcord/status/src/index.ts b/slowcord/status/src/index.ts
new file mode 100644

index 00000000..11298699 --- /dev/null +++ b/slowcord/status/src/index.ts
@@ -0,0 +1,126 @@ +import "dotenv/config"; +import https from "https"; +import Fosscord from "fosscord-gopnik"; +import mysql from "mysql2"; + +const dbConn = mysql.createConnection(process.env.DATABASE as string); +const executePromise = (sql: string, args: any[]) => new Promise((resolve, reject) => dbConn.execute(sql, args, (err, res) => { if (err) reject(err); else resolve(res); })); + +const instance = { + app: process.env.INSTANCE_WEB_APP as string, + api: process.env.INSTANCE_API as string, + cdn: process.env.INSTANCE_CDN as string, + token: process.env.INSTANCE_TOKEN as string, +}; + +const client = new Fosscord.Client({ + intents: [], + http: { + api: instance.api, + cdn: instance.cdn + } +}); + +const gatewayMeasure = async (name: string) => { + const time = Math.max(client.ws.ping, 0); + await savePerf(time, name, ''); + console.log(`${name} took ${time}ms`); +}; + +client.on("ready", () => { + console.log(`Ready on gateway as ${client.user!.tag}`); +}); + +client.on("error", (error) => { + console.log(`Gateway error`, error); +}); + +client.on("warn", (msg) => { + console.log(`Gateway warning:`, msg); +}); + +const savePerf = async (time: number, name: string, error?: string | Error) => { + if (error && typeof error != "string") error = error.message; + try { + await executePromise("INSERT INTO performance (value, endpoint, timestamp, error) VALUES (?, ?, ?, ?)", [time ?? 0, name, new Date(), error ?? null]); + await executePromise("DELETE FROM performance WHERE DATE(timestamp) < now() - interval ? DAY", [process.env.RETENTION_DAYS]); + } + catch (e) { + console.error(e); + } +}; + +const makeTimedRequest = (path: string, body?: object): Promise<number> => new Promise((resolve, reject) => { + const opts = { + hostname: new URL(path).hostname, + port: 443, + path: new URL(path).pathname, + method: "GET", + headers: { + "Content-Type": "application/json", + "Authorization": instance.token, + }, + timeout: 1000, + }; + + let start: number, end: number; + const req = https.request(opts, res => { + if (res.statusCode! < 200 || res.statusCode! > 300) { + return reject(`${res.statusCode} ${res.statusMessage}`); + } + + res.on("data", (data) => { + }); + + res.on("end", () => { + end = Date.now(); + resolve(end - start); + }) + }); + + req.on("finish", () => { + if (body) req.write(JSON.stringify(body)); + start = Date.now(); + }); + + req.on("error", (error) => { + reject(error); + }); + + req.end(); +}); + +const measureApi = async (name: string, path: string, body?: object) => { + let error, time = -1; + try { + time = await makeTimedRequest(path, body); + } + catch (e) { + error = e as Error | string; + } + + console.log(`${name} took ${time}ms ${(error ? "with error" : "")}`, error ?? ""); + + await savePerf(time, name, error); +}; + +const app = async () => { + await new Promise((resolve) => dbConn.connect(resolve)); + console.log("Connected to db"); + // await client.login(instance.token); + + console.log(`Monitoring performance for instance at ${new URL(instance.api).hostname}`); + + const doMeasurements = async () => { + await measureApi("ping", `${instance.api}/ping`); + await measureApi("users/@me", `${instance.api}/users/@me`); + await measureApi("login", `${instance.app}/login`); + // await gatewayMeasure("websocketPing"); + + setTimeout(doMeasurements, parseInt(process.env.MEASURE_INTERVAL as string)); + }; + + doMeasurements(); +}; + +app(); \ No newline at end of file