diff --git a/backend/package-lock.json b/backend/package-lock.json index 79e1da28..f1978985 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -24,7 +24,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.45", + "knub": "^30.0.0-beta.46", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", @@ -3043,9 +3043,9 @@ } }, "node_modules/knub": { - "version": "30.0.0-beta.45", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.45.tgz", - "integrity": "sha512-r1jtHBYthOn8zjgyILh418/Qnw8f/cUMzz5aky7+T5HLFV0BAiBzeg5TOb0UFMkn8ewIPSy8GTG1x/CIAv3s8Q==", + "version": "30.0.0-beta.46", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.46.tgz", + "integrity": "sha512-eNGfFVXwdDnyIjL3nLJceVIlwDdfnM3zJPuPdsOKUbRp4yNBnRSBcG+TnaXc3nUWmXIq3q78rRPeThoo0qz6iQ==", "dependencies": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", @@ -8290,9 +8290,9 @@ } }, "knub": { - "version": "30.0.0-beta.45", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.45.tgz", - "integrity": "sha512-r1jtHBYthOn8zjgyILh418/Qnw8f/cUMzz5aky7+T5HLFV0BAiBzeg5TOb0UFMkn8ewIPSy8GTG1x/CIAv3s8Q==", + "version": "30.0.0-beta.46", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.46.tgz", + "integrity": "sha512-eNGfFVXwdDnyIjL3nLJceVIlwDdfnM3zJPuPdsOKUbRp4yNBnRSBcG+TnaXc3nUWmXIq3q78rRPeThoo0qz6iQ==", "requires": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", diff --git a/backend/package.json b/backend/package.json index a6bf19c8..91516ab9 100644 --- a/backend/package.json +++ b/backend/package.json @@ -39,7 +39,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.45", + "knub": "^30.0.0-beta.46", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", diff --git a/backend/src/plugins/Automod/events/runAutomodOnMessage.ts b/backend/src/plugins/Automod/events/runAutomodOnMessage.ts index 7181b257..449352fe 100644 --- a/backend/src/plugins/Automod/events/runAutomodOnMessage.ts +++ b/backend/src/plugins/Automod/events/runAutomodOnMessage.ts @@ -6,6 +6,7 @@ import { addRecentActionsFromMessage } from "../functions/addRecentActionsFromMe import { clearRecentActionsForMessage } from "../functions/clearRecentActionsForMessage"; import { runAutomod } from "../functions/runAutomod"; import { AutomodContext, AutomodPluginType } from "../types"; +import { performance } from "perf_hooks"; export function runAutomodOnMessage( pluginData: GuildPluginData, @@ -23,11 +24,16 @@ export function runAutomodOnMessage( }; pluginData.state.queue.add(async () => { + const startTime = performance.now(); + if (isEdit) { clearRecentActionsForMessage(pluginData, context); } addRecentActionsFromMessage(pluginData, context); + await runAutomod(pluginData, context); + + pluginData.getKnubInstance().profiler.addDataPoint(`automod:${pluginData.guild.id}`, performance.now() - startTime); }); } diff --git a/backend/src/plugins/BotControl/BotControlPlugin.ts b/backend/src/plugins/BotControl/BotControlPlugin.ts index 9c6b0123..7897d837 100644 --- a/backend/src/plugins/BotControl/BotControlPlugin.ts +++ b/backend/src/plugins/BotControl/BotControlPlugin.ts @@ -18,7 +18,7 @@ import { ReloadServerCmd } from "./commands/ReloadServerCmd"; import { RemoveDashboardUserCmd } from "./commands/RemoveDashboardUserCmd"; import { ServersCmd } from "./commands/ServersCmd"; import { BotControlPluginType, ConfigSchema } from "./types"; -import { PluginPerformanceCmd } from "./commands/PluginPerformanceCmd"; +import { ProfilerDataCmd } from "./commands/ProfilerDataCmd"; import { AddServerFromInviteCmd } from "./commands/AddServerFromInviteCmd"; import { ChannelToServerCmd } from "./commands/ChannelToServerCmd"; import { RestPerformanceCmd } from "./commands/RestPerformanceCmd"; @@ -53,7 +53,7 @@ export const BotControlPlugin = zeppelinGlobalPlugin()({ ListDashboardUsersCmd, ListDashboardPermsCmd, EligibleCmd, - PluginPerformanceCmd, + ProfilerDataCmd, RestPerformanceCmd, RateLimitPerformanceCmd, AddServerFromInviteCmd, diff --git a/backend/src/plugins/BotControl/commands/PluginPerformanceCmd.ts b/backend/src/plugins/BotControl/commands/PluginPerformanceCmd.ts deleted file mode 100644 index afcb3d6c..00000000 --- a/backend/src/plugins/BotControl/commands/PluginPerformanceCmd.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { TextChannel } from "discord.js"; -import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; -import { createChunkedMessage, formatNumber, resolveInvite, sorter, verboseUserMention } from "../../../utils"; -import { botControlCmd } from "../types"; - -export const PluginPerformanceCmd = botControlCmd({ - trigger: ["plugin_performance"], - permission: "can_performance", - - signature: {}, - - async run({ pluginData, message: msg, args }) { - const stats = pluginData.getKnubInstance().getPluginPerformanceStats(); - const averageLoadTimeEntries = Object.entries(stats.averageLoadTimes); - averageLoadTimeEntries.sort(sorter((v) => v[1].time, "DESC")); - const lines = averageLoadTimeEntries.map( - ([pluginName, { time }]) => `${pluginName}: **${formatNumber(Math.round(time))}ms**`, - ); - const fullStats = `Average plugin load times:\n\n${lines.join("\n")}`; - createChunkedMessage(msg.channel as TextChannel, fullStats); - }, -}); diff --git a/backend/src/plugins/BotControl/commands/ProfilerDataCmd.ts b/backend/src/plugins/BotControl/commands/ProfilerDataCmd.ts new file mode 100644 index 00000000..1ddc9dc6 --- /dev/null +++ b/backend/src/plugins/BotControl/commands/ProfilerDataCmd.ts @@ -0,0 +1,57 @@ +import { TextChannel } from "discord.js"; +import { commandTypeHelpers as ct } from "../../../commandTypes"; +import { getBaseUrl, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { createChunkedMessage, formatNumber, resolveInvite, sorter, verboseUserMention } from "../../../utils"; +import { botControlCmd } from "../types"; +import { GuildArchives } from "../../../data/GuildArchives"; +import moment from "moment-timezone"; + +const sortProps = { + totalTime: "TOTAL TIME", + averageTime: "AVERAGE TIME", + count: "SAMPLES", +}; + +export const ProfilerDataCmd = botControlCmd({ + trigger: ["profiler_data"], + permission: "can_performance", + + signature: { + filter: ct.string({ required: false }), + sort: ct.string({ option: true, required: false }), + }, + + async run({ pluginData, message: msg, args }) { + if (args.sort === "samples") { + args.sort = "count"; + } + const sortProp = args.sort && sortProps[args.sort] ? args.sort : "totalTime"; + + const headerInfoItems = [`sorted by ${sortProps[sortProp]}`]; + + const profilerData = pluginData.getKnubInstance().profiler.getData(); + let entries = Object.entries(profilerData); + entries.sort(sorter((entry) => entry[1][sortProp], "DESC")); + + if (args.filter) { + entries = entries.filter(([key]) => key.includes(args.filter)); + headerInfoItems.push(`matching "${args.filter}"`); + } + + const formattedEntries = entries.map(([key, data]) => { + const dataLines = [ + ["Total time", `${Math.round(data.totalTime)} ms`], + ["Average time", `${Math.round(data.averageTime)} ms`], + ["Samples", data.count], + ]; + return `${key}\n${dataLines.map((v) => ` ${v[0]}: ${v[1]}`).join("\n")}`; + }); + const formatted = `Profiler data, ${headerInfoItems.join(", ")}:\n\n${formattedEntries.join("\n\n")}`; + + const archives = GuildArchives.getGuildInstance("0"); + const archiveId = await archives.create(formatted, moment().add(1, "hour")); + const archiveUrl = archives.getUrl(getBaseUrl(pluginData), archiveId); + + msg.channel.send(`Link: ${archiveUrl}`); + }, +});