Compare commits

...

4 Commits

Author SHA1 Message Date
Marijn 7f18e9768c fix: use spotlight_url to route PHP dev errors to Spotlight sidecar 2026-07-05 22:33:15 +02:00
Marijn 750e8f805c feat: route PHP Sentry events to Spotlight in dev
Add a when@dev block to sentry.yaml that initialises the PHP Sentry SDK
with a placeholder DSN and forwards all events to the Spotlight sidecar
over the internal Docker network (http://spotlight:8969/stream).

The JS SDK already uses localhost:8969 via spotlight:true when no real
SENTRY_DSN is set, which is correct since the browser cannot reach the
internal Docker hostname.
2026-07-05 22:23:04 +02:00
Marijn ce8f55fd9a feat: add Spotlight sidecar for local Sentry development testing
Add the Spotlight container to compose.override.yaml so the feedback
widget and error events can be inspected locally without sending anything
to Sentry. The JS SDK switches to spotlight mode automatically when no
SENTRY_DSN is configured.
2026-07-05 22:10:50 +02:00
Marijn c424e25d57 feat: add Sentry User Feedback widget to backoffice (#178)
Install @sentry/browser via AssetMapper and initialize the feedback
integration on all backoffice pages. The CDN loader script is moved to
an overridable block so backoffice pages use the npm SDK without
double-initialising Sentry.

Sentry is initialised only when a DSN is configured (SENTRY_DSN env
var). When a user is logged in their email is pre-filled in the feedback
form via Sentry.setUser(); both name and email remain optional so
anonymous submissions are supported by simply leaving those fields empty.
2026-07-05 21:46:07 +02:00
7 changed files with 52 additions and 0 deletions
+23
View File
@@ -3,3 +3,26 @@ import 'bootstrap-icons/font/bootstrap-icons.min.css';
import './styles/backoffice.scss'; import './styles/backoffice.scss';
import './stimulus.js'; import './stimulus.js';
import './bootstrap.js'; import './bootstrap.js';
import * as Sentry from '@sentry/browser';
const dsn = document.querySelector('meta[name="sentry-dsn"]')?.content ?? '';
const userEmail = document.querySelector('meta[name="user-email"]')?.content ?? '';
Sentry.init({
dsn: dsn || undefined,
// When no DSN is set (local dev), forward events to Spotlight instead
spotlight: !dsn,
integrations: [
Sentry.feedbackIntegration({
colorScheme: 'system',
showName: true,
showEmail: true,
isNameRequired: false,
isEmailRequired: false,
}),
],
});
if (userEmail) {
Sentry.setUser({ email: userEmail });
}
+5
View File
@@ -70,5 +70,10 @@ services:
MP_SMTP_AUTH_ALLOW_INSECURE: 1 MP_SMTP_AUTH_ALLOW_INSECURE: 1
###< symfony/mailer ### ###< symfony/mailer ###
spotlight:
image: ghcr.io/getsentry/spotlight:latest
ports:
- "8969:8969"
volumes: volumes:
sass: sass:
+7
View File
@@ -1,3 +1,10 @@
when@dev:
sentry:
dsn: 'https://placeholder@placeholder.ingest.sentry.io/0'
options:
spotlight: true
spotlight_url: 'http://spotlight:8969/stream'
when@prod: when@prod:
sentry: sentry:
dsn: '%env(SENTRY_DSN)%' dsn: '%env(SENTRY_DSN)%'
+2
View File
@@ -1,6 +1,8 @@
twig: twig:
file_name_pattern: '*.twig' file_name_pattern: '*.twig'
form_themes: [ 'bootstrap_5_layout.html.twig' ] form_themes: [ 'bootstrap_5_layout.html.twig' ]
globals:
sentry_dsn: '%env(SENTRY_DSN)%'
when@test: when@test:
twig: twig:
+7
View File
@@ -34,4 +34,11 @@ return [
'@hotwired/stimulus' => ['version' => '3.2.2'], '@hotwired/stimulus' => ['version' => '3.2.2'],
'@hotwired/turbo' => ['version' => '8.0.23'], '@hotwired/turbo' => ['version' => '8.0.23'],
'bootstrap-icons/font/bootstrap-icons.min.css' => ['version' => '1.13.1', 'type' => 'css'], 'bootstrap-icons/font/bootstrap-icons.min.css' => ['version' => '1.13.1', 'type' => 'css'],
'@sentry/browser' => ['version' => '10.63.0'],
'@sentry/feedback' => ['version' => '10.63.0'],
'@sentry/core/browser' => ['version' => '10.63.0'],
'@sentry/browser-utils' => ['version' => '10.63.0'],
'@sentry/replay' => ['version' => '10.63.0'],
'@sentry/replay-canvas' => ['version' => '10.63.0'],
'@sentry/core' => ['version' => '10.63.0'],
]; ];
+5
View File
@@ -1,5 +1,10 @@
{% extends 'base.html.twig' %} {% extends 'base.html.twig' %}
{% block importmap %}{{ importmap('backoffice') }}{% endblock %} {% block importmap %}{{ importmap('backoffice') }}{% endblock %}
{% block sentry_loader %}{% endblock %}
{% block head_extra %}
<meta name="sentry-dsn" content="{{ sentry_dsn }}">
<meta name="user-email" content="{{ app.user ? app.user.userIdentifier : '' }}">
{% endblock %}
{% block title %}Tijd voor de test | {% endblock %} {% block title %}Tijd voor de test | {% endblock %}
{% block nav %}{{ include('backoffice/nav.html.twig') }}{% endblock %} {% block nav %}{{ include('backoffice/nav.html.twig') }}{% endblock %}
+3
View File
@@ -3,14 +3,17 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
{% block sentry_loader %}
<script <script
src="https://js-de.sentry-cdn.com/30cf438bc708c97e6f45c127bed9af96.min.js" src="https://js-de.sentry-cdn.com/30cf438bc708c97e6f45c127bed9af96.min.js"
crossorigin="anonymous" crossorigin="anonymous"
></script> ></script>
{% endblock %}
<title> <title>
{% block title %}Tijd voor de test{% endblock title %} {% block title %}Tijd voor de test{% endblock title %}
</title> </title>
{% block importmap %}{% endblock %} {% block importmap %}{% endblock %}
{% block head_extra %}{% endblock %}
</head> </head>
<body> <body>
{% block nav %} {% block nav %}