๐ Error Tracking (GlitchTip) โ Developer Guide
Overview
Mallnline uses GlitchTip โ a self-hosted, open-source error tracking platform โ to capture unhandled errors, uncaught promise rejections, and performance traces from Visitors' and Buyers' browsers. GlitchTip is fully compatible with the Sentry SDK, so the frontend uses @sentry/sveltekit under the hood.
| Component | Purpose | Technology |
|---|---|---|
| GlitchTip Web | Dashboard for viewing errors, stack traces, and breadcrumbs | Docker (glitchtip/glitchtip) |
| GlitchTip Worker | Background processing (event ingestion, cleanup) | Celery beat + Redis |
| Frontend SDK | Client-side error capture and performance tracing | @sentry/sveltekit |
| User Context | Associates errors with authenticated Visitors/Buyers | sentryContext.ts utility |
Why GlitchTip?
- Self-hosted โ all error data stays on your infrastructure. No third-party data processing.
- Sentry SDK compatible โ drop-in DSN swap if you ever want to migrate to Sentry cloud or back.
- Lightweight โ runs on ~1 GB RAM alongside existing Postgres and Redis.
- Free at any scale โ no per-event pricing, no seat limits.
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Browser (Visitor) โ
โ โ
โ @sentry/sveltekit SDK โ
โ hooks.client.ts โ
โ โ
โ DSN โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ GlitchTip :8000 โ
โ โ
โ โโโโโโโโโโโโโโโโโโ โ
โ โ Web Dashboard โ โ โโโ Developers view errors here
โ โโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโ โ
โ โ Celery Worker โ โ โโโ Background event processing
โ โโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโดโโโโโ โ
โ โผ โผ โ
โ Postgres Redis โ โโโ Shared with federation stack
โ (DB 0) (DB 1) โ
โโโโโโโโโโโโโโโโโโโโโโโโ
GlitchTip reuses the existing ngwenya-postgres instance (separate ngwenya_glitchtip database) and Redis (database index 1, to avoid conflicts with the gateway cache on DB 0).
Production note: In production, GlitchTip should run as a fully separate deployment with its own dedicated Postgres and Redis instances โ no shared resources with the application databases.
Quick Start
1. Start GlitchTip
# From ngwenya-federation/
make glitchtip-up
This single command:
- Starts Postgres, Redis, GlitchTip web, and the Celery worker
- Waits for the health check
- Auto-runs
make glitchtip-setupwhich:- Creates the
ngwenya_glitchtipdatabase (idempotent) - Runs Django migrations
- Creates the admin account (
mallnline.dev@gmail.com/admin123) - Generates an API token via Django ORM
- Injects the token into
apps/tower/.env
- Creates the
Dashboard: http://localhost:8000
2. Configure the Frontend
Set the DSN in ngwenya-front/.env:
PUBLIC_SENTRY_DSN=http://73b493b8de6049d4b08cdce5aa5a4c4f@localhost:8000/1
PUBLIC_SENTRY_ENVIRONMENT=beta
Finding your DSN: Log in at
http://localhost:8000โ open your project โ Settings โ Client Keys (DSN)
Restart the dev server (pnpm run dev). Errors will now appear in the GlitchTip dashboard.
3. Start the Tower Subgraph
make restart-tower
Tower reads the auto-injected GLITCHTIP_API_TOKEN from apps/tower/.env and connects to the GlitchTip REST API. The Tower admin dashboard Error Tracking widgets will now show live data.
4. Verify
Send a test error directly to GlitchTip to confirm the ingestion pipeline works:
# From ngwenya-federation/
make glitchtip-test
This sends a curl request to the Sentry store API using your project's DSN key. If you see โ
Event accepted, check http://localhost:8000 โ the error should appear under Issues.
You can also verify from the browser by opening DevTools Console on your running frontend and running:
// setTimeout wrapper ensures Sentry's global handler catches it
// (a bare throw in the console is caught by DevTools, not the SDK)
setTimeout(() => { throw new Error('GlitchTip browser test'); }, 0);
Tip: If browser errors aren't showing up, make sure you restarted the dev server after setting
PUBLIC_SENTRY_DSNโ env vars are only read at startup.
Make Targets
The backend Makefile provides six GlitchTip targets:
| Command | Description |
|---|---|
make glitchtip-up |
Start GlitchTip + dependencies, wait for health check |
make glitchtip-setup |
First-time setup: create DB, run migrations, create admin account |
make glitchtip-test |
Send a test error via curl to verify event ingestion |
make glitchtip-down |
Stop GlitchTip containers (leaves DBs running) |
make glitchtip-logs |
Tail GlitchTip web + worker logs |
make glitchtip-status |
Show container status + health check |
Frontend SDK Integration
Initialization (`hooks.client.ts`)
The SDK is initialized in src/hooks.client.ts โ the SvelteKit client-side error hook. Key behaviors:
import * as Sentry from '@sentry/sveltekit';
if (browser) {
const dsn = import.meta.env.PUBLIC_SENTRY_DSN;
if (dsn) {
Sentry.init({
dsn,
environment: import.meta.env.PUBLIC_SENTRY_ENVIRONMENT || 'beta',
sendDefaultPii: false, // GDPR-safe
tracesSampleRate: 0.2, // 20% of navigations traced
});
}
}
export const handleError = Sentry.handleErrorWithSentry(ngwenyaErrorHandler);
Design decisions:
- No-op without DSN โ if
PUBLIC_SENTRY_DSNis not set, no Sentry code runs. Safe for local dev without Docker. sendDefaultPii: falseโ no IP addresses, user-agent strings, or cookies are sent automatically. GDPR-compliant by default.tracesSampleRate: 0.2โ only 20% of page navigations generate performance traces. Keeps volume manageable.- Header scrubbing โ
authorization,x-org-id,x-guest-id, andcookieheaders are stripped from all transaction payloads viabeforeSendTransaction.
User Context (`sentryContext.ts`)
When a Visitor logs in, their identity is synced to GlitchTip so that error reports show who was affected:
import { setSentryUser } from '$lib/services/sentryContext';
// On login
setSentryUser({ handle: 'v|meekdenzo', email: 'user@example.com', id: '...' });
// On logout
setSentryUser(null);
The +layout.svelte root layout subscribes to authStore changes and calls setSentryUser automatically โ no manual wiring needed in individual pages.
Security: User context uses the
handle(e.g.,v|meekdenzo) as the identifier, not raw UUIDs. This complies with the platform's identity security guardrails.
Vite Plugin
The sentrySvelteKit() Vite plugin is configured in vite.config.ts with source map upload disabled (GlitchTip doesn't support the Sentry source map upload API):
import { sentrySvelteKit } from '@sentry/sveltekit';
plugins: [
sentrySvelteKit({
autoUploadSourceMaps: false
}),
sveltekit(),
// ...
]
The plugin must appear before sveltekit() in the plugins array.
Manual Error Capture
Beyond automatic unhandled error capture, you can manually report errors anywhere in the frontend:
import * as Sentry from '@sentry/sveltekit';
try {
await riskyOperation();
} catch (error) {
Sentry.captureException(error, {
tags: { component: 'ucart-checkout', maletId: 'm|luminara' },
extra: { cartItemCount: 3, totalAmount: 'R150.00' }
});
}
Adding Breadcrumbs
Breadcrumbs provide a trail of events leading up to an error โ clicks, navigations, and network requests are captured automatically. You can add custom breadcrumbs for domain-specific actions:
Sentry.addBreadcrumb({
category: 'ucart',
message: 'Added item to uCart',
data: { productId: 'prod_123', maletHandle: 'm|luminara' },
level: 'info'
});
Environment Variables
Frontend (`ngwenya-front/.env`)
| Variable | Required | Default | Description |
|---|---|---|---|
PUBLIC_SENTRY_DSN |
No | โ | GlitchTip project DSN. Error tracking is disabled when unset. |
PUBLIC_SENTRY_ENVIRONMENT |
No | beta |
Environment tag attached to all events |
Backend (`docker-compose-dev.yaml`)
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
postgres://...ngwenya_glitchtip |
GlitchTip's PostgreSQL database |
REDIS_URL |
redis://redis:6379/1 |
Redis on database 1 (avoids gateway conflicts) |
SECRET_KEY |
Dev placeholder | Django secret key โ change in production |
GLITCHTIP_DOMAIN |
http://localhost:8000 |
Public URL for the dashboard |
ENABLE_OPEN_USER_REGISTRATION |
true |
Allow anyone to register (dev only) |
GLITCHTIP_MAX_EVENT_LIFE_DAYS |
90 |
Auto-prune events older than 90 days |
Docker Infrastructure
GlitchTip runs as two containers in docker-compose-dev.yaml:
# Web dashboard + event ingestion API
glitchtip:
image: glitchtip/glitchtip:latest
ports:
- "8000:8000" # Dashboard + DSN endpoint
depends_on:
- postgres
- redis
# Background worker (Celery beat)
glitchtip-worker:
image: glitchtip/glitchtip:latest
command: bin/run-celery-with-beat.sh
depends_on:
- postgres
- redis
The ngwenya_glitchtip PostgreSQL database is auto-created by infra/postgres/init-uchat-db.sh alongside the existing ngwenya_uchat database.
What Gets Captured
| Event Type | Automatic? | Details |
|---|---|---|
| Unhandled errors | โ | JavaScript runtime errors, uncaught promise rejections |
| Console errors | โ | console.error() calls captured as breadcrumbs |
| Network requests | โ | XHR/fetch requests + responses captured as breadcrumbs |
| User clicks | โ | DOM click events captured as breadcrumbs |
| Page navigations | โ | SvelteKit route changes captured as breadcrumbs |
| Performance traces | โ (sampled) | 20% of navigations generate full timing traces |
| Custom errors | Manual | Use Sentry.captureException() or Sentry.captureMessage() |
| Session replays | โ | Not supported by GlitchTip |
What Is NOT Captured
- PII โ
sendDefaultPii: falseprevents automatic capture of IP addresses and cookies - Auth tokens โ
authorization,x-org-id,x-guest-id, andcookieheaders are scrubbed from traces - Raw UUIDs โ user context uses handles, not database IDs
- Server-side errors โ this integration is client-side only; server errors go through the Alerts pipeline
Migrating to Sentry Cloud
Because the frontend uses @sentry/sveltekit (the standard Sentry SDK), migration to Sentry's hosted cloud is a one-line change:
- PUBLIC_SENTRY_DSN=http://abc123@localhost:8000/1
+ PUBLIC_SENTRY_DSN=https://abc123@o123456.ingest.sentry.io/456789
No code changes needed. You'll also gain access to Sentry-exclusive features:
- Session Replay (video-like error reproductions)
- Source map upload (readable stack traces)
- Advanced alerting rules and dashboards
Related
- Tower Subgraph โ Rust/Axum subgraph that proxies GlitchTip REST API into the federated GraphQL schema for admin dashboard integration
- Tower Health Observability โ Dual-layer health probing that runs alongside the error tracking proxy in the same Rust service
- Gateway Tracing & Observability โ Backend observability: response caching, APQ, per-operation tracing, and Prometheus metrics
- Alerts Resilience & Delivery Tracking โ Server-side notification pipeline with DLQ, retry, and delivery audit logs
- Frontend Debugging Playbook โ Step-by-step methodology for diagnosing silent UI failures in Svelte 5
- Local Development Environment โ Full federation stack setup with Podman, Make targets, and development workflows
- Privacy & Security โ GDPR compliance, data handling policies, and identity security guardrails