diff --git a/src/command.ts b/src/command.ts index 203567a..dac3d13 100644 --- a/src/command.ts +++ b/src/command.ts @@ -9,14 +9,16 @@ import { isElevated, noAuthResponse, sortBoards, - sortLists + sortLists, + stripIndentsAndNewlines, + truncate } from './util'; import { getBoard, getMember, TrelloAPIError } from './util/api'; import { prisma } from './util/prisma'; import { TrelloBoard, TrelloCard, TrelloLabel, TrelloList } from './util/types'; import fuzzy from 'fuzzy'; import { createT, langs } from './util/locale'; -import { logger } from './logger'; +import { reportError } from './util/airbrake'; interface AutocompleteItemOptions { userData?: User; @@ -208,7 +210,7 @@ export default abstract class Command extends SlashCommand { }); } - logger.error('Error in autocomplete', err); + reportError(err, `Error in autocomplete (${this.commandName})`, 'autocomplete', ctx, this.commandName); } async onError(err: Error, ctx: CommandContext) { @@ -225,16 +227,20 @@ export default abstract class Command extends SlashCommand { } if (isElevated(ctx.user.id)) { - console.log((err as any).toJSON()); - console.log((err as any).request); - console.log((err as any).response); + const e = err as any; + reportError(err, `Error in command (${ctx.commandName})`, 'command', ctx); return ctx.send({ - content: '```js\n' + err.stack + '```', + content: stripIndentsAndNewlines` + __Error in command (${ctx.commandName})__ + ${e.response && e.response.status ? `Status: ${e.response.status}` : ''} + ${e.response && e.response.status ? `Response: ${truncate(e.response.data, 1000)}` : ''} + `, + embeds: [{ description: '```js\n' + err.stack + '```' }], ephemeral: true }); } - // ? should i even localize this + reportError(err, `Error in command (${ctx.commandName})`, 'command', ctx); if (err instanceof TrelloAPIError) return ctx.send("An error occurred with Trello's API!\n" + err.toString()); else return ctx.send('An error occurred!\n' + err.toString()); } diff --git a/src/util/airbrake.ts b/src/util/airbrake.ts new file mode 100644 index 0000000..47a1046 --- /dev/null +++ b/src/util/airbrake.ts @@ -0,0 +1,39 @@ +import { Notifier } from '@airbrake/node'; +import { AutocompleteContext, CommandContext } from 'slash-create'; +import { logger } from '../logger'; + +const notifier = new Notifier({ + projectId: parseInt(process.env.AIRBRAKE_PROJECT_ID, 10), + projectKey: process.env.AIRBRAKE_PROJECT_KEY, + environment: process.env.AIRBRAKE_ENV, + keysBlocklist: [process.env.DATABASE_URL, process.env.DISCORD_BOT_TOKEN] +}); + +export function reportError( + error: any, + premsg?: string, + type?: string, + ctx?: CommandContext | AutocompleteContext, + commandName?: string +) { + if (process.env.AIRBRAKE_PROJECT_ID && process.env.AIRBRAKE_PROJECT_KEY) + notifier.notify({ + error, + params: { + ...(type ? { type } : {}), + ...(ctx + ? { + command: 'commandName' in ctx ? ctx.commandName : commandName, + user: { + id: ctx.user.id, + username: ctx.user.username, + discriminator: ctx.user.discriminator + }, + guildID: ctx.guildID, + channelID: ctx.channelID + } + : {}) + } + }); + logger.error(...(premsg ? [premsg] : []), error); +}