added glitchtip using sentry sdk

This commit is contained in:
Codex Agent
2025-12-19 10:13:30 +01:00
parent 53ec427e6e
commit 778ffc8bb9
13 changed files with 1574 additions and 58 deletions

View File

@@ -20,6 +20,17 @@ LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug LOG_LEVEL=debug
SENTRY_LARAVEL_DSN=
SENTRY_ENVIRONMENT=local
SENTRY_TRACES_SAMPLE_RATE=0.0
SENTRY_PROFILES_SAMPLE_RATE=0.0
SENTRY_RELEASE=
VITE_SENTRY_DSN=
VITE_SENTRY_ENV=local
VITE_SENTRY_TRACES_SAMPLE_RATE=0.05
VITE_SENTRY_RELEASE=
DB_CONNECTION=sqlite DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1 # DB_HOST=127.0.0.1
# DB_PORT=3306 # DB_PORT=3306

View File

@@ -10,9 +10,12 @@ use Illuminate\Http\Client\ConnectionException as HttpClientConnectionException;
use Illuminate\Queue\InvalidQueueException; use Illuminate\Queue\InvalidQueueException;
use Illuminate\Queue\MaxAttemptsExceededException; use Illuminate\Queue\MaxAttemptsExceededException;
use Illuminate\Routing\Exceptions\InvalidSignatureException; use Illuminate\Routing\Exceptions\InvalidSignatureException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemException;
use PDOException; use PDOException;
use Sentry\State\Scope;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Throwable; use Throwable;
class Handler extends ExceptionHandler class Handler extends ExceptionHandler
@@ -34,7 +37,17 @@ class Handler extends ExceptionHandler
public function register(): void public function register(): void
{ {
$this->reportable(function (Throwable $e) { $this->reportable(function (Throwable $e) {
// if ($this->shouldSkipSentry($e)) {
return;
}
if (! app()->bound('sentry') || empty(config('sentry.dsn'))) {
return;
}
$this->configureSentryScope();
app('sentry')->captureException($e);
}); });
} }
@@ -90,6 +103,58 @@ class Handler extends ExceptionHandler
return parent::render($request, $e); return parent::render($request, $e);
} }
private function configureSentryScope(): void
{
\Sentry\configureScope(function (Scope $scope): void {
$user = Auth::user();
if ($user) {
$userData = [
'id' => (string) $user->getAuthIdentifier(),
];
if (! empty($user->email)) {
$userData['email'] = $user->email;
}
if (! empty($user->username)) {
$userData['username'] = $user->username;
}
$scope->setUser($userData);
if (! empty($user->tenant_id)) {
$scope->setTag('tenant_id', (string) $user->tenant_id);
}
if (! empty($user->role)) {
$scope->setTag('user_role', $user->role);
}
}
});
}
private function shouldSkipSentry(Throwable $throwable): bool
{
if ($throwable instanceof ValidationException) {
return true;
}
$status = null;
if ($this->isHttpException($throwable)) {
$status = $this->toHttpException($throwable)->getStatusCode();
} elseif ($throwable instanceof HttpExceptionInterface) {
$status = $throwable->getStatusCode();
}
if (is_int($status) && $status < 500 && $status !== 429) {
return true;
}
return false;
}
private function buildGenericMessage(int $status): string private function buildGenericMessage(int $status): string
{ {
if ($status >= 500) { if ($status >= 500) {

View File

@@ -20,6 +20,7 @@
"laravel/wayfinder": "^0.1.9", "laravel/wayfinder": "^0.1.9",
"league/commonmark": "^2.7", "league/commonmark": "^2.7",
"minishlink/web-push": "*", "minishlink/web-push": "*",
"sentry/sentry-laravel": "*",
"simplesoftwareio/simple-qrcode": "^4.2", "simplesoftwareio/simple-qrcode": "^4.2",
"spatie/laravel-translatable": "^6.11", "spatie/laravel-translatable": "^6.11",
"staudenmeir/belongs-to-through": "^2.17", "staudenmeir/belongs-to-through": "^2.17",

477
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "cc438475a49544b724572f159f62f34b", "content-hash": "c1a772e5fe6f8d5c92fdbbea232f9f78",
"packages": [ "packages": [
{ {
"name": "anourvalar/eloquent-serialize", "name": "anourvalar/eloquent-serialize",
@@ -2390,6 +2390,66 @@
}, },
"time": "2025-11-26T23:07:12+00:00" "time": "2025-11-26T23:07:12+00:00"
}, },
{
"name": "jean85/pretty-package-versions",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
"shasum": ""
},
"require": {
"composer-runtime-api": "^2.1.0",
"php": "^7.4|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.2",
"jean85/composer-provided-replaced-stub-package": "^1.0",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^7.5|^8.5|^9.6",
"rector/rector": "^2.0",
"vimeo/psalm": "^4.3 || ^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Jean85\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alessandro Lai",
"email": "alessandro.lai85@gmail.com"
}
],
"description": "A library to get pretty versions strings of installed dependencies",
"keywords": [
"composer",
"package",
"release",
"versions"
],
"support": {
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
},
"time": "2025-03-19T14:43:43+00:00"
},
{ {
"name": "kirschbaum-development/eloquent-power-joins", "name": "kirschbaum-development/eloquent-power-joins",
"version": "4.2.10", "version": "4.2.10",
@@ -4733,6 +4793,84 @@
], ],
"time": "2025-11-20T02:34:59+00:00" "time": "2025-11-20T02:34:59+00:00"
}, },
{
"name": "nyholm/psr7",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/Nyholm/psr7.git",
"reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
"reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
"shasum": ""
},
"require": {
"php": ">=7.2",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.1 || ^2.0"
},
"provide": {
"php-http/message-factory-implementation": "1.0",
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"http-interop/http-factory-tests": "^0.9",
"php-http/message-factory": "^1.0",
"php-http/psr7-integration-tests": "^1.0",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.4",
"symfony/error-handler": "^4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.8-dev"
}
},
"autoload": {
"psr-4": {
"Nyholm\\Psr7\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com"
},
{
"name": "Martijn van der Ven",
"email": "martijn@vanderven.se"
}
],
"description": "A fast PHP7 implementation of PSR-7",
"homepage": "https://tnyholm.se",
"keywords": [
"psr-17",
"psr-7"
],
"support": {
"issues": "https://github.com/Nyholm/psr7/issues",
"source": "https://github.com/Nyholm/psr7/tree/1.8.2"
},
"funding": [
{
"url": "https://github.com/Zegnat",
"type": "github"
},
{
"url": "https://github.com/nyholm",
"type": "github"
}
],
"time": "2024-09-09T07:06:30+00:00"
},
{ {
"name": "openspout/openspout", "name": "openspout/openspout",
"version": "v4.32.0", "version": "v4.32.0",
@@ -6357,6 +6495,184 @@
], ],
"time": "2022-12-17T21:53:22+00:00" "time": "2022-12-17T21:53:22+00:00"
}, },
{
"name": "sentry/sentry",
"version": "4.19.1",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
"reference": "1c21d60bebe67c0122335bd3fe977990435af0a3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/1c21d60bebe67c0122335bd3fe977990435af0a3",
"reference": "1c21d60bebe67c0122335bd3fe977990435af0a3",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
"jean85/pretty-package-versions": "^1.5|^2.0.4",
"php": "^7.2|^8.0",
"psr/log": "^1.0|^2.0|^3.0",
"symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0|^8.0"
},
"conflict": {
"raven/raven": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.4",
"guzzlehttp/promises": "^2.0.3",
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
"monolog/monolog": "^1.6|^2.0|^3.0",
"phpbench/phpbench": "^1.0",
"phpstan/phpstan": "^1.3",
"phpunit/phpunit": "^8.5|^9.6",
"vimeo/psalm": "^4.17"
},
"suggest": {
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
},
"type": "library",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Sentry\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sentry",
"email": "accounts@sentry.io"
}
],
"description": "PHP SDK for Sentry (http://sentry.io)",
"homepage": "http://sentry.io",
"keywords": [
"crash-reporting",
"crash-reports",
"error-handler",
"error-monitoring",
"log",
"logging",
"profiling",
"sentry",
"tracing"
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
"source": "https://github.com/getsentry/sentry-php/tree/4.19.1"
},
"funding": [
{
"url": "https://sentry.io/",
"type": "custom"
},
{
"url": "https://sentry.io/pricing/",
"type": "custom"
}
],
"time": "2025-12-02T15:57:41+00:00"
},
{
"name": "sentry/sentry-laravel",
"version": "4.20.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
"reference": "95f2542ee1ebc993529b63f5c8543184abd00650"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/95f2542ee1ebc993529b63f5c8543184abd00650",
"reference": "95f2542ee1ebc993529b63f5c8543184abd00650",
"shasum": ""
},
"require": {
"illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0",
"nyholm/psr7": "^1.0",
"php": "^7.2 | ^8.0",
"sentry/sentry": "^4.19.0",
"symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.11",
"guzzlehttp/guzzle": "^7.2",
"laravel/folio": "^1.1",
"laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0",
"laravel/pennant": "^1.0",
"livewire/livewire": "^2.0 | ^3.0",
"mockery/mockery": "^1.3",
"orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8.4 | ^9.3 | ^10.4 | ^11.5"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Sentry": "Sentry\\Laravel\\Facade"
},
"providers": [
"Sentry\\Laravel\\ServiceProvider",
"Sentry\\Laravel\\Tracing\\ServiceProvider"
]
}
},
"autoload": {
"psr-0": {
"Sentry\\Laravel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sentry",
"email": "accounts@sentry.io"
}
],
"description": "Laravel SDK for Sentry (https://sentry.io)",
"homepage": "https://sentry.io",
"keywords": [
"crash-reporting",
"crash-reports",
"error-handler",
"error-monitoring",
"laravel",
"log",
"logging",
"profiling",
"sentry",
"tracing"
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
"source": "https://github.com/getsentry/sentry-laravel/tree/4.20.0"
},
"funding": [
{
"url": "https://sentry.io/",
"type": "custom"
},
{
"url": "https://sentry.io/pricing/",
"type": "custom"
}
],
"time": "2025-12-02T10:37:40+00:00"
},
{ {
"name": "simplesoftwareio/simple-qrcode", "name": "simplesoftwareio/simple-qrcode",
"version": "4.2.0", "version": "4.2.0",
@@ -8064,6 +8380,77 @@
], ],
"time": "2025-11-16T10:14:42+00:00" "time": "2025-11-16T10:14:42+00:00"
}, },
{
"name": "symfony/options-resolver",
"version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "b38026df55197f9e39a44f3215788edf83187b80"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80",
"reference": "b38026df55197f9e39a44f3215788edf83187b80",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\OptionsResolver\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an improved replacement for the array_replace PHP function",
"homepage": "https://symfony.com",
"keywords": [
"config",
"configuration",
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v7.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-11-12T15:39:26+00:00"
},
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.33.0", "version": "v1.33.0",
@@ -8958,6 +9345,94 @@
], ],
"time": "2025-10-16T11:21:06+00:00" "time": "2025-10-16T11:21:06+00:00"
}, },
{
"name": "symfony/psr-http-message-bridge",
"version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/psr-http-message-bridge.git",
"reference": "0101ff8bd0506703b045b1670960302d302a726c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/0101ff8bd0506703b045b1670960302d302a726c",
"reference": "0101ff8bd0506703b045b1670960302d302a726c",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/http-message": "^1.0|^2.0",
"symfony/http-foundation": "^6.4|^7.0|^8.0"
},
"conflict": {
"php-http/discovery": "<1.15",
"symfony/http-kernel": "<6.4"
},
"require-dev": {
"nyholm/psr7": "^1.1",
"php-http/discovery": "^1.15",
"psr/log": "^1.1.4|^2|^3",
"symfony/browser-kit": "^6.4|^7.0|^8.0",
"symfony/config": "^6.4|^7.0|^8.0",
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
"symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0",
"symfony/http-kernel": "^6.4.13|^7.1.6|^8.0",
"symfony/runtime": "^6.4.13|^7.1.6|^8.0"
},
"type": "symfony-bridge",
"autoload": {
"psr-4": {
"Symfony\\Bridge\\PsrHttpMessage\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "PSR HTTP message bridge",
"homepage": "https://symfony.com",
"keywords": [
"http",
"http-message",
"psr-17",
"psr-7"
],
"support": {
"source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-11-13T08:38:49+00:00"
},
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v7.4.0", "version": "v7.4.0",

View File

@@ -6,6 +6,15 @@ x-app-env: &app-env
APP_KEY: ${APP_KEY} APP_KEY: ${APP_KEY}
LOG_CHANNEL: stack LOG_CHANNEL: stack
LOG_LEVEL: ${LOG_LEVEL:-info} LOG_LEVEL: ${LOG_LEVEL:-info}
SENTRY_LARAVEL_DSN: ${SENTRY_LARAVEL_DSN:-}
SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-}
SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.0}
SENTRY_PROFILES_SAMPLE_RATE: ${SENTRY_PROFILES_SAMPLE_RATE:-0.0}
SENTRY_RELEASE: ${SENTRY_RELEASE:-}
VITE_SENTRY_DSN: ${VITE_SENTRY_DSN:-}
VITE_SENTRY_ENV: ${VITE_SENTRY_ENV:-}
VITE_SENTRY_TRACES_SAMPLE_RATE: ${VITE_SENTRY_TRACES_SAMPLE_RATE:-}
VITE_SENTRY_RELEASE: ${VITE_SENTRY_RELEASE:-}
DB_CONNECTION: mysql DB_CONNECTION: mysql
DB_HOST: mysql DB_HOST: mysql
DB_PORT: 3306 DB_PORT: 3306
@@ -84,6 +93,10 @@ services:
- app-code:/var/www/html - app-code:/var/www/html
env_file: env_file:
- path: .env - path: .env
environment:
VITE_SENTRY_DSN: ${VITE_SENTRY_DSN:-}
VITE_SENTRY_ENV: ${VITE_SENTRY_ENV:-}
VITE_SENTRY_RELEASE: ${VITE_SENTRY_RELEASE:-}
depends_on: depends_on:
app: app:
condition: service_healthy condition: service_healthy

View File

@@ -0,0 +1,104 @@
---
title: GlitchTip (Error Monitoring)
sidebar_label: GlitchTip
---
GlitchTip 5.2 is our Sentry-compatible error and performance monitoring stack. It lives at **https://logsder.fotospiel.app** and accepts the standard Sentry SDKs (Laravel + React). This page explains how to wire the DSNs, roll it out in Docker/Dokploy, and how to sanity-check events. Keep PII out of breadcrumbs and context; log only what is needed to debug.
## 1) Environment variables
Set these in `.env` (never commit) and ensure they are passed through Docker (`docker-compose.dokploy.yml` already forwards them):
```
SENTRY_LARAVEL_DSN=https://<key>@logsder.fotospiel.app/<project-id>
SENTRY_ENVIRONMENT=production
SENTRY_TRACES_SAMPLE_RATE=0.05 # adjust per env
SENTRY_PROFILES_SAMPLE_RATE=0.02 # optional profiling
SENTRY_RELEASE=$(git rev-parse --short HEAD)
VITE_SENTRY_DSN=https://<key>@logsder.fotospiel.app/<project-id>
VITE_SENTRY_ENV=production
VITE_SENTRY_RELEASE=$(git rev-parse --short HEAD)
```
Notes:
- DSN is Sentry-format; projects are created in GlitchTip UI. Use per-environment DSNs when possible.
- Keep sampling conservative in production to avoid noise and cost.
- If you do **not** want PII, set `SENTRY_SEND_DEFAULT_PII=false` in Laravel config (or handle in `config/sentry.php`).
## 2) Backend (Laravel 12, PHP 8.3)
1. Install SDK: `composer require sentry/sentry-laravel`.
2. (Optional) Publish config: `php artisan vendor:publish --provider="Sentry\\Laravel\\ServiceProvider" --tag="config"` → tweak `config/sentry.php` (environment, sample rates, PII).
3. Context enrichment (recommended):
- In `app/Exceptions/Handler.php`, set user (`id`, `email`) and tenant/event IDs on the Sentry scope.
- Drop noisy 4xx exceptions via `shouldReport` or by ignoring `HttpException` with status < 500.
4. Health check: run `php artisan sentry:test` (sends a test event).
5. Queue/CLI: the DSN is forwarded to workers via the shared env anchor, so job failures also report.
## 3) Frontend (React 19 / Vite 7 PWAs)
1. Install SDKs: `npm i @sentry/react @sentry/vite-plugin @sentry/tracing`.
2. Initialize in each app entry (`resources/js/guest/...` and `resources/js/admin/...`):
```ts
import * as Sentry from '@sentry/react';
Sentry.init({
dsn: import.meta.env.VITE_SENTRY_DSN,
environment: import.meta.env.VITE_SENTRY_ENV,
release: import.meta.env.VITE_SENTRY_RELEASE,
tracesSampleRate: 0.05,
});
```
Wrap the root in `<Sentry.ErrorBoundary>` with a user-friendly fallback.
3. (Optional) Vite plugin for source maps:
```ts
import { sentryVitePlugin } from '@sentry/vite-plugin';
export default defineConfig({
plugins: [
react(),
sentryVitePlugin({
org: 'glitchtip',
project: 'fotospiel-web',
authToken: process.env.SENTRY_AUTH_TOKEN,
url: 'https://logsder.fotospiel.app', // GlitchTip base
}),
],
});
```
If you skip source map upload, events still work; stack traces will be minified.
## 4) Docker/Dokploy wiring
- `docker-compose.dokploy.yml` now forwards `SENTRY_*` and `VITE_SENTRY_*` to `app`, workers, scheduler, and docs-build.
- Ensure the build container that runs `npm run build` sees `VITE_SENTRY_*` (set in Dokploy env UI or `.env` loaded by Dokploy).
- Redeploy stack after setting envs; no other container changes needed.
## 5) Rollout / validation checklist
1. Set env vars for the target environment (`production`, `staging`).
2. Deploy containers.
3. Trigger test events:
- Backend: `php artisan sentry:test`.
- Frontend: throw a test error from console (`Sentry.captureException(new Error('GlitchTip smoke test')))`.
4. Verify events arrive in GlitchTip project at `https://logsder.fotospiel.app`.
5. Tune `tracesSampleRate`/`profilesSampleRate` after a day of traffic.
## 6) Hygiene & PII guardrails
- Do not attach raw request bodies or tokens. Scrub secrets in Sentry beforeSend hooks if added.
- Limit user context to non-sensitive identifiers (user id/email) and tenant/event IDs.
- Avoid logging photo metadata or guest names in breadcrumbs.
## 7) Troubleshooting
- No events: check DSN matches project and env vars are present in container (`printenv | grep SENTRY`).
- Minified stack traces: upload source maps via the Vite plugin or disable code splitting for critical bundles.
- High volume: drop sampling (`tracesSampleRate`, `profilesSampleRate`) and add ignore rules for expected 4xx.

View File

@@ -93,6 +93,7 @@ const sidebars = {
label: 'Monitoring & Diagramme', label: 'Monitoring & Diagramme',
items: [ items: [
'ops/monitoring-observability', 'ops/monitoring-observability',
'ops/monitoring-glitchtip',
'ops/diagrams', 'ops/diagrams',
], ],
}, },

802
package-lock.json generated
View File

@@ -27,6 +27,9 @@
"@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8", "@radix-ui/react-tooltip": "^1.2.8",
"@react-spring/web": "^10.0.3", "@react-spring/web": "^10.0.3",
"@sentry/react": "^10.32.0",
"@sentry/tracing": "^7.120.4",
"@sentry/vite-plugin": "^4.6.1",
"@stripe/stripe-js": "^8.5.3", "@stripe/stripe-js": "^8.5.3",
"@tailwindcss/vite": "^4.1.17", "@tailwindcss/vite": "^4.1.17",
"@tamagui/button": "~1.139.2", "@tamagui/button": "~1.139.2",
@@ -2253,6 +2256,102 @@
"node": "20 || >=22" "node": "20 || >=22"
} }
}, },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
"integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"license": "MIT"
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
"integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/@isaacs/ttlcache": { "node_modules/@isaacs/ttlcache": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
@@ -3253,6 +3352,16 @@
"pako": "^1.0.10" "pako": "^1.0.10"
} }
}, },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@playwright/test": { "node_modules/@playwright/test": {
"version": "1.57.0", "version": "1.57.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz",
@@ -5215,6 +5324,429 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@sentry-internal/browser-utils": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.32.0.tgz",
"integrity": "sha512-LI83ZKv5ItRajfY7xmQpNs00nWNOXO+A6MCj8LNDpPouYA8m7VvqkCKG9Yh50a/5eIO9lbSWTrARO8rWR3c9jA==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.32.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/feedback": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.32.0.tgz",
"integrity": "sha512-YjDdVR8Ep7lOGilRfSrioBKQlFzWP+j1ibL+9rfwYPWWeQSfK2mbg8+PmbWOcTIXZ/MpuZRMF6ZdkVi7VYBSJw==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.32.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.32.0.tgz",
"integrity": "sha512-P6paw7bLDP72ZNJkcyKSXCXfd+/NKwRfnJpwgkRI9kjy9o0KZrIW2P/xTGftp5q1XxQ7tCt94j2gc1HelOpngw==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "10.32.0",
"@sentry/core": "10.32.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.32.0.tgz",
"integrity": "sha512-GdhyRKywIP9IQc7RoTrBFjx2EFBjiRSndxeiW43qybO1xD2S5Cq/S7ZwkaJOXN8Ie1awm3/E6+mVct5jc6KKAg==",
"license": "MIT",
"dependencies": {
"@sentry-internal/replay": "10.32.0",
"@sentry/core": "10.32.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/tracing": {
"version": "7.120.4",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.120.4.tgz",
"integrity": "sha512-Fz5+4XCg3akeoFK+K7g+d7HqGMjmnLoY2eJlpONJmaeT9pXY7yfUyXKZMmMajdE2LxxKJgQ2YKvSCaGVamTjHw==",
"license": "MIT",
"dependencies": {
"@sentry/core": "7.120.4",
"@sentry/types": "7.120.4",
"@sentry/utils": "7.120.4"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry-internal/tracing/node_modules/@sentry/core": {
"version": "7.120.4",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.120.4.tgz",
"integrity": "sha512-TXu3Q5kKiq8db9OXGkWyXUbIxMMuttB5vJ031yolOl5T/B69JRyAoKuojLBjRv1XX583gS1rSSoX8YXX7ATFGA==",
"license": "MIT",
"dependencies": {
"@sentry/types": "7.120.4",
"@sentry/utils": "7.120.4"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/babel-plugin-component-annotate": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.6.1.tgz",
"integrity": "sha512-aSIk0vgBqv7PhX6/Eov+vlI4puCE0bRXzUG5HdCsHBpAfeMkI8Hva6kSOusnzKqs8bf04hU7s3Sf0XxGTj/1AA==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/@sentry/browser": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.32.0.tgz",
"integrity": "sha512-NtQlXQybrWMbUOPENS4bvxzhMX1Oi+IUH9NXA/mZ06KbQntPLES7yfIKhLNpRipuCzeS16hCJp6HMao2bZB2Hg==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "10.32.0",
"@sentry-internal/feedback": "10.32.0",
"@sentry-internal/replay": "10.32.0",
"@sentry-internal/replay-canvas": "10.32.0",
"@sentry/core": "10.32.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/bundler-plugin-core": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-4.6.1.tgz",
"integrity": "sha512-WPeRbnMXm927m4Kr69NTArPfI+p5/34FHftdCRI3LFPMyhZDzz6J3wLy4hzaVUgmMf10eLzmq2HGEMvpQmdynA==",
"license": "MIT",
"dependencies": {
"@babel/core": "^7.18.5",
"@sentry/babel-plugin-component-annotate": "4.6.1",
"@sentry/cli": "^2.57.0",
"dotenv": "^16.3.1",
"find-up": "^5.0.0",
"glob": "^10.5.0",
"magic-string": "0.30.8",
"unplugin": "1.0.1"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/glob": {
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/magic-string": {
"version": "0.30.8",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
"integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/@sentry/cli": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.58.4.tgz",
"integrity": "sha512-ArDrpuS8JtDYEvwGleVE+FgR+qHaOp77IgdGSacz6SZy6Lv90uX0Nu4UrHCQJz8/xwIcNxSqnN22lq0dH4IqTg==",
"hasInstallScript": true,
"license": "FSL-1.1-MIT",
"dependencies": {
"https-proxy-agent": "^5.0.0",
"node-fetch": "^2.6.7",
"progress": "^2.0.3",
"proxy-from-env": "^1.1.0",
"which": "^2.0.2"
},
"bin": {
"sentry-cli": "bin/sentry-cli"
},
"engines": {
"node": ">= 10"
},
"optionalDependencies": {
"@sentry/cli-darwin": "2.58.4",
"@sentry/cli-linux-arm": "2.58.4",
"@sentry/cli-linux-arm64": "2.58.4",
"@sentry/cli-linux-i686": "2.58.4",
"@sentry/cli-linux-x64": "2.58.4",
"@sentry/cli-win32-arm64": "2.58.4",
"@sentry/cli-win32-i686": "2.58.4",
"@sentry/cli-win32-x64": "2.58.4"
}
},
"node_modules/@sentry/cli-darwin": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.58.4.tgz",
"integrity": "sha512-kbTD+P4X8O+nsNwPxCywtj3q22ecyRHWff98rdcmtRrvwz8CKi/T4Jxn/fnn2i4VEchy08OWBuZAqaA5Kh2hRQ==",
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/cli-linux-arm": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.58.4.tgz",
"integrity": "sha512-rdQ8beTwnN48hv7iV7e7ZKucPec5NJkRdrrycMJMZlzGBPi56LqnclgsHySJ6Kfq506A2MNuQnKGaf/sBC9REA==",
"cpu": [
"arm"
],
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"linux",
"freebsd",
"android"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/cli-linux-arm64": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.58.4.tgz",
"integrity": "sha512-0g0KwsOozkLtzN8/0+oMZoOuQ0o7W6O+hx+ydVU1bktaMGKEJLMAWxOQNjsh1TcBbNIXVOKM/I8l0ROhaAb8Ig==",
"cpu": [
"arm64"
],
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"linux",
"freebsd",
"android"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/cli-linux-i686": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.58.4.tgz",
"integrity": "sha512-NseoIQAFtkziHyjZNPTu1Gm1opeQHt7Wm1LbLrGWVIRvUOzlslO9/8i6wETUZ6TjlQxBVRgd3Q0lRBG2A8rFYA==",
"cpu": [
"x86",
"ia32"
],
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"linux",
"freebsd",
"android"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/cli-linux-x64": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.58.4.tgz",
"integrity": "sha512-d3Arz+OO/wJYTqCYlSN3Ktm+W8rynQ/IMtSZLK8nu0ryh5mJOh+9XlXY6oDXw4YlsM8qCRrNquR8iEI1Y/IH+Q==",
"cpu": [
"x64"
],
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"linux",
"freebsd",
"android"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/cli-win32-arm64": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.58.4.tgz",
"integrity": "sha512-bqYrF43+jXdDBh0f8HIJU3tbvlOFtGyRjHB8AoRuMQv9TEDUfENZyCelhdjA+KwDKYl48R1Yasb4EHNzsoO83w==",
"cpu": [
"arm64"
],
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/cli-win32-i686": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.58.4.tgz",
"integrity": "sha512-3triFD6jyvhVcXOmGyttf+deKZcC1tURdhnmDUIBkiDPJKGT/N5xa4qAtHJlAB/h8L9jgYih9bvJnvvFVM7yug==",
"cpu": [
"x86",
"ia32"
],
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/cli-win32-x64": {
"version": "2.58.4",
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.58.4.tgz",
"integrity": "sha512-cSzN4PjM1RsCZ4pxMjI0VI7yNCkxiJ5jmWncyiwHXGiXrV1eXYdQ3n1LhUYLZ91CafyprR0OhDcE+RVZ26Qb5w==",
"cpu": [
"x64"
],
"license": "FSL-1.1-MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=10"
}
},
"node_modules/@sentry/core": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.32.0.tgz",
"integrity": "sha512-E+ihb8+5PBfYMamnXHalgsmxkcG2YQqhRdgYf3yWJ5dJvi4njh1VWK3kNVj1GvsU6ktaielAx4Rg5dwEFMnbZg==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/react": {
"version": "10.32.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.32.0.tgz",
"integrity": "sha512-vMfGz7x3Ahplcdm0RlEtTNUZ08qpUSr3NRJMQ6duUDxxe0Mqo6DisyQWNQKSROZ7BtLCJUfio6/LRGpkRUoo8A==",
"license": "MIT",
"dependencies": {
"@sentry/browser": "10.32.0",
"@sentry/core": "10.32.0",
"hoist-non-react-statics": "^3.3.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"react": "^16.14.0 || 17.x || 18.x || 19.x"
}
},
"node_modules/@sentry/tracing": {
"version": "7.120.4",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.120.4.tgz",
"integrity": "sha512-cAtpLh23qW3hoqZJ6c36EvFki5NhFWUSK71ALHefqDXEocMlfDc9I+IGn3B/ola2D2TDEDamCy3x32vctKqOag==",
"license": "MIT",
"dependencies": {
"@sentry-internal/tracing": "7.120.4"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/types": {
"version": "7.120.4",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.120.4.tgz",
"integrity": "sha512-cUq2hSSe6/qrU6oZsEP4InMI5VVdD86aypE+ENrQ6eZEVLTCYm1w6XhW1NvIu3UuWh7gZec4a9J7AFpYxki88Q==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/utils": {
"version": "7.120.4",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.120.4.tgz",
"integrity": "sha512-zCKpyDIWKHwtervNK2ZlaK8mMV7gVUijAgFeJStH+CU/imcdquizV3pFLlSQYRswG+Lbyd6CT/LGRh3IbtkCFw==",
"license": "MIT",
"dependencies": {
"@sentry/types": "7.120.4"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/vite-plugin": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-4.6.1.tgz",
"integrity": "sha512-Qvys1y3o8/bfL3ikrHnJS9zxdjt0z3POshdBl3967UcflrTqBmnGNkcVk53SlmtJWIfh85fgmrLvGYwZ2YiqNg==",
"license": "MIT",
"dependencies": {
"@sentry/bundler-plugin-core": "4.6.1",
"unplugin": "1.0.1"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@sinclair/typebox": { "node_modules/@sinclair/typebox": {
"version": "0.27.8", "version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -8039,7 +8571,6 @@
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"license": "MIT", "license": "MIT",
"optional": true,
"dependencies": { "dependencies": {
"debug": "4" "debug": "4"
}, },
@@ -8671,6 +9202,18 @@
"baseline-browser-mapping": "dist/cli.js" "baseline-browser-mapping": "dist/cli.js"
} }
}, },
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/bl": { "node_modules/bl": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
@@ -9026,6 +9569,42 @@
"node": ">= 16" "node": ">= 16"
} }
}, },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/chokidar/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/chownr": { "node_modules/chownr": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
@@ -9830,7 +10409,6 @@
"version": "16.6.1", "version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
@@ -9853,6 +10431,12 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"license": "MIT"
},
"node_modules/eciesjs": { "node_modules/eciesjs": {
"version": "0.4.16", "version": "0.4.16",
"resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.16.tgz", "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.16.tgz",
@@ -11466,7 +12050,6 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"locate-path": "^6.0.0", "locate-path": "^6.0.0",
@@ -11549,6 +12132,34 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"license": "ISC",
"dependencies": {
"cross-spawn": "^7.0.6",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/foreground-child/node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"license": "ISC",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
@@ -12270,6 +12881,21 @@
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"license": "BSD-3-Clause",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/html-encoding-sniffer": { "node_modules/html-encoding-sniffer": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@@ -12356,7 +12982,6 @@
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"license": "MIT", "license": "MIT",
"optional": true,
"dependencies": { "dependencies": {
"agent-base": "6", "agent-base": "6",
"debug": "4" "debug": "4"
@@ -12740,6 +13365,18 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-boolean-object": { "node_modules/is-boolean-object": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
@@ -13326,6 +13963,21 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/jest-environment-node": { "node_modules/jest-environment-node": {
"version": "29.7.0", "version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
@@ -14256,7 +14908,6 @@
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"p-locate": "^5.0.0" "p-locate": "^5.0.0"
@@ -14975,7 +15626,6 @@
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
"license": "ISC", "license": "ISC",
"optional": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -15722,7 +16372,6 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"yocto-queue": "^0.1.0" "yocto-queue": "^0.1.0"
@@ -15738,7 +16387,6 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"p-limit": "^3.0.2" "p-limit": "^3.0.2"
@@ -15759,6 +16407,12 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"license": "BlueOak-1.0.0"
},
"node_modules/package-manager-detector": { "node_modules/package-manager-detector": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz",
@@ -15874,6 +16528,28 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/path-to-regexp": { "node_modules/path-to-regexp": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
@@ -16189,6 +16865,15 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/promise": { "node_modules/promise": {
"version": "8.3.0", "version": "8.3.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
@@ -16883,6 +17568,18 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/recast": { "node_modules/recast": {
"version": "0.23.11", "version": "0.23.11",
"resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
@@ -18133,6 +18830,21 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/string.prototype.matchall": { "node_modules/string.prototype.matchall": {
"version": "4.0.12", "version": "4.0.12",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
@@ -18261,6 +18973,19 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-bom": { "node_modules/strip-bom": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
@@ -19192,6 +19917,18 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/unplugin": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz",
"integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==",
"license": "MIT",
"dependencies": {
"acorn": "^8.8.1",
"chokidar": "^3.5.3",
"webpack-sources": "^3.2.3",
"webpack-virtual-modules": "^0.5.0"
}
},
"node_modules/until-async": { "node_modules/until-async": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz", "resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz",
@@ -20754,6 +21491,21 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/webpack-sources": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
"integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
"license": "MIT",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz",
"integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==",
"license": "MIT"
},
"node_modules/whatwg-encoding": { "node_modules/whatwg-encoding": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
@@ -20967,6 +21719,39 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/ansi-styles": { "node_modules/wrap-ansi/node_modules/ansi-styles": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -21114,7 +21899,6 @@
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=10"

View File

@@ -64,6 +64,9 @@
"@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8", "@radix-ui/react-tooltip": "^1.2.8",
"@react-spring/web": "^10.0.3", "@react-spring/web": "^10.0.3",
"@sentry/react": "^10.32.0",
"@sentry/tracing": "^7.120.4",
"@sentry/vite-plugin": "^4.6.1",
"@stripe/stripe-js": "^8.5.3", "@stripe/stripe-js": "^8.5.3",
"@tailwindcss/vite": "^4.1.17", "@tailwindcss/vite": "^4.1.17",
"@tamagui/button": "~1.139.2", "@tamagui/button": "~1.139.2",

View File

@@ -16,12 +16,14 @@ import { EventProvider } from './context/EventContext';
import MatomoTracker from '@/components/analytics/MatomoTracker'; import MatomoTracker from '@/components/analytics/MatomoTracker';
import { ConsentProvider } from '@/contexts/consent'; import { ConsentProvider } from '@/contexts/consent';
import CookieBanner from '@/components/consent/CookieBanner'; import CookieBanner from '@/components/consent/CookieBanner';
import { Sentry, initSentry } from '@/lib/sentry';
const DevTenantSwitcher = React.lazy(() => import('./DevTenantSwitcher')); const DevTenantSwitcher = React.lazy(() => import('./DevTenantSwitcher'));
const enableDevSwitcher = import.meta.env.DEV || import.meta.env.VITE_ENABLE_TENANT_SWITCHER === 'true'; const enableDevSwitcher = import.meta.env.DEV || import.meta.env.VITE_ENABLE_TENANT_SWITCHER === 'true';
initializeTheme(); initializeTheme();
initSentry('admin');
const rootEl = document.getElementById('root')!; const rootEl = document.getElementById('root')!;
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
@@ -43,11 +45,19 @@ if ('serviceWorker' in navigator) {
}); });
} }
const AdminFallback: React.FC<{ message: string }> = ({ message }) => (
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
{message}
</div>
);
createRoot(rootEl).render( createRoot(rootEl).render(
<React.StrictMode> <React.StrictMode>
<Sentry.ErrorBoundary fallback={<AdminFallback message="Oberfläche konnte nicht geladen werden." />}>
<AppearanceProvider> <AppearanceProvider>
<AdminApp /> <AdminApp />
</AppearanceProvider> </AppearanceProvider>
</Sentry.ErrorBoundary>
</React.StrictMode> </React.StrictMode>
); );

View File

@@ -13,8 +13,16 @@ import CookieBanner from '@/components/consent/CookieBanner';
import React from 'react'; import React from 'react';
import { usePage } from '@inertiajs/react'; import { usePage } from '@inertiajs/react';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { Sentry, initSentry } from './lib/sentry';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel'; const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
const InertiaFallback: React.FC = () => (
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
Oberfläche konnte nicht geladen werden.
</div>
);
initSentry('inertia');
const LocaleSync: React.FC<{ children: React.ReactNode }> = ({ children }) => { const LocaleSync: React.FC<{ children: React.ReactNode }> = ({ children }) => {
// usePage is only available inside Inertia-provided tree; guard for SSR/raw mounts // usePage is only available inside Inertia-provided tree; guard for SSR/raw mounts
@@ -63,6 +71,7 @@ createInertiaApp({
} }
root.render( root.render(
<Sentry.ErrorBoundary fallback={<InertiaFallback />}>
<AppearanceProvider> <AppearanceProvider>
<ConsentProvider> <ConsentProvider>
<I18nextProvider i18n={i18n}> <I18nextProvider i18n={i18n}>
@@ -74,6 +83,7 @@ createInertiaApp({
</I18nextProvider> </I18nextProvider>
</ConsentProvider> </ConsentProvider>
</AppearanceProvider> </AppearanceProvider>
</Sentry.ErrorBoundary>
); );
}, },
progress: { progress: {

View File

@@ -3,8 +3,16 @@ import { createRoot } from 'react-dom/client';
import '../../css/app.css'; import '../../css/app.css';
import { AppearanceProvider, initializeTheme } from '@/hooks/use-appearance'; import { AppearanceProvider, initializeTheme } from '@/hooks/use-appearance';
import { enableGuestDemoMode, shouldEnableGuestDemoMode } from './demo/demoMode'; import { enableGuestDemoMode, shouldEnableGuestDemoMode } from './demo/demoMode';
import { Sentry, initSentry } from '@/lib/sentry';
const GuestFallback: React.FC<{ message: string }> = ({ message }) => (
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
{message}
</div>
);
initializeTheme(); initializeTheme();
initSentry('guest');
if (shouldEnableGuestDemoMode()) { if (shouldEnableGuestDemoMode()) {
enableGuestDemoMode(); enableGuestDemoMode();
} }
@@ -14,11 +22,13 @@ const isShareRoute = typeof window !== 'undefined' && window.location.pathname.s
const shareRoot = async () => { const shareRoot = async () => {
const { SharedPhotoStandalone } = await import('./pages/SharedPhotoPage'); const { SharedPhotoStandalone } = await import('./pages/SharedPhotoPage');
createRoot(rootEl).render( createRoot(rootEl).render(
<Sentry.ErrorBoundary fallback={<GuestFallback message="Dieses Foto kann gerade nicht geladen werden." />}>
<React.StrictMode> <React.StrictMode>
<AppearanceProvider> <AppearanceProvider>
<SharedPhotoStandalone /> <SharedPhotoStandalone />
</AppearanceProvider> </AppearanceProvider>
</React.StrictMode> </React.StrictMode>
</Sentry.ErrorBoundary>
); );
}; };
@@ -53,41 +63,29 @@ const appRoot = async () => {
} }
createRoot(rootEl).render( createRoot(rootEl).render(
<Sentry.ErrorBoundary fallback={<GuestFallback message="Erlebnisse können nicht geladen werden." />}>
<React.StrictMode> <React.StrictMode>
<AppearanceProvider> <AppearanceProvider>
<LocaleProvider> <LocaleProvider>
<ToastProvider> <ToastProvider>
<MatomoTracker config={matomoConfig} /> <MatomoTracker config={matomoConfig} />
<Suspense <Suspense fallback={<GuestFallback message="Erlebnisse werden geladen …" />}>
fallback={(
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
Erlebnisse werden geladen
</div>
)}
>
<RouterProvider router={router} /> <RouterProvider router={router} />
</Suspense> </Suspense>
</ToastProvider> </ToastProvider>
</LocaleProvider> </LocaleProvider>
</AppearanceProvider> </AppearanceProvider>
</React.StrictMode> </React.StrictMode>
</Sentry.ErrorBoundary>
); );
}; };
if (isShareRoute) { if (isShareRoute) {
shareRoot().catch(() => { shareRoot().catch(() => {
createRoot(rootEl).render( createRoot(rootEl).render(<GuestFallback message="Dieses Foto kann gerade nicht geladen werden." />);
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
Dieses Foto kann gerade nicht geladen werden.
</div>
);
}); });
} else { } else {
appRoot().catch(() => { appRoot().catch(() => {
createRoot(rootEl).render( createRoot(rootEl).render(<GuestFallback message="Erlebnisse können nicht geladen werden." />);
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
Erlebnisse können nicht geladen werden.
</div>
);
}); });
} }

View File

@@ -0,0 +1,41 @@
import * as Sentry from '@sentry/react';
type AppSurface = 'guest' | 'admin' | 'inertia';
const defaultTracesSampleRate = 0.05;
const parseSampleRate = (value: string | undefined): number => {
const parsed = Number.parseFloat(value ?? '');
if (Number.isNaN(parsed) || parsed < 0) {
return defaultTracesSampleRate;
}
return parsed;
};
export const initSentry = (app: AppSurface): void => {
const dsn = import.meta.env.VITE_SENTRY_DSN;
if (! dsn) {
return;
}
Sentry.init({
dsn,
environment: import.meta.env.VITE_SENTRY_ENV ?? import.meta.env.MODE,
release: import.meta.env.VITE_SENTRY_RELEASE,
tracesSampleRate: parseSampleRate(import.meta.env.VITE_SENTRY_TRACES_SAMPLE_RATE),
beforeSend(event) {
event.tags = {
...event.tags,
app,
};
return event;
},
normalizeDepth: 6,
});
};
export { Sentry };