feat : error tracking backend vers GlitchTip (via Tailscale) (#37)
Auto Tag Develop / tag (push) Successful in 9s
Auto Tag Develop / tag (push) Successful in 9s
## Objectif Remonter les erreurs **backend** Symfony vers **GlitchTip** (SDK Sentry), **prod uniquement**, **inerte sans `SENTRY_DSN`**. Transport réseau via **Tailscale** sur le host de prod (infra, hors repo). Frontend hors périmètre. ## Contenu - `sentry/sentry-symfony:^5.10` (+ `symfony.lock` recipe) - `config/bundles.php` → `SentryBundle ['prod' => true]` - `config/packages/sentry.yaml` (nouveau) : DSN runtime, release `%app.version%`, 4xx ignorés, pas de tracing, handler Monolog ERROR+ - `config/packages/monolog.yaml` : handler `sentry` en `when@prod` - `.env` : bloc `SENTRY_DSN` documenté (vide → inerte) - `doc/error-tracking.md` (runbook Tailscale) + section `CLAUDE.md` - Spec + plan sous `docs/superpowers/` ## Vérifications - Prod `cache:clear` OK, service `Sentry\Monolog\Handler` chargé - **267/267 tests verts**, dev/test inchangés (bundle non chargé hors prod) - Aucun changement `frontend/` / `.gitea/` / `deploy/docker/` - Revue multi-agents : **READY TO MERGE** (aucun Critical/Important) ## Activation prod (hors code, cf. `doc/error-tracking.md`) 1. Tailscale sur l'hôte GlitchTip **et** sur le VPS OVH (prod) 2. Créer le projet `sirh-api` dans GlitchTip → récupérer le DSN 3. `SENTRY_DSN=http://<clé>@<IP-tailnet>:<port>/<id>` dans l'env_file serveur + redéploiement 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #37 Co-authored-by: matthieu <matthieu@yuno.malio.fr> Co-committed-by: matthieu <matthieu@yuno.malio.fr>
This commit was merged in pull request #37.
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# Error tracking (GlitchTip)
|
||||
|
||||
Les erreurs **backend** (Symfony) sont remontées vers **GlitchTip** (instance interne MALIO,
|
||||
compatible SDK Sentry), org `malio`, projet `sirh-api`. **Prod uniquement**, **inerte sans DSN**.
|
||||
|
||||
> Frontend hors périmètre (les erreurs front partent du navigateur RH ; ajout futur possible via
|
||||
> un proxy nginx `/ingest`).
|
||||
|
||||
## Contrainte réseau & transport
|
||||
|
||||
GlitchTip est sur le réseau interne (bloqué par Sophos), servi en **HTTPS sur
|
||||
`logs.malio-dev.fr`** (cert auto-signé par la CA interne « MALIO-DEV Local Root CA »). SIRH tourne
|
||||
sur un **VPS OVH** public. Le lien passe par un **tunnel Tailscale** entre les deux hôtes.
|
||||
|
||||
**Topologie retenue (Option A — HTTPS + hostname mappé sur le tailnet) :**
|
||||
- Tailscale est installé **sur l'hôte GlitchTip** (IP tailnet `100.111.223.34`) **et sur le VPS
|
||||
OVH** (IP tailnet `100.93.52.45`).
|
||||
- Le **DSN reste inchangé** : `https://<clé>@logs.malio-dev.fr/<id>` (même endpoint que le
|
||||
navigateur → pas de souci `ALLOWED_HOSTS`, Host header et cert cohérents).
|
||||
- Côté SIRH, le nom `logs.malio-dev.fr` est résolu vers l'**IP tailnet de GlitchTip** via
|
||||
`extra_hosts` dans le `docker-compose` du serveur.
|
||||
- La **CA racine MALIO** est bakée dans l'image SIRH (`deploy/docker/Dockerfile.prod`) pour que le
|
||||
SDK accepte le TLS auto-signé.
|
||||
|
||||
> Pré-requis : le nginx qui sert `logs.malio-dev.fr` en 443 doit écouter sur une interface
|
||||
> joignable via le tailnet (typiquement `0.0.0.0:443` → joignable sur `100.111.223.34:443`).
|
||||
|
||||
## Fichiers concernés
|
||||
|
||||
| Fichier | Rôle |
|
||||
|---|---|
|
||||
| `config/packages/sentry.yaml` | conf backend (prod-only, DSN runtime, 4xx ignorés, release = `app.version`, handler Monolog ERROR+) |
|
||||
| `config/bundles.php` | `SentryBundle` enregistré `['prod' => true]` |
|
||||
| `config/packages/monolog.yaml` | handler `sentry` (service) en `when@prod` |
|
||||
| `.env` | bloc documenté `SENTRY_DSN` (vide → inerte) |
|
||||
| `deploy/docker/Dockerfile.prod` | bake la CA racine MALIO (`update-ca-certificates`) pour le TLS interne |
|
||||
| `deploy/docker/malio-dev-root-ca.crt` | certificat **public** de la CA interne (aucune clé privée) |
|
||||
|
||||
## Activation (runbook)
|
||||
|
||||
1. **Tailscale sur les deux hôtes** (GlitchTip **et** VPS OVH) :
|
||||
```bash
|
||||
curl -fsSL https://tailscale.com/install.sh | sh
|
||||
sudo tailscale up # ou --authkey tskey-auth-XXXX (headless)
|
||||
tailscale ip -4 # GlitchTip → 100.111.223.34 ; OVH → 100.93.52.45
|
||||
```
|
||||
2. **Vérifier l'accès** depuis le VPS OVH (tunnel + nginx 443 de GlitchTip) :
|
||||
```bash
|
||||
tailscale ping 100.111.223.34
|
||||
curl -sSk -o /dev/null -w "%{http_code}\n" https://100.111.223.34/ # réponse HTTP = tunnel OK
|
||||
```
|
||||
3. **Mapper le hostname vers l'IP tailnet** dans le `docker-compose` du serveur OVH (service `php`),
|
||||
pour que le container résolve `logs.malio-dev.fr` :
|
||||
```yaml
|
||||
extra_hosts:
|
||||
- "logs.malio-dev.fr:100.111.223.34"
|
||||
```
|
||||
4. **Projet GlitchTip** : déjà créé (org `malio`, projet `sirh-api`, id `3`). DSN de base affiché
|
||||
dans *Settings → Client Keys* : `https://<clé>@logs.malio-dev.fr/3`.
|
||||
5. **Injecter le DSN tel quel** (hostname conservé) dans l'env_file serveur (pas dans l'image),
|
||||
puis rebuild/redéployer l'image (la CA est bakée au build) :
|
||||
```env
|
||||
SENTRY_DSN=https://<clé>@logs.malio-dev.fr/3
|
||||
```
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker compose exec php php bin/console cache:clear --env=prod
|
||||
```
|
||||
|
||||
## Tester l'envoi
|
||||
|
||||
Le bundle `sentry/sentry-symfony` fournit une commande qui envoie un événement de test et
|
||||
confirme s'il est bien parti vers GlitchTip. Elle n'existe qu'en **prod** (bundle prod-only) et
|
||||
nécessite `SENTRY_DSN` défini.
|
||||
|
||||
```bash
|
||||
# Sur le serveur, dans le container PHP (SENTRY_DSN doit être dans l'env) :
|
||||
docker compose exec php sh -lc "APP_ENV=prod php bin/console sentry:test"
|
||||
```
|
||||
|
||||
Sortie attendue : `Sending test message... done.` → une **Issue de test** apparaît dans le projet
|
||||
`sirh-api` côté GlitchTip. Si l'envoi échoue (`Message not sent`), le problème est réseau
|
||||
(Tailscale/route/port) ou DSN, pas applicatif.
|
||||
|
||||
Pré-check connectivité depuis le VPS OVH (`-k` ignore le cert juste pour ce test) :
|
||||
|
||||
```bash
|
||||
tailscale ping 100.111.223.34
|
||||
curl -sSk -o /dev/null -w "%{http_code}\n" https://100.111.223.34/ # réponse HTTP = tunnel OK
|
||||
# Avec résolution du hostname (comme le container) + validation par la CA :
|
||||
curl --resolve logs.malio-dev.fr:443:100.111.223.34 \
|
||||
--cacert deploy/docker/malio-dev-root-ca.crt \
|
||||
-sS -o /dev/null -w "%{http_code}\n" https://logs.malio-dev.fr/
|
||||
```
|
||||
|
||||
Alternative sans commande dédiée : déclencher un `throw new \RuntimeException('glitchtip test')`
|
||||
temporaire dans un endpoint, ou un `$logger->error('glitchtip test')` (niveau ERROR+ → Issue).
|
||||
|
||||
## CA HTTPS interne (bakée dans l'image)
|
||||
|
||||
GlitchTip est en HTTPS avec un cert auto-signé par la **CA interne MALIO**. Le SDK refuse un TLS
|
||||
non approuvé (« Message not sent »). La CA publique (`deploy/docker/malio-dev-root-ca.crt`, aucune
|
||||
clé privée) est donc installée dans le trust store de l'image au build (`deploy/docker/Dockerfile.prod`,
|
||||
stage production) :
|
||||
|
||||
```dockerfile
|
||||
COPY deploy/docker/malio-dev-root-ca.crt /usr/local/share/ca-certificates/malio-dev-root-ca.crt
|
||||
RUN update-ca-certificates
|
||||
```
|
||||
|
||||
Combinée à l'`extra_hosts` (hostname → IP tailnet), le container fait confiance à
|
||||
`logs.malio-dev.fr` et l'atteint via le tunnel.
|
||||
|
||||
Design détaillé : `docs/superpowers/specs/2026-06-28-glitchtip-backend-error-tracking-design.md`.
|
||||
Reference in New Issue
Block a user