generated from nhcarrigan/template
feat: add prometheus metrics
This commit is contained in:
parent
188480052b
commit
23fba3d95d
@ -44,6 +44,7 @@
|
|||||||
"express": "4.19.2",
|
"express": "4.19.2",
|
||||||
"node-html-to-image": "4.0.0",
|
"node-html-to-image": "4.0.0",
|
||||||
"node-schedule": "2.1.1",
|
"node-schedule": "2.1.1",
|
||||||
|
"prom-client": "15.1.3",
|
||||||
"winston": "3.13.0"
|
"winston": "3.13.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
pnpm-lock.yaml
generated
30
pnpm-lock.yaml
generated
@ -29,6 +29,9 @@ importers:
|
|||||||
node-schedule:
|
node-schedule:
|
||||||
specifier: 2.1.1
|
specifier: 2.1.1
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
|
prom-client:
|
||||||
|
specifier: 15.1.3
|
||||||
|
version: 15.1.3
|
||||||
winston:
|
winston:
|
||||||
specifier: 3.13.0
|
specifier: 3.13.0
|
||||||
version: 3.13.0
|
version: 3.13.0
|
||||||
@ -252,6 +255,10 @@ packages:
|
|||||||
'@octokit/types@13.5.0':
|
'@octokit/types@13.5.0':
|
||||||
resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==}
|
resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==}
|
||||||
|
|
||||||
|
'@opentelemetry/api@1.9.0':
|
||||||
|
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
|
||||||
|
engines: {node: '>=8.0.0'}
|
||||||
|
|
||||||
'@pkgr/core@0.1.1':
|
'@pkgr/core@0.1.1':
|
||||||
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
|
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
|
||||||
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
||||||
@ -547,6 +554,9 @@ packages:
|
|||||||
before-after-hook@2.2.3:
|
before-after-hook@2.2.3:
|
||||||
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
||||||
|
|
||||||
|
bintrees@1.0.2:
|
||||||
|
resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==}
|
||||||
|
|
||||||
body-parser@1.20.2:
|
body-parser@1.20.2:
|
||||||
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
|
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
@ -1716,6 +1726,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
|
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
|
|
||||||
|
prom-client@15.1.3:
|
||||||
|
resolution: {integrity: sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==}
|
||||||
|
engines: {node: ^16 || ^18 || >=20}
|
||||||
|
|
||||||
proxy-addr@2.0.7:
|
proxy-addr@2.0.7:
|
||||||
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
@ -1991,6 +2005,9 @@ packages:
|
|||||||
tar-stream@3.1.7:
|
tar-stream@3.1.7:
|
||||||
resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
|
resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
|
||||||
|
|
||||||
|
tdigest@0.1.2:
|
||||||
|
resolution: {integrity: sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==}
|
||||||
|
|
||||||
text-hex@1.0.0:
|
text-hex@1.0.0:
|
||||||
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
|
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
|
||||||
|
|
||||||
@ -2476,6 +2493,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@octokit/openapi-types': 22.2.0
|
'@octokit/openapi-types': 22.2.0
|
||||||
|
|
||||||
|
'@opentelemetry/api@1.9.0': {}
|
||||||
|
|
||||||
'@pkgr/core@0.1.1': {}
|
'@pkgr/core@0.1.1': {}
|
||||||
|
|
||||||
'@prisma/client@5.13.0(prisma@5.13.0)':
|
'@prisma/client@5.13.0(prisma@5.13.0)':
|
||||||
@ -2816,6 +2835,8 @@ snapshots:
|
|||||||
|
|
||||||
before-after-hook@2.2.3: {}
|
before-after-hook@2.2.3: {}
|
||||||
|
|
||||||
|
bintrees@1.0.2: {}
|
||||||
|
|
||||||
body-parser@1.20.2:
|
body-parser@1.20.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes: 3.1.2
|
bytes: 3.1.2
|
||||||
@ -4168,6 +4189,11 @@ snapshots:
|
|||||||
|
|
||||||
progress@2.0.3: {}
|
progress@2.0.3: {}
|
||||||
|
|
||||||
|
prom-client@15.1.3:
|
||||||
|
dependencies:
|
||||||
|
'@opentelemetry/api': 1.9.0
|
||||||
|
tdigest: 0.1.2
|
||||||
|
|
||||||
proxy-addr@2.0.7:
|
proxy-addr@2.0.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
forwarded: 0.2.0
|
forwarded: 0.2.0
|
||||||
@ -4512,6 +4538,10 @@ snapshots:
|
|||||||
fast-fifo: 1.3.2
|
fast-fifo: 1.3.2
|
||||||
streamx: 2.16.1
|
streamx: 2.16.1
|
||||||
|
|
||||||
|
tdigest@0.1.2:
|
||||||
|
dependencies:
|
||||||
|
bintrees: 1.0.2
|
||||||
|
|
||||||
text-hex@1.0.0: {}
|
text-hex@1.0.0: {}
|
||||||
|
|
||||||
text-table@0.2.0: {}
|
text-table@0.2.0: {}
|
||||||
|
@ -3,6 +3,7 @@ import { scheduleJob } from "node-schedule";
|
|||||||
import { ExtendedClient } from "../../interfaces/ExtendedClient";
|
import { ExtendedClient } from "../../interfaces/ExtendedClient";
|
||||||
import { maintainSecurity } from "../../modules/maintainSecurity";
|
import { maintainSecurity } from "../../modules/maintainSecurity";
|
||||||
import { postBirthdays } from "../../modules/postBirthdays";
|
import { postBirthdays } from "../../modules/postBirthdays";
|
||||||
|
import { Prometheus } from "../../modules/prometheus";
|
||||||
import { registerCommands } from "../../utils/registerCommands";
|
import { registerCommands } from "../../utils/registerCommands";
|
||||||
import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ import { sendDebugMessage } from "../../utils/sendDebugMessage";
|
|||||||
export const onReady = async (bot: ExtendedClient) => {
|
export const onReady = async (bot: ExtendedClient) => {
|
||||||
await sendDebugMessage(bot, `Logged in as ${bot.user?.tag}`);
|
await sendDebugMessage(bot, `Logged in as ${bot.user?.tag}`);
|
||||||
await registerCommands(bot);
|
await registerCommands(bot);
|
||||||
|
bot.analytics = new Prometheus(bot);
|
||||||
|
|
||||||
// Daily at 9am PST
|
// Daily at 9am PST
|
||||||
scheduleJob("birthdays", "0 9 * * *", async () => await postBirthdays(bot));
|
scheduleJob("birthdays", "0 9 * * *", async () => await postBirthdays(bot));
|
||||||
|
@ -15,4 +15,5 @@ export const onGuildCreate = async function (
|
|||||||
await bot.env.debugHook.send({
|
await bot.env.debugHook.send({
|
||||||
content: `JOINED GUILD: ${guild.name} (${guild.id}) - owned by ${owner?.displayName} (${owner.id})`
|
content: `JOINED GUILD: ${guild.name} (${guild.id}) - owned by ${owner?.displayName} (${owner.id})`
|
||||||
});
|
});
|
||||||
|
bot.analytics.updateGuilds(bot);
|
||||||
};
|
};
|
||||||
|
@ -36,6 +36,7 @@ export const onGuildDelete = async function (
|
|||||||
await bot.db.security
|
await bot.db.security
|
||||||
.deleteMany({ where: { serverId: guild.id } })
|
.deleteMany({ where: { serverId: guild.id } })
|
||||||
.catch(() => null);
|
.catch(() => null);
|
||||||
|
bot.analytics.updateGuilds(bot);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await errorHandler(bot, "on guild delete", err);
|
await errorHandler(bot, "on guild delete", err);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ export const onInteraction = async (
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bot.analytics.commandUsed();
|
||||||
if (interaction.isChatInputCommand()) {
|
if (interaction.isChatInputCommand()) {
|
||||||
handleChatInputCommand(bot, interaction);
|
handleChatInputCommand(bot, interaction);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import { Client, WebhookClient } from "discord.js";
|
|||||||
import { Command } from "./Command";
|
import { Command } from "./Command";
|
||||||
import { Context } from "./Context";
|
import { Context } from "./Context";
|
||||||
|
|
||||||
|
import type { Prometheus } from "../modules/prometheus.js";
|
||||||
|
|
||||||
export interface ExtendedClient extends Client {
|
export interface ExtendedClient extends Client {
|
||||||
env: {
|
env: {
|
||||||
token: string;
|
token: string;
|
||||||
@ -12,6 +14,7 @@ export interface ExtendedClient extends Client {
|
|||||||
devMode: boolean;
|
devMode: boolean;
|
||||||
};
|
};
|
||||||
db: PrismaClient;
|
db: PrismaClient;
|
||||||
|
analytics: Prometheus;
|
||||||
commands: Command[];
|
commands: Command[];
|
||||||
contexts: Context[];
|
contexts: Context[];
|
||||||
configs: { [serverId: string]: Omit<configs, "id"> };
|
configs: { [serverId: string]: Omit<configs, "id"> };
|
||||||
|
29
src/modules/prometheus.ts
Normal file
29
src/modules/prometheus.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import client, { Counter, Gauge } from "prom-client";
|
||||||
|
import type { ExtendedClient } from "../interfaces/ExtendedClient.js";
|
||||||
|
|
||||||
|
export class Prometheus {
|
||||||
|
private client = client;
|
||||||
|
private guilds: Gauge;
|
||||||
|
private commands: Counter;
|
||||||
|
|
||||||
|
constructor(bot: ExtendedClient) {
|
||||||
|
this.guilds = new Gauge({
|
||||||
|
name: "guilds",
|
||||||
|
help: "The number of guilds the bot is in."
|
||||||
|
});
|
||||||
|
this.guilds.set(bot.guilds.cache.size);
|
||||||
|
this.commands = new Counter({
|
||||||
|
name: "commands",
|
||||||
|
help: "The number of commands that have been used since last boot."
|
||||||
|
});
|
||||||
|
this.client.collectDefaultMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
public commandUsed() {
|
||||||
|
this.commands.inc();
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateGuilds(bot: ExtendedClient) {
|
||||||
|
this.guilds.set(bot.guilds.cache.size);
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import https from "https";
|
|||||||
import { Octokit } from "@octokit/rest";
|
import { Octokit } from "@octokit/rest";
|
||||||
import { GuildTextBasedChannel } from "discord.js";
|
import { GuildTextBasedChannel } from "discord.js";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
|
import { register } from "prom-client";
|
||||||
|
|
||||||
import { IgnoredActors, ThankYou } from "../config/Github";
|
import { IgnoredActors, ThankYou } from "../config/Github";
|
||||||
import { ExtendedClient } from "../interfaces/ExtendedClient";
|
import { ExtendedClient } from "../interfaces/ExtendedClient";
|
||||||
@ -47,6 +48,15 @@ export const serve = async (bot: ExtendedClient) => {
|
|||||||
res.send("bot online!");
|
res.send("bot online!");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get("/metrics", async (_req, res) => {
|
||||||
|
try {
|
||||||
|
res.set("Content-Type", register.contentType);
|
||||||
|
res.end(await register.metrics());
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).end(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.post("/kofi", async (req, res) => {
|
app.post("/kofi", async (req, res) => {
|
||||||
const payload = JSON.parse(req.body.data);
|
const payload = JSON.parse(req.body.data);
|
||||||
const {
|
const {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user