|
|
||
|---|---|---|
| .. | ||
| README.md | ||
GlitchTip — Fehlerprotokoll von Pressekonto
Stand: 06.10.2026 · Gilt ab: v1.1.0 (live seit 05.10.2026) Für: KI-Chats und Entwickler, die Fehler aus GlitchTip auswerten und beheben.
Dieses Dokument beschreibt, was GlitchTip hier ist, wie Fehler dorthin
gelangen, was zu tun ist, wenn jemand sagt „schau mal in GlitchTip“, und
welche Regeln dabei nicht verletzt werden dürfen. Hintergrund und
Entscheidungen: ../betrieb/monitoring-plan.md
(Phase 1, Entscheidungen M1–M9).
1. Überblick
| Was | Wert |
|---|---|
| Instanz | https://errors.adametz.media (selbst gehostet, Sentry-kompatibel) |
| Organisation (Slug) | adametz-media |
| Projekt 1 | server-pressekonto — PHP/Laravel: Exceptions und Fehlersignale |
| Projekt 2 | browser-pressekonto — JavaScript-Fehler aus dem Browser |
| Umgebungen | production (Live), local (Entwicklung). Nur production ist Betrieb |
| Release | Git-Tag aus der Datei RELEASE (z. B. v1.1.0), siehe Abschnitt 6 |
| Aufbewahrung | 90 Tage (GLITCHTIP_MAX_EVENT_LIFE_DAYS auf dem GlitchTip-Server) |
| Alarmierung | GlitchTip-Alert-Regel: Mail bei neuem Fehlertyp. Betriebs-Alerts der App (fehlgeschlagene Jobs/Tasks) laufen getrennt über Mail + ntfy (push.adametz.media, Topic pressekonto-ops) |
GlitchTip ist nicht das einzige Signal. Daneben: /health (externer
Monitor), Admin ▸ Reports ▸ Betriebsüberwachung, storage/logs/*.log.
2. Wie Fehler nach GlitchTip gelangen
Server (Projekt 1)
| Weg | Datei | Was |
|---|---|---|
| Gemeldete Exceptions | bootstrap/app.php → Integration::handles($exceptions) |
Alles, was Laravel über report() meldet — unbehandelte Exceptions in Requests, Jobs, Commands |
| Fehlersignale ohne Exception | app/Http/Middleware/ReportErrorSignals.php, app/Support/Monitoring/ErrorSignal.php |
Warnungen: 404 mit eigenem Referrer („Toter interner Link“), 403/429 für Angemeldete, 419 („Seite abgelaufen“). Je Signal und Ort höchstens 5 Meldungen in 10 Minuten |
| Konfiguration | config/sentry.php |
DSN, Release, Datenschutz-Optionen |
| Datenschutzfilter | app/Support/Monitoring/ErrorReportScrubber.php (before_send) |
Nur User-ID, Tokens/Signaturen aus URL/Query/Referer, E-Mails aus Meldungen |
Bewusst nicht gemeldet:
- Laravels Standard-
dontReport: 404, Validierung, Authentifizierung, 419 als Exception (419 kommt als Fehlersignal). CommandNotFoundException— vertippteartisan-Befehle (bootstrap/app.php).App\Services\SearchConsole\SearchConsoleUnavailable— Google hängt vorübergehend; nurLog::warning, der Lauf alarmiert erst bei Abbruch oder ≥ 50 % Fehlern.
Browser (Projekt 2)
| Datei | Was |
|---|---|
resources/js/error-reporting.js |
Hört auf error und unhandledrejection; lädt das SDK erst beim ersten Fehler; filtert URLs/E-Mails; Ablehnungen ohne Error werden mit Typ und Inhalt beschrieben |
resources/js/error-reporting-sdk.js |
Re-Export der benötigten SDK-Funktionen (Tree-Shaking) |
resources/views/components/monitoring/browser-errors.blade.php |
<meta name="pk-error-reporting"> mit DSN, Release, User-ID, Bereich; nur mit SENTRY_BROWSER_DSN |
| Eingebunden in | partials/head (Portal, area: portal), web/layouts/web-master (area: web), components/layouts/auth/pressekonto (area: auth) |
Fehlgeschlagene Livewire-Requests (5xx, 419) meldet der Server, nicht der Browser.
Tests melden nie an GlitchTip
phpunit.xml leert SENTRY_LARAVEL_DSN, SENTRY_DSN, SENTRY_BROWSER_DSN.
Wächtertest: tests/Feature/Monitoring/ErrorReportingTest.php („the test suite
never reports to the real glitchtip“). Tests, die Sentry-Ereignisse prüfen,
benutzen Tests\Support\FakeGlitchTip::install().
Erkennungszeichen für Test-Rauschen in GlitchTip: Umgebung local und
Texte wie „Queue weg“, „Datenbank nicht erreichbar“, SQLite-Fehler
(„General error: 1 no such table“ — Live ist MySQL), „no role named
customer“. Bis 06.10.2026 kamen solche Einträge aus Testläufen mit lokaler DSN.
3. Zugriff per API (lesend)
Token: GLITCHTIP_API_TOKEN in der lokalen .env — nur lesen
(project:read, event:read). Kein org:read (Organisationsliste → 403),
kein Schreiben (Auflösen → 403). Den Token nie ausgeben, nie committen.
Alle Befehle aus dem Projektverzeichnis:
T=$(grep -E "^GLITCHTIP_API_TOKEN=" .env | cut -d= -f2- | tr -d "'\"")
B=https://errors.adametz.media/api/0
Offene Einträge eines Projekts (Projekt 1 = Server, 2 = Browser; environment=production für Live, weglassen für alle):
curl -s -H "Authorization: Bearer $T" \
"$B/organizations/adametz-media/issues/?project=1&query=is:unresolved&environment=production&limit=100" \
| python3 -c "
import json,sys
for i in json.load(sys.stdin):
print(i['id'], i['level'], i['count'], i['firstSeen'][:16], i['lastSeen'][:16], '|', (i['title'] or '')[:100])"
Letztes Ereignis eines Eintrags mit Umgebung, Release, URL und Stacktrace:
curl -s -H "Authorization: Bearer $T" "$B/issues/<ID>/events/latest/" | python3 -c "
import json,sys
e=json.load(sys.stdin); tags={t['key']:t['value'] for t in e.get('tags',[])}
print('env:',tags.get('environment'),'| release:',tags.get('release'),'| area:',tags.get('area'),'| browser:',tags.get('browser'))
for en in e.get('entries',[]):
if en['type']=='exception':
for v in en['data'].get('values',[]):
print('EXC',v.get('type'),':',(v.get('value') or '')[:300])
for f in ((v.get('stacktrace') or {}).get('frames') or [])[-8:]:
print(' ',f.get('filename') or f.get('absPath'),f.get('function'),f.get('lineNo'),f.get('colNo'))
if en['type']=='request': print('REQ',en['data'].get('url'))"
Mehrere Ereignisse eines Eintrags: $B/issues/<ID>/events/?limit=10.
Projekte: $B/projects/.
Weboberfläche: https://errors.adametz.media/adametz-media/issues?project=1.
4. Aufgabe: GlitchTip auswerten und Fehler beheben
Wenn der Auftrag lautet „schau in GlitchTip“, „was sagt GlitchTip“ o. Ä.:
-
Abrufen. Offene Einträge beider Projekte, zuerst
environment=production, dann ohne Filter. -
Einordnen — jeder Eintrag in genau eine Klasse:
Klasse Erkennen Vorgehen Test-/Entwicklungsrauschen Umgebung local, Texte aus Tests (Abschnitt 2)Nichts am Code; Betreiber markiert „Resolved“. Taucht es mit productionauf → echter FehlerBedienfehler am Server z. B. CommandNotFoundExceptionIn dontReportaufnehmen, falls wiederkehrendExterner Dienst vorübergehend Timeouts/5xx von Google, OpenAI, Stripe … Retry + Warnung statt report(), Abbruch- und Zeitbudget; Muster:SearchConsoleClient+SearchConsoleUnavailableEchter Bug Stacktrace in app/,resources/, Browserfehler mit eigener Datei/URLSchritte 3–6 Unklar z. B. Error: [object Object]Erfassung verbessern (mehr Kontext, keine personenbezogenen Daten), auf das nächste Auftreten warten -
Code finden. Stacktrace (
filename,function,lineNo),culprit, URL (REQ), Bereich (area). Bei Browserfehlern zeigen die Frames oft nurlivewire.min.js— der Hinweis steckt dann im Funktionsnamen (z. B.[Alpine] __('…')= Alpine-Ausdruck) → inresources/viewsnach dem Ausdruck suchen. -
Reproduzieren mit rotem Test, dann Fix (Projektregel: jede Änderung mit Test). Ist der Fehler ein Muster, das wieder auftreten kann, einen Wächtertest über alle Dateien schreiben (Beispiele:
BladePhpBlockGuardTest,BladeAlpineTranslationGuardTest). -
Qualitätsgates: betroffene Tests, dann
php artisan test --compact --parallel,vendor/bin/phpstan analyse --memory-limit=2G,vendor/bin/pint --dirty --format agent; bei JSnpm run build. -
Dokumentieren: Eintrag in Abschnitt 7 (ID, Klasse, Ursache, Fix, Commit). Commit-Nachricht nennt die GlitchTip-ID.
-
Ausliefern über den nächsten Deploy (Hotfix: letzte Versionsstelle erhöhen). Ablauf seit
v1.1.1: Git-Deploy per Tag,../betrieb/git-deploy.mdAbschnitte C und D (Assets bauen und committen, Tag, Push, auf dem Serverdeploy.sh). -
Auflösen in GlitchTip macht der Betreiber (Token ist nur lesend) — erst nach dem Deploy. Kommt der Fehler mit neuem Release wieder, öffnet GlitchTip den Eintrag erneut.
5. Regeln, die nicht verletzt werden dürfen
- Datenschutz (M4):
send_default_piibleibtfalse,max_request_body_sizebleibtnever, Log- und Cache-Breadcrumbs bleiben aus,ErrorReportScrubberbleibt inbefore_send. Kein Name, keine E-Mail, keine IP an GlitchTip — nur die interne User-ID. Neue Query-Parameter, die mitgehen sollen, nur überErrorReportScrubber::AllowedQueryParameters(und dieselbe Liste inerror-reporting.js/ Umami-Filter). - Keine variablen Zahlen in Fehlermeldungen, wenn sie gruppiert werden sollen: GlitchTip gruppiert nach Text.
…after 20002 msund…after 20001 mswurden drei getrennte Einträge (Issues 11, 13, 14). Variable Werte in den Kontext, nicht in die Meldung — oder einen Fingerprint setzen wieErrorSignal. - Vorübergehende Fremdfehler nicht einzeln melden. Sonst flutet ein Google-Ausfall GlitchTip und verdeckt echte Fehler.
- Tests melden nie an GlitchTip (Abschnitt 2). Neue Sentry-Tests nur mit
FakeGlitchTip. - Token nur lesend. Für Schreibrechte (Auflösen per API) erst mit dem Betreiber sprechen.
6. Konfiguration
| Variable | Wo | Wert |
|---|---|---|
SENTRY_LARAVEL_DSN |
.env |
DSN Projekt 1 |
SENTRY_BROWSER_DSN |
.env |
DSN Projekt 2 (öffentlich, steht im HTML) |
SENTRY_ENVIRONMENT |
.env |
production (Live) bzw. local |
SENTRY_RELEASE / APP_VERSION |
.env |
leer lassen — kommt aus der Datei RELEASE |
GLITCHTIP_API_TOKEN |
nur lokale .env |
Lese-Token für Abschnitt 3 |
Release: App\Support\Monitoring\Release::current() liest APP_VERSION
bzw. SENTRY_RELEASE, sonst die Datei RELEASE im Projektwurzelverzeichnis.
Seit dem Git-Deploy schreibt dev/betrieb/deploy.sh sie beim Deploy (echo "$tag" > RELEASE),
GlitchTip zeigt also genau den ausgelieferten Tag. Bei den SFTP-Deploys bis
v1.1.0 wurde sie von Hand erzeugt; daher stammen Releases wie
v1.1.0-3-gb1cec16 in älteren Einträgen.
Nach Änderung: php artisan config:cache.
7. Protokoll der Einträge
Stand 06.10.2026 (Abruf per API). „Fix“ = im Code behoben; ausgeliefert mit dem nächsten Deploy.
| ID | Projekt | Umgebung | Eintrag | Klasse | Ursache / Maßnahme | Stand |
|---|---|---|---|---|---|---|
| 1 | Server | local | GlitchTip-Test Server | Test | Anbindungstest 05.10. | auflösen |
| 8 | Server | production | Deploy-Test v1.1.0 | Test | Deploy-Prüfung 05.10. | auflösen |
| 3, 16 | Server | local | Queue weg | Test-Rauschen | ExpireGrandfatheringTest meldete an echte DSN |
Fix 2f02acc, auflösen |
| 5, 17 | Server | local | Datenbank nicht erreichbar | Test-Rauschen | PressReleaseSchedulingTest |
Fix 2f02acc, auflösen |
| 4 | Server | local | no such table: conversion_events | Test-Rauschen | SQLite im Test | Fix 2f02acc, auflösen |
| 6 | Server | local | Wasserstandsmarke steht auf 1 statt 0 | Test-Rauschen | Konkurrenztest der Aufruf-Aggregation | Fix 2f02acc, auflösen |
| 7 | Server | local | no role named customer |
Test-Rauschen | Tests ohne Rollen-Seeder | Fix 2f02acc, auflösen |
| 9 | Server | production | Command "config:cachels" is not defined | Bedienfehler | Tippfehler auf dem Server | dontReport (16af374); auflösen |
| 11, 13, 14 | Server | production | cURL error 28 … searchconsole.googleapis.com | Extern | Google URL Inspection hing; jeder Timeout einzeln gemeldet, Lauf 1¾ h | Fix a90f24a: Retry, Warnung statt Meldung, Abbruch nach 5 in Folge, 40-min-Budget; nach Deploy auflösen |
| 12 | Server | production | URL Inspection API antwortet mit 500 | Extern | Google-interner Fehler | wie 11 |
| 15 | Browser | production | ReferenceError: __ is not defined | Bug | /register: :placeholder="__('…')" an <input> → Alpine wertet PHP-Helfer im Browser aus |
Fix 16af374: placeholder="{{ __('…') }}", Wächtertest BladeAlpineTranslationGuardTest; nach Deploy auflösen |
| 10 | Browser | production | Error: [object Object] | Unklar | Promise-Ablehnung mit Objekt auf businessportal24.com/de |
Erfassung verbessert (16af374, Typ + Inhalt); nach Deploy neues Auftreten abwarten |