From 2413120e95ea08acdc8532e0080e820a0bbb3a5d Mon Sep 17 00:00:00 2001 From: Adeyemi Adetunji Date: Mon, 30 Sep 2024 01:49:59 +0100 Subject: [PATCH] feat: Integrate Sentry to backend (#270) * feat: Integrate Sentry to backend * update lock * update .env --------- Co-authored-by: Rotimi Best --- apps/backend/.env.example | 3 ++ apps/backend/package-lock.json | 11 +++++++ apps/backend/package.json | 2 ++ apps/backend/server.js | 31 +++++++++++++++++-- apps/docs/pages/quickstart/self-hosting.mdx | 1 + pnpm-lock.yaml | 34 +++++++++++++++++++++ 6 files changed, 79 insertions(+), 3 deletions(-) diff --git a/apps/backend/.env.example b/apps/backend/.env.example index abacf469..2c9fb028 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -16,3 +16,6 @@ SMTP_HOST= SMTP_USER= SMTP_PASSWORD= SMTP_PORT= + +# Sentry DNS +SENTRY_DNS= \ No newline at end of file diff --git a/apps/backend/package-lock.json b/apps/backend/package-lock.json index 13f51aed..ff8c1c4e 100644 --- a/apps/backend/package-lock.json +++ b/apps/backend/package-lock.json @@ -2878,6 +2878,17 @@ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, + "node_modules/node-abi": { + "version": "3.59.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.59.0.tgz", + "integrity": "sha512-HyyfzvTLCE8b1SX2nWimlra8cibEsypcSu/Az4SXMhWhtuctkwAX7qsEYNjUOIoYtPV884oN3wtYTN+iZKBtvw==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-fetch": { "version": "2.6.12", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", diff --git a/apps/backend/package.json b/apps/backend/package.json index 1d40c873..147db941 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -21,6 +21,8 @@ "dependencies": { "@aws-sdk/client-s3": "^3.388.0", "@aws-sdk/lib-storage": "^3.535.0", + "@sentry/node": "^7.110.1", + "@sentry/profiling-node": "^7.110.1", "@supabase/supabase-js": "^2.32.0", "@types/nodemailer": "^6.4.11", "axios": "^1.4.0", diff --git a/apps/backend/server.js b/apps/backend/server.js index 0779d930..523af7ef 100644 --- a/apps/backend/server.js +++ b/apps/backend/server.js @@ -4,6 +4,8 @@ const express = require('express'); const rateLimit = require('express-rate-limit'); const cors = require('cors'); const bodyParser = require('body-parser'); +const sentry = require('@sentry/node'); +const { ProfilingIntegration } = require('@sentry/profiling-node'); const uploadVideo = require('./src/routes/uploadVideo'); const downloadCertificate = require('./src/routes/downloadCertificate'); @@ -12,14 +14,19 @@ const downloadCourse = require('./src/routes/downloadCourse'); const katex = require('./src/routes/katex'); const sendEmail = require('./src/routes/sendEmail'); +sentry.init({ + dsn: process.env.SENTRY_DNS || '', + integrations: [new ProfilingIntegration()], + tracesSampleRate: 1.0, + profilesSampleRate: 1.0 +}); + // Express server const app = express(); - const port = process.env.PORT || 3002; app.use(express.json()); app.use(bodyParser.urlencoded({ extended: true })); - app.use(cors()); // Rate limiting middleware @@ -30,6 +37,11 @@ const limiter = rateLimit({ app.use(limiter); +// Integrate Sentry middleware +app.use(sentry.Handlers.requestHandler()); +app.use(sentry.Handlers.errorHandler()); + +// Register routes app.use('/downloadCertificate', downloadCertificate); app.use('/downloadLesson', downloadLesson); app.use('/downloadCourse', downloadCourse); @@ -41,10 +53,23 @@ app.get('/', (req, res) => { res.send('Welcome to ClassroomIO'); }); +// Start server app.listen(port, () => { console.log(`ClassroomIO Backend listening on port ${port}!`); }); +// Handle uncaught exceptions process.on('uncaughtException', (err) => { - console.error('Uncaught error, err'); + console.error('Uncaught error', err); +}); + +// Error-handling middleware +app.use((error, req, res, next) => { + console.error('Exception error caught:', error); + + // Capture and send the error to Sentry + sentry.captureException(error); + + // Respond with a 500 Internal Server Error + res.status(500).json({ error: 'Internal Server Error' }); }); diff --git a/apps/docs/pages/quickstart/self-hosting.mdx b/apps/docs/pages/quickstart/self-hosting.mdx index ca67baa3..55df5235 100644 --- a/apps/docs/pages/quickstart/self-hosting.mdx +++ b/apps/docs/pages/quickstart/self-hosting.mdx @@ -87,6 +87,7 @@ CLOUDFLARE_ACCESS_KEY="" CLOUDFLARE_ACCOUNT_ID="" CLOUDFLARE_BUCKET_DOMAIN="" CLOUDFLARE_SECRET_ACCESS_KEY="" +SENTRY_DNS="" ``` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1fcbc591..68287825 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,12 @@ importers: '@aws-sdk/lib-storage': specifier: ^3.535.0 version: 3.658.1(@aws-sdk/client-s3@3.658.1) + '@sentry/node': + specifier: ^7.110.1 + version: 7.119.0 + '@sentry/profiling-node': + specifier: ^7.110.1 + version: 7.119.0 '@supabase/supabase-js': specifier: ^2.32.0 version: 2.45.4 @@ -3730,6 +3736,27 @@ packages: localforage: 1.10.0 dev: false + /@sentry/node@7.119.0: + resolution: {integrity: sha512-9PFzN8xS6U0oZCflpVxS2SSIsHkCaj7qYBlsvHj4CTGWfao9ImwrU6+smy4qoG6oxwPfoVb5pOOMb4WpWOvXcQ==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.119.0 + '@sentry/core': 7.119.0 + '@sentry/integrations': 7.119.0 + '@sentry/types': 7.119.0 + '@sentry/utils': 7.119.0 + dev: false + + /@sentry/profiling-node@7.119.0: + resolution: {integrity: sha512-KEJ2kFVWDmg2qi7y24PuSqerlW+iDK4C6pDXpXV6h+GEekUXsnRSAqtKc5H6LJqVGe8ljgFqPy75XIkM1qPBzw==} + engines: {node: '>=8.0.0'} + hasBin: true + requiresBuild: true + dependencies: + detect-libc: 2.0.3 + node-abi: 3.68.0 + dev: false + /@sentry/replay@7.119.0: resolution: {integrity: sha512-BnNsYL+X5I4WCH6wOpY6HQtp4MgVt0NVlhLUsEyrvMUiTs0bPkDBrulsgZQBUKJsbOr3l9nHrFoNVB/0i6WNLA==} engines: {node: '>=12'} @@ -11544,6 +11571,13 @@ packages: - supports-color dev: false + /node-abi@3.68.0: + resolution: {integrity: sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==} + engines: {node: '>=10'} + dependencies: + semver: 7.6.3 + dev: false + /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'}