diff options
author | Madeline <46743919+MaddyUnderStars@users.noreply.github.com> | 2023-01-10 13:19:05 +1100 |
---|---|---|
committer | Madeline <46743919+MaddyUnderStars@users.noreply.github.com> | 2023-01-10 13:20:37 +1100 |
commit | 2f065e6b3793f2c2d4ab196a341cf23efb721011 (patch) | |
tree | 8966b0ec65d611d7b3a129e16d3276b58344ba44 | |
parent | Add error handler for individual gateway sockets (diff) | |
download | server-2f065e6b3793f2c2d4ab196a341cf23efb721011.tar.xz |
Move sentry init to util. use sentry in each module, not just bundle
-rw-r--r-- | src/api/Server.ts | 5 | ||||
-rw-r--r-- | src/bundle/Server.ts | 78 | ||||
-rw-r--r-- | src/cdn/Server.ts | 6 | ||||
-rw-r--r-- | src/cdn/start.ts | 3 | ||||
-rw-r--r-- | src/gateway/Server.ts | 10 | ||||
-rw-r--r-- | src/util/util/Sentry.ts | 102 | ||||
-rw-r--r-- | src/util/util/index.ts | 1 |
7 files changed, 125 insertions, 80 deletions
diff --git a/src/api/Server.ts b/src/api/Server.ts index fff94936..1a0ea6b2 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts @@ -1,7 +1,7 @@ import "missing-native-js-functions"; import { Server, ServerOptions } from "lambert-server"; import { Authentication, CORS } from "./middlewares/"; -import { Config, initDatabase, initEvent } from "@fosscord/util"; +import { Config, initDatabase, initEvent, Sentry } from "@fosscord/util"; import { ErrorHandler } from "./middlewares/ErrorHandler"; import { BodyParser } from "./middlewares/BodyParser"; import { Router, Request, Response, NextFunction } from "express"; @@ -38,6 +38,7 @@ export class FosscordServer extends Server { await Config.init(); await initEvent(); await initInstance(); + await Sentry.init(this.app); let logRequests = process.env["LOG_REQUESTS"] != undefined; if (logRequests) { @@ -96,6 +97,8 @@ export class FosscordServer extends Server { this.app.use(ErrorHandler); TestClient(this.app); + Sentry.errorHandler(this.app); + if (logRequests) console.log( red( diff --git a/src/bundle/Server.ts b/src/bundle/Server.ts index e6f8d17c..abd05e1f 100644 --- a/src/bundle/Server.ts +++ b/src/bundle/Server.ts @@ -7,10 +7,7 @@ import * as Gateway from "@fosscord/gateway"; import { CDNServer } from "@fosscord/cdn"; import express from "express"; import { green, bold, yellow } from "picocolors"; -import { Config, initDatabase } from "@fosscord/util"; -import * as Sentry from "@sentry/node"; -import * as Tracing from "@sentry/tracing"; -import * as Integrations from "@sentry/integrations"; +import { Config, initDatabase, Sentry } from "@fosscord/util"; const app = express(); const server = http.createServer(); @@ -30,81 +27,12 @@ process.on("SIGTERM", async () => { async function main() { await initDatabase(); await Config.init(); - - //Sentry - if (Config.get().sentry.enabled) { - console.log( - `[Bundle] ${yellow( - "You are using Sentry! This may slightly impact performance on large loads!", - )}`, - ); - Sentry.init({ - dsn: Config.get().sentry.endpoint, - integrations: [ - new Sentry.Integrations.Http({ tracing: true }), - new Tracing.Integrations.Express({ app }), - new Tracing.Integrations.Mysql(), - new Integrations.RewriteFrames({ - root: __dirname, - }), - ], - tracesSampleRate: Config.get().sentry.traceSampleRate, - environment: Config.get().sentry.environment, - }); - - Sentry.addGlobalEventProcessor((event, hint) => { - if (event.transaction) { - // Rewrite things that look like IDs to `:id` for sentry - event.transaction = event.transaction - .split("/") - .map((x) => (!parseInt(x) ? x : ":id")) - .join("/"); - } - - // TODO: does this even do anything? - delete event.request?.cookies; - if (event.request?.headers) { - delete event.request.headers["X-Real-Ip"]; - delete event.request.headers["X-Forwarded-For"]; - delete event.request.headers["X-Forwarded-Host"]; - delete event.request.headers["X-Super-Properties"]; - } - - if (event.breadcrumbs) { - event.breadcrumbs = event.breadcrumbs.filter((x) => { - // Filter breadcrumbs that we don't care about - if (x.message?.includes("identified as")) return false; - if (x.message?.includes("[WebSocket] closed")) return false; - if ( - x.message?.includes( - "Got Resume -> cancel not implemented", - ) - ) - return false; - if (x.message?.includes("[Gateway] New connection from")) - return false; - - return true; - }); - } - - return event; - }); - - app.use(Sentry.Handlers.requestHandler()); - app.use(Sentry.Handlers.tracingHandler()); - } + await Sentry.init(app); server.listen(port); await Promise.all([api.start(), cdn.start(), gateway.start()]); - if (Config.get().sentry.enabled) { - app.use(Sentry.Handlers.errorHandler()); - app.use(function onError(err: any, req: any, res: any, next: any) { - res.statusCode = 500; - res.end(res.sentry + "\n"); - }); - } + Sentry.errorHandler(app); console.log(`[Server] ${green(`listening on port ${bold(port)}`)}`); } diff --git a/src/cdn/Server.ts b/src/cdn/Server.ts index 7340a735..abf59a2a 100644 --- a/src/cdn/Server.ts +++ b/src/cdn/Server.ts @@ -1,5 +1,5 @@ import { Server, ServerOptions } from "lambert-server"; -import { Config, initDatabase, registerRoutes } from "@fosscord/util"; +import { Config, initDatabase, registerRoutes, Sentry } from "@fosscord/util"; import path from "path"; import avatarsRoute from "./routes/avatars"; import guildProfilesRoute from "./routes/guild-profiles"; @@ -18,6 +18,8 @@ export class CDNServer extends Server { async start() { await initDatabase(); await Config.init(); + await Sentry.init(this.app); + this.app.use((req, res, next) => { res.set("Access-Control-Allow-Origin", "*"); // TODO: use better CSP policy @@ -87,6 +89,8 @@ export class CDNServer extends Server { ); this.log("verbose", "[Server] Route /guilds/banners registered"); + Sentry.errorHandler(this.app); + return super.start(); } diff --git a/src/cdn/start.ts b/src/cdn/start.ts index c22984fa..4b619c25 100644 --- a/src/cdn/start.ts +++ b/src/cdn/start.ts @@ -1,6 +1,5 @@ require("module-alias/register"); -import dotenv from "dotenv"; -dotenv.config(); +import "dotenv/config"; import { CDNServer } from "./Server"; const server = new CDNServer({ port: Number(process.env.PORT) || 3003 }); diff --git a/src/gateway/Server.ts b/src/gateway/Server.ts index 7e1489be..48f1a7d9 100644 --- a/src/gateway/Server.ts +++ b/src/gateway/Server.ts @@ -1,7 +1,13 @@ import "missing-native-js-functions"; import dotenv from "dotenv"; dotenv.config(); -import { closeDatabase, Config, initDatabase, initEvent } from "@fosscord/util"; +import { + closeDatabase, + Config, + initDatabase, + initEvent, + Sentry, +} from "@fosscord/util"; import ws from "ws"; import { Connection } from "./events/Connection"; import http from "http"; @@ -50,6 +56,8 @@ export class Server { await initDatabase(); await Config.init(); await initEvent(); + await Sentry.init(); + if (!this.server.listening) { this.server.listen(this.port); console.log(`[Gateway] online on 0.0.0.0:${this.port}`); diff --git a/src/util/util/Sentry.ts b/src/util/util/Sentry.ts new file mode 100644 index 00000000..3e7bb97b --- /dev/null +++ b/src/util/util/Sentry.ts @@ -0,0 +1,102 @@ +import { Config } from "./Config"; +import { yellow } from "picocolors"; + +import express from "express"; +import * as SentryNode from "@sentry/node"; +import * as Tracing from "@sentry/tracing"; +import * as Integrations from "@sentry/integrations"; + +// Work around for when bundle calls api/etc +let errorHandlersUsed = false; + +export const Sentry = { + /** Call BEFORE registering your routes */ + init: async (app?: express.Application) => { + const { enabled, endpoint, traceSampleRate, environment } = + Config.get().sentry; + if (!enabled) return; + + if (!!SentryNode.getCurrentHub().getClient()) return; // we've already initialised sentry + + console.log("[Sentry] Enabling sentry..."); + + if (traceSampleRate >= 0.8) { + console.log( + `[Sentry] ${yellow( + "Your sentry trace sampling rate is >= 80%. For large loads, this may degrade performance.", + )}`, + ); + } + + SentryNode.init({ + dsn: endpoint, + integrations: [ + new SentryNode.Integrations.Http({ tracing: true }), + new Tracing.Integrations.Express({ app }), + new Tracing.Integrations.Mysql(), + new Integrations.RewriteFrames({ + root: __dirname, + }), + ], + tracesSampleRate: traceSampleRate, // naming? + environment, + }); + + SentryNode.addGlobalEventProcessor((event, hint) => { + if (event.transaction) { + // Rewrite things that look like IDs to `:id` for sentry + event.transaction = event.transaction + .split("/") + .map((x) => (!parseInt(x) ? x : ":id")) + .join("/"); + } + + // TODO: does this even do anything? + delete event.request?.cookies; + if (event.request?.headers) { + delete event.request.headers["X-Real-Ip"]; + delete event.request.headers["X-Forwarded-For"]; + delete event.request.headers["X-Forwarded-Host"]; + delete event.request.headers["X-Super-Properties"]; + } + + if (event.breadcrumbs) { + event.breadcrumbs = event.breadcrumbs.filter((x) => { + // Filter breadcrumbs that we don't care about + if (x.message?.includes("identified as")) return false; + if (x.message?.includes("[WebSocket] closed")) return false; + if ( + x.message?.includes( + "Got Resume -> cancel not implemented", + ) + ) + return false; + if (x.message?.includes("[Gateway] New connection from")) + return false; + + return true; + }); + } + + return event; + }); + + if (app) { + app.use(SentryNode.Handlers.requestHandler()); + app.use(SentryNode.Handlers.tracingHandler()); + } + }, + + /** Call AFTER registering your routes */ + errorHandler: (app: express.Application) => { + if (!Config.get().sentry.enabled) return; + if (errorHandlersUsed) return; + errorHandlersUsed = true; + + app.use(SentryNode.Handlers.errorHandler()); + app.use(function onError(err: any, req: any, res: any, next: any) { + res.statusCode = 500; + res.end(res.sentry + "\n"); + }); + }, +}; diff --git a/src/util/util/index.ts b/src/util/util/index.ts index 01ef4eae..0012579f 100644 --- a/src/util/util/index.ts +++ b/src/util/util/index.ts @@ -20,3 +20,4 @@ export * from "./String"; export * from "./Array"; export * from "./TraverseDirectory"; export * from "./InvisibleCharacters"; +export * from "./Sentry"; |