feat(sentry): Ajoute l'intégration de Sentry pour le suivi des erreurs.

This commit is contained in:
Serreau Jovann
2025-10-16 08:42:01 +02:00
parent c448043b5b
commit 6e6b571243
13 changed files with 157 additions and 16 deletions

1
.env
View File

@@ -76,3 +76,4 @@ CLOUDFLARE_TOKEN=4mqx9d7ynvoeCaXonJA07U19rH8gGhctqp7j2Lch
MAILCOW_KEY=DF0E7E-0FD059-16226F-8ECFF1-E558B3
DEV_URL=https://1fc91cb07736.ngrok-free.app
SENTRY_BACKEND=https://dcf4ed12f5844686f088838f26082bf0@o4510197735948288.ingest.de.sentry.io/4510197737979984

View File

@@ -11,6 +11,7 @@ import {SecurityWall} from './class/SecurityWall'
import {IpWall} from './class/IpWall'
import {ConfirmModal} from './class/ConfirmModal'
import preactCustomElement from './functions/preact'
import * as Sentry from "@sentry/browser";
function script() {
@@ -49,6 +50,26 @@ function full() {
}
});
});
let metaSentry = document.querySelector('meta[name="sentry"]');
if(metaSentry != undefined) {
Sentry.init({
dsn: "https://f134747cc727471fefb197ab5fd4b1b0@o4510197735948288.ingest.de.sentry.io/4510197772320848",
// Setting this option to true will send default PII data to Sentry.
// For example, automatic IP address collection on events
sendDefaultPii: true,
tunnel: "/tunnel",
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration()
],
// Tracing
tracesSampleRate: 1.0, // Capture 100% of the transactions
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0 // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
}
}
document.addEventListener('DOMContentLoaded', ()=>{

View File

@@ -1,6 +1,7 @@
import './app.scss'
import * as Turbo from "@hotwired/turbo"
import {PaymentChaque, PaymentPage, PaymentSepa, PaymentVirement} from "./class/PaymentPage.js";
import * as Sentry from "@sentry/browser";
customElements.define('payment-page',PaymentPage,{extends:'button'})
customElements.define('payment-cheque',PaymentChaque,{extends:'button'})
@@ -9,6 +10,26 @@ customElements.define('payment-virement',PaymentVirement,{extends:'button'})
document.addEventListener('DOMContentLoaded', () => {
let metaSentry = document.querySelector('meta[name="sentry"]');
if(metaSentry != undefined) {
Sentry.init({
dsn: "https://f134747cc727471fefb197ab5fd4b1b0@o4510197735948288.ingest.de.sentry.io/4510197772320848",
// Setting this option to true will send default PII data to Sentry.
// For example, automatic IP address collection on events
sendDefaultPii: true,
tunnel: "/tunnel",
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration()
],
// Tracing
tracesSampleRate: 1.0, // Capture 100% of the transactions
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0 // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
}
function createSvgIconPassword(paths, classes) {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("fill", "none");

BIN
bun.lockb

Binary file not shown.

View File

@@ -38,6 +38,7 @@
"phpoffice/phpspreadsheet": "*",
"phpstan/phpdoc-parser": "^2.2",
"presta/sitemap-bundle": "^4.1",
"sentry/sentry": "*",
"sentry/sentry-symfony": "^5.3",
"setasign/fpdi": "^2.6",
"spatie/mjml-php": "^1.2",

14
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1daefc9419bbfdfa4b4f286a2a26b1b2",
"content-hash": "c30269ac9b27fa9af3a5958c1033684b",
"packages": [
{
"name": "async-aws/core",
@@ -7034,16 +7034,16 @@
},
{
"name": "sentry/sentry",
"version": "4.15.2",
"version": "4.16.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
"reference": "61a2d918e8424b6de4a2e265c15133a00c17db51"
"reference": "c5b086e4235762da175034bc463b0d31cbb38d2e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/61a2d918e8424b6de4a2e265c15133a00c17db51",
"reference": "61a2d918e8424b6de4a2e265c15133a00c17db51",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/c5b086e4235762da175034bc463b0d31cbb38d2e",
"reference": "c5b086e4235762da175034bc463b0d31cbb38d2e",
"shasum": ""
},
"require": {
@@ -7107,7 +7107,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
"source": "https://github.com/getsentry/sentry-php/tree/4.15.2"
"source": "https://github.com/getsentry/sentry-php/tree/4.16.0"
},
"funding": [
{
@@ -7119,7 +7119,7 @@
"type": "custom"
}
],
"time": "2025-09-03T07:23:48+00:00"
"time": "2025-09-22T13:38:03+00:00"
},
{
"name": "sentry/sentry-symfony",

View File

@@ -25,7 +25,7 @@
"@grapesjs/studio-sdk-plugins": "^1.0.28",
"@hotwired/turbo": "^8.0.13",
"@preact/preset-vite": "^2.10.2",
"@sentry/browser": "^9.46.0",
"@sentry/browser": "^10.20.0",
"@tailwindcss/vite": "^4.1.13",
"@usewaypoint/email-builder": "^0.0.8",
"autoprefixer": "^10.4.21",

View File

@@ -5,5 +5,17 @@ use App\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
if($_ENV['APP_ENV'] == "prod") {
\Sentry\init([
'dsn' => $_ENV['SENTRY_DSN'],
// Specify a fixed sample rate
'traces_sample_rate' => 1.0,
// Set a sampling rate for profiling - this is relative to traces_sample_rate
'profiles_sample_rate' => 1.0,
// Enable logs to be sent to Sentry
'enable_logs' => true,
]);
}
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};

View File

@@ -17,7 +17,7 @@ use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
class TutoController extends AbstractController
{
#[Route(path: '/artemis/esyweb/tuto', name: 'artemis_esyweb_tuto', methods: ['GET', 'POST'])]
public function tutos(KernelInterface $kernel,Request $request,UploaderHelper $uploaderHelper,LoggerService $loggerService,EsyWebTutoRepository $esyWebTutoRepository,EntityManagerInterface $entityManager)
public function tutos()
{

View File

@@ -0,0 +1,57 @@
<?php
namespace App\Controller;
use App\Repository\CustomerAdvertPaymentRepository;
use App\Service\Mailer\Mailer;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class TunnelController extends AbstractController
{
#[Route(path: '/tunnel',name: 'tunnels',methods: ['POST'])]
public function tunnelSentry(Request $request, HttpClientInterface $httpClient): Response
{
// Step 1: Get raw request content
$content = $request->getContent();
// Step 2: Parse the first line (DSN) from the request content
$piece = explode("\n", $content)[0];
$header = json_decode($piece, true); // Decode the JSON into an array
// Step 3: Parse the DSN to extract project details
$dns = parse_url($header['dsn']);
$project_id = str_replace("/", "", $dns['path']); // Clean the project ID path
// Step 4: Construct the Sentry envelope URL
$upstream_sentry_url = 'https://' . $dns['host'] . '/api/' . $project_id . '/envelope/';
try {
// Step 5: Forward the request to Sentry's API
$httpClient->request('POST', $upstream_sentry_url, [
'body' => $content // Forward the exact content of the original request
]);
// Return a successful empty response
return $this->json([]);
} catch (\Exception $exception) {
// Step 6: Handle any general exceptions during the request
return $this->json(
['error' => 'Error in Sentry tunnel: ' . $exception->getMessage()],
Response::HTTP_INTERNAL_SERVER_ERROR
);
} catch (TransportExceptionInterface $e) {
// Step 7: Handle any transport-specific exceptions (e.g., network errors)
return $this->json(
['error' => 'Error in Sentry tunnel: ' . $e->getMessage()],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\EventListener;
use Error;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
#[AsEventListener(event: ExceptionEvent::class,method: 'onKernelException')]
class ErrorSubscriber
{
public function onKernelException(ExceptionEvent $event)
{
if($event->getThrowable() instanceof Error) {
if($_ENV['APP_ENV'] == "prod") {
\Sentry\captureException($event);
}
}
}
}

View File

@@ -6,15 +6,19 @@
<title>{{ websiteTitle }} - {% block title %}{% endblock %}</title>
{% if noIndex is defined %}
<meta name="robots" content="noindex, nofollow">
<meta name="robots" content="noindex, nofollow">
{% endif %}
<link rel="icon" type="image/png" href="{{ asset('favicon/favicon-96x96.png') }}" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="{{ asset('favicon/favicon.svg') }}" />
<link rel="shortcut icon" href="{{ asset('favicon/favicon.ico') }}" />
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('favicon/apple-touch-icon.png') }}" />
<meta name="apple-mobile-web-app-title" content="{{ websiteTitle }}" />
<link rel="manifest" href="{{ asset('favicon/site.webmanifest') }}" />
<link rel="icon" type="image/png" href="{{ asset('favicon/favicon-96x96.png') }}" sizes="96x96"/>
<link rel="icon" type="image/svg+xml" href="{{ asset('favicon/favicon.svg') }}"/>
<link rel="shortcut icon" href="{{ asset('favicon/favicon.ico') }}"/>
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('favicon/apple-touch-icon.png') }}"/>
<meta name="apple-mobile-web-app-title" content="{{ websiteTitle }}"/>
<link rel="manifest" href="{{ asset('favicon/site.webmanifest') }}"/>
{{ vite_asset('app.js',[]) }}
{% if app.environment == "prod" %}
<meta name="sentry" content="up">
{% endif %}
</head>
{# Changement ici : fond noir, texte blanc #}
<body class="bg-gray-900 font-sans antialiased text-gray-100">

View File

@@ -48,6 +48,10 @@
}
</style>
<script src="https://signature.esy-web.dev/js/form.js"></script>
{% if app.environment == "prod" %}
<meta name="sentry" content="up">
{% endif %}
</head>
<body class="bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-gray-100">