Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 25 additions & 34 deletions forge/forge.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const cookie = require('@fastify/cookie')
const csrf = require('@fastify/csrf-protection')
const helmet = require('@fastify/helmet')
const { ProfilingIntegration } = require('@sentry/profiling-node')
const Sentry = require('@sentry/node')
const { nodeProfilingIntegration } = require('@sentry/profiling-node')
const fastify = require('fastify')

const auditLog = require('./auditLog')
Expand Down Expand Up @@ -140,49 +141,18 @@ module.exports = async (options = {}) => {
}
}
}
const server = fastify({
forceCloseConnections: true,
bodyLimit: 10485760, // 10mb max payload size, set to allow for VERY large flows
routerOptions: {
maxParamLength: 500
},
trustProxy: true,
logger: loggerConfig,
// Increase the default timeout
pluginTimeout: 20000
})

if (runtimeConfig.telemetry.backend?.prometheus?.enabled) {
const metricsPlugin = require('fastify-metrics')
await server.register(metricsPlugin, { endpoint: '/metrics' })
}

if (runtimeConfig.telemetry.backend?.sentry?.dsn) {
const environment = process.env.SENTRY_ENV ?? (process.env.NODE_ENV ?? 'unknown')
const sentrySampleRate = environment === 'production' ? 0.1 : 0.5
server.register(require('@immobiliarelabs/fastify-sentry'), {
Sentry.init({
dsn: runtimeConfig.telemetry.backend.sentry.dsn,
sendClientReports: true,
environment,
release: `flowfuse@${runtimeConfig.version}`,
profilesSampleRate: sentrySampleRate, // relative to output from tracesSampler
integrations: [
new ProfilingIntegration()
nodeProfilingIntegration()
],
extractUserData (request) {
const user = request.session?.User || request.user
if (!user) {
return {}
}
const extractedUser = {
id: user.hashid,
username: user.username,
email: user.email,
name: user.name
}

return extractedUser
},
tracesSampler: (samplingContext) => {
// Adjust sample rates for routes with high volumes, sorted descending by volume

Expand Down Expand Up @@ -221,6 +191,27 @@ module.exports = async (options = {}) => {
})
}

const server = fastify({
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sentry.init() is moved to before fastify() because Sentry v10 uses OpenTelemetry to instrument Node.js modules at startup. Calling it after fastify() meant those patches were never applied and errors weren't captured.

forceCloseConnections: true,
bodyLimit: 10485760, // 10mb max payload size, set to allow for VERY large flows
routerOptions: {
maxParamLength: 500
},
trustProxy: true,
logger: loggerConfig,
// Increase the default timeout
pluginTimeout: 20000
})

if (runtimeConfig.telemetry.backend?.prometheus?.enabled) {
const metricsPlugin = require('fastify-metrics')
await server.register(metricsPlugin, { endpoint: '/metrics' })
}

if (runtimeConfig.telemetry.backend?.sentry?.dsn) {
Sentry.setupFastifyErrorHandler(server)
}

server.addHook('onError', async (request, reply, error) => {
// Useful for debugging when a route goes wrong
// console.error(error.stack)
Expand Down
4 changes: 4 additions & 0 deletions forge/routes/auth/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const Sentry = require('@sentry/node')

/**
* Routes related to session handling, login/out etc
*
Expand Down Expand Up @@ -72,6 +74,7 @@ async function init (app, opts) {
const mfaMissing = request.session.User.mfa_enabled && !request.session.mfa_verified

if (emailVerified && passwordNotExpired && !suspended && !mfaMissing) {
Sentry.setUser({ id: request.session.User.hashid, username: request.session.User.username, email: request.session.User.email, name: request.session.User.name })
return
}
if (request.routeOptions.config.allowAnonymous) {
Expand Down Expand Up @@ -116,6 +119,7 @@ async function init (app, opts) {
reply.code(401).send({ code: 'unauthorized', error: 'unauthorized' })
return
}
Sentry.setUser({ id: request.session.User.hashid, username: request.session.User.username, email: request.session.User.email, name: request.session.User.name })
if (accessToken.name) {
// Temp hack to give token full user scope
delete request.session.scope
Expand Down
11 changes: 4 additions & 7 deletions frontend/src/services/error-tracking.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {
BrowserTracing,
Replay,
browserTracingIntegration,
init,
vueRouterInstrumentation
replayIntegration
} from '@sentry/vue'

export const setupSentry = (app, router) => {
Expand All @@ -16,10 +15,8 @@ export const setupSentry = (app, router) => {
app,
dsn,
integrations: [
new BrowserTracing({
routingInstrumentation: vueRouterInstrumentation(router)
}),
new Replay()
browserTracingIntegration({ router }),
replayIntegration()
],
sendClientReports: true,

Expand Down
Loading
Loading