(frontend) add sentry

In order to monitor the frontend, we are adding
sentry.
This commit is contained in:
Anthony LC
2024-11-15 14:34:45 +01:00
committed by Anthony LC
parent 5b1745f991
commit e9ac393a8f
7 changed files with 1114 additions and 138 deletions

View File

@@ -17,6 +17,7 @@ and this project adheres to
- ✨(backend) whitelist pod's IP address #443
- ✨(backend) config endpoint #425
- ✨(frontend) config endpoint #424
- ✨(frontend) add sentry #424
## Changed

View File

@@ -1,5 +1,19 @@
import { expect, test } from '@playwright/test';
const config = {
COLLABORATION_SERVER_URL: 'ws://localhost:4444',
ENVIRONMENT: 'development',
FRONTEND_THEME: 'dsfr',
MEDIA_BASE_URL: 'http://localhost:8083',
LANGUAGES: [
['en-us', 'English'],
['fr-fr', 'French'],
['de-de', 'German'],
],
LANGUAGE_CODE: 'en-us',
SENTRY_DSN: null,
};
test.describe('Config', () => {
test('it checks the config api is called', async ({ page }) => {
const responsePromise = page.waitForResponse(
@@ -12,18 +26,34 @@ test.describe('Config', () => {
const response = await responsePromise;
expect(response.ok()).toBeTruthy();
expect(await response.json()).toStrictEqual({
COLLABORATION_SERVER_URL: 'ws://localhost:4444',
ENVIRONMENT: 'development',
FRONTEND_THEME: 'dsfr',
MEDIA_BASE_URL: 'http://localhost:8083',
LANGUAGES: [
['en-us', 'English'],
['fr-fr', 'French'],
['de-de', 'German'],
],
LANGUAGE_CODE: 'en-us',
SENTRY_DSN: null,
expect(await response.json()).toStrictEqual(config);
});
test('it checks that sentry is trying to init from config endpoint', async ({
page,
}) => {
await page.route('**/api/v1.0/config/', async (route) => {
const request = route.request();
if (request.method().includes('GET')) {
await route.fulfill({
json: {
...config,
SENTRY_DSN: 'https://sentry.io/123',
},
});
} else {
await route.continue();
}
});
const invalidMsg = 'Invalid Sentry Dsn: https://sentry.io/123';
const consoleMessage = page.waitForEvent('console', {
timeout: 5000,
predicate: (msg) => msg.text().includes(invalidMsg),
});
await page.goto('/');
expect((await consoleMessage).text()).toContain(invalidMsg);
});
});

View File

@@ -21,6 +21,7 @@
"@gouvfr-lasuite/integration": "1.0.2",
"@hocuspocus/provider": "2.13.7",
"@openfun/cunningham-react": "2.9.4",
"@sentry/nextjs": "8.39.0",
"@tanstack/react-query": "5.60.5",
"i18next": "23.16.5",
"i18next-browser-languagedetector": "8.0.0",

View File

@@ -13,6 +13,12 @@ jest.mock('next/router', () => ({
},
}));
jest.mock('@sentry/nextjs', () => ({
captureException: jest.fn(),
captureMessage: jest.fn(),
setUser: jest.fn(),
}));
describe('Page', () => {
it('checks Page rendering', () => {
render(<Page />, { wrapper: AppWrapper });

View File

@@ -1,9 +1,20 @@
import { PropsWithChildren } from 'react';
import { PropsWithChildren, useEffect } from 'react';
import { useSentryStore } from '@/stores/useSentryStore';
import { useConfig } from './api/useConfig';
export const ConfigProvider = ({ children }: PropsWithChildren) => {
useConfig();
const { data: conf } = useConfig();
const { setSentry } = useSentryStore();
useEffect(() => {
if (!conf?.SENTRY_DSN) {
return;
}
setSentry(conf.SENTRY_DSN, conf.ENVIRONMENT);
}, [conf?.SENTRY_DSN, conf?.ENVIRONMENT, setSentry]);
return children;
};

View File

@@ -0,0 +1,32 @@
import * as Sentry from '@sentry/nextjs';
import type { Client } from '@sentry/types';
import { create } from 'zustand';
import packageJson from '../../package.json';
interface SentryState {
sentry?: Client;
setSentry: (dsn?: string, environment?: string) => void;
}
export const useSentryStore = create<SentryState>((set, get) => ({
sentry: undefined,
setSentry: (dsn, environment) => {
const sentry = get().sentry;
if (sentry) {
return;
}
set({
sentry: Sentry.init({
dsn,
environment,
integrations: [Sentry.replayIntegration()],
release: packageJson.version,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
tracesSampleRate: 1.0,
}),
});
},
}));

File diff suppressed because it is too large Load Diff