summary refs log tree commit diff
path: root/slowcord/status/src/index.ts
blob: 735b8a9b642a26610f7f2560ecda0fe8ba680e57 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import "dotenv/config";
import https from "https";
import mysql from "mysql2";
import fetch from "node-fetch";

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 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 saveSystemUsage = async (load: number, procUptime: number, sysUptime: number, ram: number, sessions: number) => {
	try {
		await executePromise("INSERT INTO monitor (time, cpu, procUp, sysUp, ram, sessions) VALUES (?, ?, ?, ?, ?, ?)", [new Date(), load, procUptime, sysUptime, ram, sessions]);
	}
	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);
};

interface monitorzSchema {
	load: number[];
	procUptime: number;
	sysUptime: number;
	memPercent: number;
	sessions: number;
}

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");

		try {
			const res = await fetch(`${instance.api}/-/monitorz`, {
				headers: {
					Authorization: process.env.INSTANCE_TOKEN as string,
				}
			});
			const json = await res.json() as monitorzSchema;
			await saveSystemUsage(json.load[1], json.procUptime, json.sysUptime, json.memPercent, json.sessions);
		}
		catch (e) {
		}

		setTimeout(doMeasurements, parseInt(process.env.MEASURE_INTERVAL as string));
	};

	doMeasurements();
};

app();