145 lines
3.8 KiB
TypeScript
145 lines
3.8 KiB
TypeScript
/**
|
|
* FIX #20: Configuration Sentry pour error tracking
|
|
* - Intégration avec le logger structuré
|
|
* - Capture automatique des erreurs React
|
|
* - Enrichissement avec contexte (request_id, user_id, etc.)
|
|
*/
|
|
|
|
import * as Sentry from '@sentry/react';
|
|
import { logger, getLogContext } from '@/utils/logger';
|
|
|
|
/**
|
|
* Initialiser Sentry avec configuration
|
|
*/
|
|
export function initSentry(): void {
|
|
const dsn = import.meta.env.VITE_SENTRY_DSN;
|
|
const environment = import.meta.env.MODE || 'development';
|
|
const enabled = import.meta.env.PROD && dsn; // Activer uniquement en production si DSN configuré
|
|
|
|
if (!enabled) {
|
|
if (environment !== 'development' && !dsn) {
|
|
logger.debug('[Sentry] Error tracking disabled', {
|
|
reason: 'DSN not configured',
|
|
environment,
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
|
|
Sentry.init({
|
|
dsn,
|
|
environment,
|
|
integrations: [
|
|
Sentry.browserTracingIntegration(),
|
|
Sentry.replayIntegration({
|
|
maskAllText: true,
|
|
blockAllMedia: true,
|
|
}),
|
|
],
|
|
// Performance Monitoring
|
|
tracesSampleRate: environment === 'production' ? 0.1 : 1.0, // 10% en prod, 100% en dev
|
|
// Session Replay
|
|
replaysSessionSampleRate: 0.1, // 10% des sessions
|
|
replaysOnErrorSampleRate: 1.0, // 100% des sessions avec erreur
|
|
// Filtrage des erreurs
|
|
beforeSend(event, hint) {
|
|
// Enrichir avec le contexte du logger
|
|
const logContext = getLogContext();
|
|
if (logContext.request_id) {
|
|
event.tags = { ...event.tags, request_id: logContext.request_id };
|
|
}
|
|
if (logContext.user_id) {
|
|
event.user = { ...event.user, id: String(logContext.user_id) };
|
|
}
|
|
|
|
// Logger l'erreur avec le logger structuré
|
|
const error = hint.originalException;
|
|
logger.error('[Sentry] Error captured', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
sentry_event_id: event.event_id,
|
|
...logContext,
|
|
});
|
|
|
|
return event;
|
|
},
|
|
// Ignorer certaines erreurs
|
|
ignoreErrors: [
|
|
// Erreurs réseau courantes
|
|
'NetworkError',
|
|
'Network request failed',
|
|
'Failed to fetch',
|
|
// Erreurs de résolution DNS
|
|
'Resolving timed out',
|
|
// Erreurs de CORS
|
|
'CORS',
|
|
// Erreurs de script tiers
|
|
'Script error',
|
|
'Non-Error promise rejection captured',
|
|
],
|
|
// Ignorer certaines URLs
|
|
denyUrls: [
|
|
// Extensions de navigateur
|
|
/extensions\//i,
|
|
/^chrome:\/\//i,
|
|
/^chrome-extension:\/\//i,
|
|
// Scripts tiers
|
|
/cdn\./i,
|
|
],
|
|
});
|
|
|
|
logger.info('[Sentry] Error tracking initialized', {
|
|
environment,
|
|
dsn_configured: !!dsn,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Enrichir le contexte Sentry avec les informations du logger
|
|
*/
|
|
export function setSentryContext(context: Record<string, unknown>): void {
|
|
Sentry.setContext('application', context);
|
|
}
|
|
|
|
/**
|
|
* Capturer une exception manuellement
|
|
*/
|
|
export function captureException(
|
|
error: Error,
|
|
context?: Record<string, unknown>,
|
|
): string {
|
|
if (context) {
|
|
Sentry.setContext('custom', context);
|
|
}
|
|
|
|
// Enrichir avec le contexte du logger
|
|
const logContext = getLogContext();
|
|
if (logContext.request_id) {
|
|
Sentry.setTag('request_id', String(logContext.request_id));
|
|
}
|
|
if (logContext.user_id) {
|
|
Sentry.setUser({ id: String(logContext.user_id) });
|
|
}
|
|
|
|
return Sentry.captureException(error);
|
|
}
|
|
|
|
/**
|
|
* Capturer un message personnalisé
|
|
*/
|
|
export function captureMessage(
|
|
message: string,
|
|
level: Sentry.SeverityLevel = 'info',
|
|
context?: Record<string, unknown>,
|
|
): string {
|
|
if (context) {
|
|
Sentry.setContext('custom', context);
|
|
}
|
|
|
|
// Enrichir avec le contexte du logger
|
|
const logContext = getLogContext();
|
|
if (logContext.request_id) {
|
|
Sentry.setTag('request_id', String(logContext.request_id));
|
|
}
|
|
|
|
return Sentry.captureMessage(message, level);
|
|
}
|