Skip to content

Commit 21b789f

Browse files
authored
fix(sentry): sentry information now coming from bff (#269)
1 parent 7ce45e3 commit 21b789f

File tree

9 files changed

+119
-37
lines changed

9 files changed

+119
-37
lines changed

.env.template

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
VITE_SENTRY_ENVIRONMENT=
21
# Sentry DSN configuration, no need to be set for local setup
32
# Frontend:
43
SENTRY_ORG=
54
SENTRY_PROJECT=
6-
VITE_SENTRY_DSN=
5+
FRONTEND_SENTRY_DSN=
6+
FRONTEND_SENTRY_ENVIRONMENT=
77
# BFF:
88
BFF_SENTRY_DSN=
99
DYNATRACE_SCRIPT_URL=

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
<script type="module" src="/src/mount.ts"></script>
1414
</body>
1515

16-
</html>
16+
</html>

package-lock.json

Lines changed: 23 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
"npm": "^11.0.0"
88
},
99
"scripts": {
10-
"dev": "node --loader ts-node/esm ./server.ts --local-dev",
10+
"dev": "tsx ./server.ts --local-dev",
1111
"start": "node dist/server.js",
12-
"build": "tsc && npm run build:server && vite build",
12+
"build": "npm run build:server && npm run build:client",
13+
"build:client": "vite build",
1314
"build:server": "tsc -p tsconfig.server.json",
1415
"lint": "eslint ./src --report-unused-disable-directives --max-warnings 0",
1516
"lint:fix": "eslint ./src --fix",
@@ -91,7 +92,7 @@
9192
"fastify-tsconfig": "^3.0.0",
9293
"globals": "^16.0.0",
9394
"prettier": "^3.5.3",
94-
"ts-node": "^10.9.2",
95+
"tsx": "^4.20.5",
9596
"typescript": "^5.7.3",
9697
"typescript-eslint": "^8.26.1",
9798
"vite": "^6.3.4",

server.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if (!process.env.BFF_SENTRY_DSN || process.env.BFF_SENTRY_DSN.trim() === '') {
2424
} else {
2525
Sentry.init({
2626
dsn: process.env.BFF_SENTRY_DSN,
27-
environment: process.env.VITE_SENTRY_ENVIRONMENT,
27+
environment: process.env.FRONTEND_SENTRY_ENVIRONMENT,
2828
beforeSend(event) {
2929
if (event.request && event.request.cookies) {
3030
event.request.cookies = Object.keys(event.request.cookies).reduce((acc, key) => {
@@ -72,12 +72,12 @@ await fastify.register(envPlugin);
7272

7373
let sentryHost = '';
7474
// @ts-ignore
75-
if (fastify.config.VITE_SENTRY_DSN && fastify.config.VITE_SENTRY_DSN.length > 0) {
75+
if (fastify.config.FRONTEND_SENTRY_DSN && fastify.config.FRONTEND_SENTRY_DSN.length > 0) {
7676
try {
7777
// @ts-ignore
78-
sentryHost = new URL(fastify.config.VITE_SENTRY_DSN).hostname;
78+
sentryHost = new URL(fastify.config.FRONTEND_SENTRY_DSN).hostname;
7979
} catch {
80-
console.log('VITE_SENTRY_DSN is not a valid URL');
80+
console.log('FRONTEND_SENTRY_DSN is not a valid URL');
8181
sentryHost = '';
8282
}
8383
}
@@ -95,7 +95,9 @@ fastify.register(helmet, {
9595
contentSecurityPolicy: {
9696
directives: {
9797
'connect-src': ["'self'", 'sdk.openui5.org', sentryHost, dynatraceOrigin],
98-
'script-src': isLocalDev ? ["'self'", "'unsafe-inline'", dynatraceOrigin] : ["'self'", dynatraceOrigin],
98+
'script-src': isLocalDev
99+
? ["'self'", "'unsafe-inline'", "'unsafe-eval'", sentryHost, dynatraceOrigin]
100+
: ["'self'", sentryHost, dynatraceOrigin],
99101
// @ts-ignore
100102
'frame-ancestors': [...fastify.config.FRAME_ANCESTORS.split(',')],
101103
},
@@ -112,6 +114,15 @@ await fastify.register(FastifyVite, {
112114
spa: true,
113115
});
114116

117+
fastify.get('/sentry', function (req, reply) {
118+
return reply.send({
119+
// @ts-ignore
120+
FRONTEND_SENTRY_DSN: fastify.config.FRONTEND_SENTRY_DSN,
121+
// @ts-ignore
122+
FRONTEND_SENTRY_ENVIRONMENT: fastify.config.FRONTEND_SENTRY_ENVIRONMENT,
123+
});
124+
});
125+
115126
// @ts-ignore
116127
fastify.get('/', function (req, reply) {
117128
return reply.html();

server/config/env.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ const schema = {
3030
FEEDBACK_URL_LINK: { type: 'string' },
3131
FRAME_ANCESTORS: { type: 'string' },
3232
BFF_SENTRY_DSN: { type: 'string' },
33-
VITE_SENTRY_DSN: { type: 'string' },
34-
VITE_SENTRY_ENVIRONMENT: { type: 'string' },
33+
FRONTEND_SENTRY_DSN: { type: 'string' },
34+
FRONTEND_SENTRY_ENVIRONMENT: { type: 'string' },
3535

3636
// System variables
3737
NODE_ENV: { type: 'string', enum: ['development', 'production'] },

src/lib/sentry.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import * as Sentry from '@sentry/react';
2+
import React from 'react';
3+
import { Routes, useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from 'react-router-dom';
4+
5+
// Define proper typing for Sentry configuration
6+
interface SentryConfig {
7+
FRONTEND_SENTRY_DSN: string;
8+
FRONTEND_SENTRY_ENVIRONMENT: string;
9+
}
10+
11+
// Validate sentryConfig format
12+
function isValidSentryConfig(config: unknown): config is SentryConfig {
13+
if (typeof config !== 'object' || config === null) {
14+
return false;
15+
}
16+
17+
const typedConfig = config as Record<string, unknown>;
18+
return (
19+
typeof typedConfig.FRONTEND_SENTRY_DSN === 'string' &&
20+
typedConfig.FRONTEND_SENTRY_DSN.length > 0 &&
21+
typeof typedConfig.FRONTEND_SENTRY_ENVIRONMENT === 'string' &&
22+
typedConfig.FRONTEND_SENTRY_ENVIRONMENT.length > 0
23+
);
24+
}
25+
26+
// Fetch Sentry configuration from server
27+
async function fetchSentryConfig(): Promise<unknown> {
28+
try {
29+
const response = await fetch('/sentry');
30+
if (!response.ok) {
31+
throw new Error(`HTTP error! status: ${response.status}`);
32+
}
33+
return await response.json();
34+
} catch (error) {
35+
console.warn('Failed to fetch Sentry configuration:', error);
36+
return null;
37+
}
38+
}
39+
40+
// Initialize Sentry and return the wrapped Routes component
41+
export async function initializeSentry(): Promise<typeof Routes> {
42+
const sentryConfig = await fetchSentryConfig();
43+
44+
if (!isValidSentryConfig(sentryConfig)) {
45+
console.warn('Invalid or missing Sentry configuration, continuing without Sentry integration');
46+
return Routes;
47+
}
48+
49+
// Initialize Sentry with valid configuration
50+
Sentry.init({
51+
dsn: sentryConfig.FRONTEND_SENTRY_DSN,
52+
environment: sentryConfig.FRONTEND_SENTRY_ENVIRONMENT,
53+
integrations: [
54+
Sentry.reactRouterV7BrowserTracingIntegration({
55+
useEffect: React.useEffect,
56+
useLocation,
57+
useNavigationType,
58+
createRoutesFromChildren,
59+
matchRoutes,
60+
}),
61+
],
62+
});
63+
64+
return Sentry.withSentryReactRouterV7Routing(Routes);
65+
}

src/mount.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,11 @@
11
import { createRoot } from 'react-dom/client';
22
import { createApp } from './main.tsx';
3-
import * as Sentry from '@sentry/react';
4-
import React from 'react';
5-
import { Routes, useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from 'react-router-dom';
3+
import { initializeSentry } from './lib/sentry.ts';
64

7-
let sentryRoutes = Routes;
8-
if (import.meta.env.VITE_SENTRY_DSN && import.meta.env.VITE_SENTRY_DSN.length > 0) {
9-
Sentry.init({
10-
dsn: import.meta.env.VITE_SENTRY_DSN,
11-
environment: import.meta.env.VITE_SENTRY_ENVIRONMENT,
12-
integrations: [
13-
Sentry.reactRouterV7BrowserTracingIntegration({
14-
useEffect: React.useEffect,
15-
useLocation,
16-
useNavigationType,
17-
createRoutesFromChildren,
18-
matchRoutes,
19-
}),
20-
],
21-
});
5+
// Initialize Sentry and get the Routes component (with or without Sentry integration)
6+
const SentryRoutes = await initializeSentry();
227

23-
sentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes);
24-
}
25-
26-
export const SentryRoutes = sentryRoutes;
8+
export { SentryRoutes };
279

2810
const root = createRoot(document.getElementById('root')!);
2911
root.render(createApp());

vite.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default defineConfig({
1414
sentryVitePlugin({
1515
org: process.env.SENTRY_ORG,
1616
project: process.env.SENTRY_PROJECT,
17+
telemetry: false,
1718
reactComponentAnnotation: {
1819
enabled: true,
1920
},
@@ -22,5 +23,6 @@ export default defineConfig({
2223

2324
build: {
2425
sourcemap: true,
26+
target: 'esnext', // Support top-level await
2527
},
2628
});

0 commit comments

Comments
 (0)