mivita/dev/glitch-tip/README.md
2026-10-08 12:35:04 +00:00

4.5 KiB

GlitchTip — Fehlerprotokoll mivita.care

Stand: 08.10.2026 · Hintergrund und Regeln: dev/git-deploy-monitoring/02-fehlerprotokoll-glitchtip.md

Wert
Instanz https://errors.adametz.media (selbst gehostet, gemeinsam mit anderen Projekten)
Organisation adametz-media
Projekt Server (PHP/Laravel) server-mivitacare, ID 4 → SENTRY_LARAVEL_DSN
Projekt Browser (JavaScript) browser-mivitacare, ID 3 → SENTRY_BROWSER_DSN
Umgebungen production (Live), local (Entwicklung, nur zum Testen)
Push (ntfy) https://push.adametz.media, Topic in MONITORING_NTFY_TOPIC
Alert-Regeln beide Projekte: Mail bei neuem Fehlertyp, nur production
Live seit v1.3.0 (08.10.2026)

Was gemeldet wird

Quelle Wie
Exceptions (Request, Job, Command) App\Exceptions\Handler::report() → Integration::captureUnhandledException(); Laravels dontReport gilt (404, Validierung, Auth), zusätzlich PayoneTransportException, CommandNotFoundException
Fehler ohne Exception App\Http\Middleware\ReportErrorSignals (global): 404 mit eigenem Referrer (nach Pfad, nicht Route — wegen der Catch-all-Route), 403/429 für Angemeldete, 419; höchstens 5 je 10 Min. und Ort
Browserfehler public/js/error-reporting/error-reporting.js über <x-monitoring.browser-errors area="…" /> in 7 Layouts (crm, crm-auth, portal, portal-auth, portal-public, web, shop)
Betriebs-Alarme App\Support\OperationalAlert → Log, Mail, ntfy (siehe dev/betrieb/README.md, Abschnitt G)

Datenschutz: App\Support\Monitoring\ErrorReportScrubber (Server) und dieselben Regeln in error-reporting.js (Browser): nur User-ID, keine Request-Bodys/Cookies, Tokens und nicht erlaubte Query-Parameter als [Filtered], E-Mail-Adressen als [email]. Erlaubte Query-Parameter: page, q, tab, sort, lang, month, year (+ utm_*) — Liste an beiden Stellen gleich halten.

Tests melden nie an das echte GlitchTip/ntfy (phpunit.xml, Wächtertest in ErrorReportingTest).

Browser-SDK (selbst gehostet)

Kein Drittanbieter-CDN (sonst ginge die IP jedes Besuchers an Sentry). public/js/error-reporting/:

  • error-reporting.js — Listener, lädt das SDK erst beim ersten Fehler; ES2018, ohne Regex-Lookbehind (ältere Safari-Versionen brechen sonst beim Parsen ab — Test prüft das)
  • sentry-browser-<version>.min.js — Version in config('monitoring.browser.sdk_version')

Neu bauen (z. B. Update auf eine neue SDK-Version), außerhalb des Projekts:

mkdir /tmp/sentry-build && cd /tmp/sentry-build && npm init -y >/dev/null
npm install --ignore-scripts --save-exact @sentry/browser@<version> esbuild
echo "export { captureException, init, setTag, setUser } from '@sentry/browser';" > entry.js
npx esbuild entry.js --bundle --minify --format=iife --global-name=MivitaSentry --target=es2018 \
  --legal-comments=none --outfile=sentry-browser-<version>.min.js

Datei nach public/js/error-reporting/ kopieren, sdk_version in config/monitoring.php anpassen, alte Datei löschen.

Auswerten per API

Lese-Token (project:read, event:read) liegt lokal als GLITCHTIP_API_TOKEN in der .env — nie ausgeben, nie committen.

T=$(grep -E "^GLITCHTIP_API_TOKEN=" .env | cut -d= -f2- | tr -d "'\"")
B=https://errors.adametz.media/api/0

# Offene Einträge, nur Live (project=4 Server, project=3 Browser)
curl -s -H "Authorization: Bearer $T" \
  "$B/organizations/adametz-media/issues/?project=4&query=is:unresolved&environment=production&limit=100" \
| python3 -c "
import json,sys
for i in json.load(sys.stdin):
    print(i['id'], i['count'], i['firstSeen'][:16], i['lastSeen'][:16], '|', (i['title'] or '')[:100])"

# Letztes Ereignis eines Eintrags (Umgebung, Release, Bereich, Stacktrace)
curl -s -H "Authorization: Bearer $T" "$B/issues/<ID>/events/latest/"

Einordnen und Vorgehen: Abschnitt 7 in 02-fehlerprotokoll-glitchtip.md. Auflösen in GlitchTip von Hand (Token ist nur lesend).

Testen

# Server (Umgebung laut SENTRY_ENVIRONMENT)
php artisan tinker --execute 'report(new RuntimeException("GlitchTip-Test"));'
# Alarm (Mail + ntfy)
php artisan tinker --execute 'App\Support\OperationalAlert::send("Test-Alarm");'

Browser (Konsole auf einer Seite der App, z. B. CRM):

setTimeout(() => { throw new Error('Browser-Test test@example.com') });

→ erscheint im Projekt browser-mivitacare, E-Mail als [email].