diff --git a/backend/src/health.controller.spec.ts b/backend/src/health.controller.spec.ts index c8c2e1e..8e9f9eb 100644 --- a/backend/src/health.controller.spec.ts +++ b/backend/src/health.controller.spec.ts @@ -1,8 +1,13 @@ import { CACHE_MANAGER } from "@nestjs/cache-manager"; import { Test, TestingModule } from "@nestjs/testing"; +import * as Sentry from "@sentry/nestjs"; import { DatabaseService } from "./database/database.service"; import { HealthController } from "./health.controller"; +jest.mock("@sentry/nestjs", () => ({ + getClient: jest.fn(), +})); + describe("HealthController", () => { let controller: HealthController; @@ -37,10 +42,15 @@ describe("HealthController", () => { it("should return ok if database and redis are connected", async () => { mockDb.execute.mockResolvedValue([]); mockCacheManager.set.mockResolvedValue(undefined); + (Sentry.getClient as jest.Mock).mockReturnValue({ + getOptions: () => ({ dsn: "http://dsn" }), + }); + const result = await controller.check(); expect(result.status).toBe("ok"); expect(result.database).toBe("connected"); expect(result.redis).toBe("connected"); + expect(result.sentry).toBe("active"); }); it("should return error if database is disconnected", async () => { @@ -62,4 +72,19 @@ describe("HealthController", () => { expect(result.redis).toBe("disconnected"); expect(result.redisError).toBe("Redis Error"); }); + + it("should return sentry disabled if client or dsn is missing", async () => { + mockDb.execute.mockResolvedValue([]); + mockCacheManager.set.mockResolvedValue(undefined); + (Sentry.getClient as jest.Mock).mockReturnValue(undefined); + + const result = await controller.check(); + expect(result.sentry).toBe("disabled"); + + (Sentry.getClient as jest.Mock).mockReturnValue({ + getOptions: () => ({ dsn: undefined }), + }); + const result2 = await controller.check(); + expect(result2.sentry).toBe("disabled"); + }); }); diff --git a/backend/src/health.controller.ts b/backend/src/health.controller.ts index d049e87..fbf0617 100644 --- a/backend/src/health.controller.ts +++ b/backend/src/health.controller.ts @@ -1,5 +1,6 @@ import { CACHE_MANAGER } from "@nestjs/cache-manager"; import { Controller, Get, Inject } from "@nestjs/common"; +import * as Sentry from "@sentry/nestjs"; import type { Cache } from "cache-manager"; import { sql } from "drizzle-orm"; import { DatabaseService } from "./database/database.service"; @@ -39,6 +40,14 @@ export class HealthController { health.redisError = error.message; } + // Check Sentry status + const sentryClient = Sentry.getClient(); + if (sentryClient?.getOptions().dsn) { + health.sentry = "active"; + } else { + health.sentry = "disabled"; + } + return health; } } diff --git a/backend/src/main.ts b/backend/src/main.ts index 8e6b3f9..85fd7f1 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -19,22 +19,35 @@ async function bootstrap() { const sentryDsn = configService.get("SENTRY_DSN"); if (sentryDsn) { - Sentry.init({ - dsn: sentryDsn, - integrations: [nodeProfilingIntegration()], - tracesSampleRate: 1.0, - profilesSampleRate: 1.0, - sendDefaultPii: false, // RGPD - beforeSend(event) { - // Hachage de l'IP utilisateur pour Sentry si elle est présente - if (event.user?.ip_address) { - event.user.ip_address = createHash("sha256") - .update(event.user.ip_address) - .digest("hex"); - } - return event; - }, - }); + try { + Sentry.init({ + dsn: sentryDsn, + integrations: [Sentry.nestIntegration(), nodeProfilingIntegration()], + tracesSampleRate: 1.0, + profilesSampleRate: 1.0, + sendDefaultPii: false, // RGPD + beforeSend(event) { + // Hachage de l'IP utilisateur pour Sentry si elle est présente + if (event.user?.ip_address) { + event.user.ip_address = createHash("sha256") + .update(event.user.ip_address) + .digest("hex"); + } + return event; + }, + }); + + const client = Sentry.getClient(); + if (client?.getOptions().dsn) { + logger.log("Sentry is initialized and connection is active"); + } else { + logger.warn("Sentry initialized but DSN is missing"); + } + } catch (error) { + logger.error(`Failed to initialize Sentry: ${error.message}`); + } + } else { + logger.warn("Sentry is disabled (SENTRY_DSN not configured)"); } // Sécurité