Monitorering
Komplett oversikt over monitorering, logging, analytics, infrastrukturkostnader og rate limiting.
Observability-stack
heading.anchorLabel Hva gikk galt? Hva gjoer brukerne? ┌─────────────┐ ┌────────────────┐ │ Sentry │ │ TelemetryDeck │ │ (errors) │ │ (analytics) │ └──────┬──────┘ └───────┬────────┘ │ │ ┌──────────────────┼────────────────────────┼──────────┐ │ │ App │ │ │ ┌──────────────┴───┐ ┌───────┴───────┐ │ │ │ API (Fastify) │ │ iOS (SwiftUI) │ │ │ │ • Sentry (5xx) │ │ • Sentry │ │ │ │ • Pino (events) │ │ (crashes) │ │ │ │ • Queue errors │ │ • TelemetryDeck│ │ │ └────────┬─────────┘ │ (18 signals)│ │ │ │ └───────────────┘ │ │ ┌────────┴─────────┐ │ │ │ Railway │ │ │ │ (logs + metrics) │ │ │ └──────────────────┘ │ └──────────────────────────────────────────────────────┘| Verktoey | Jobb | Lag | Kostnad |
|---|---|---|---|
| Sentry | Errors, crashes, ANR | API + iOS | $0 (5K events/mnd) |
| TelemetryDeck | Brukeratferd, funnels | iOS | $0 (100K signals/mnd) |
| Pino structured logs | Business events, audit trail | API → Railway | $0 |
| Railway Metrics | CPU, memory, requests | Infrastruktur | $0 |
Sentry — Error Monitoring
heading.anchorLabelHva fanges
heading.anchorLabel| Kilde | Fanges automatisk | Ignoreres |
|---|---|---|
| API 5xx errors | Ja | 4xx, validering, business errors |
| Queue final failures (etter 3 retries) | Ja | Retry-forsoek |
| Queue worker errors | Ja | — |
| Queue stalled jobs | Warning | — |
| iOS crashes | Ja | — |
| iOS app hangs (>5s) | Ja | — |
| iOS KMP bridge errors | Selektivt manuelt | Nettverksfeil, forventede feil |
Konfigurasjon
heading.anchorLabel- API:
@sentry/nodei Fastify. Init iapps/api/src/lib/sentry.ts - iOS:
sentry-cocoavia SPM. Init iiosApp/Services/SentryService.swift - PII-scrubbing: Brukerinnhold (impulstekst, refleksjoner, notater) redigeres i
beforeSend - Aktivert: Kun production (
NODE_ENV=productionfor API,#if !DEBUGfor iOS) - Sample rates:
sampleRate=1.0,tracesSampleRate=0,profilesSampleRate=0
Viktige filer
heading.anchorLabelAPI:
| Fil | Hva |
|---|---|
src/lib/sentry.ts | Config, PII scrubbing, hjelpefunksjoner |
src/server.ts | Foerste import, Fastify-integrasjon, shutdown flush |
src/middleware/error-handler.ts | Kun 5xx-fangst |
src/middleware/auth.ts | User context (userId, tier) |
src/queues/base/bullmq-job-queue.ts | Final failures, worker errors, stalled jobs |
iOS:
| Fil | Hva |
|---|---|
Services/SentryService.swift | Config, PII scrubbing, hjelpefunksjoner |
ImpulseApp.swift | Init (foer KMP), user context etter auth |
ContentView.swift | Tab navigation breadcrumbs |
Stores/KMPStoreProvider.swift | Error bridge, clear user paa logout |
Environment-variabler
heading.anchorLabel| Variabel | Hvor | Kilde |
|---|---|---|
SENTRY_DSN | Railway (Doppler) | Sentry project settings (im-api) |
RAILWAY_GIT_COMMIT_SHA | Railway | Automatisk |
| DSN (iOS) | Hardkodet i SentryService.swift | Sentry project settings (im-ios) |
TelemetryDeck — User Analytics
heading.anchorLabelPrivacy-first, GDPR-compliant (ingen samtykke-dialog noedvendig). Signals sendes kun fra iOS.
Signals (18 totalt)
heading.anchorLabelKonverteringsflow (8):
| Signal | Parametere | Trigger |
|---|---|---|
app.launched | — | App start |
onboarding.completed | personalized | Onboarding ferdig |
onboarding.skipped | — | Onboarding hoppet over |
impulse.captured | classification, source | Impuls opprettet |
session.started | classification | Sesjon startet |
session.completed | classification, durationSeconds | Alle 5 steg fullfoert |
session.abandoned | classification, lastStep | Sesjon avbrutt |
checkin.completed | outcome | AI-vurdering mottatt |
Monetisering (5):
| Signal | Parametere | Trigger |
|---|---|---|
paywall.shown | trigger | Paywall vist |
paywall.dismissed | trigger | Paywall lukket uten kjoep |
purchase.completed | tier, fromTrial | StoreKit-kjoep vellykket |
purchase.failed | tier, errorType | StoreKit-kjoep feilet |
trial.expired | — | Trial utloept uten konvertering |
Engasjement (2):
| Signal | Parametere | Trigger |
|---|---|---|
journey.searched | — | Soek brukt i Journey |
feedback.submitted | hasRating | Feedback sendt |
Konfigurasjon:
- Fil:
iosApp/Services/Analytics.swift - App ID:
CE8DB336-B6B9-4B6A-A725-915EE4B2E24F - Test mode:
truei DEBUG builds (filtreres i dashboard) - Signal-budsjett: ~3-5/dag per bruker (100K signals/mnd gratis = ~800 MAU)
Pino Business Events — API Structured Logging
heading.anchorLabelBusiness events logges til Railway via Pino. Soekbart paa event-feltet.
Events (14 totalt)
heading.anchorLabelRevenue: subscription.trial_started — Trial startet subscription.converted — Trial → betalt subscription.churned — Abonnement utloept/kansellert
Kjerneaktivitet: impulse.created — Impuls fanget impulse.classified — AI-klassifisering fullfoert impulse.resolved — Impuls markert som resolved session.started — Sesjon startet session.completed — Sesjon fullfoert
Feature adoption: checkin.completed — Sjekk-inn vurdering ferdig checkin.converted — Sjekk-inn → impuls
Verdilevering: insights.regenerated — Innsiktsprodukter oppdatert
Kostnad: ai.tokens.used — AI token-forbruk (brukerrettede workloads)
Churn & sentiment: account.deleted — Konto permanent slettet feedback.submitted — Brukertilbakemelding sendtFormat:
{ "level": "info", "event": "session.completed", "userId": "uuid", "sessionId": "uuid", "msg": "Business event"}Filter i Railway logs: soek etter "Business event" eller spesifikt "event": "session.completed".
Hva som IKKE logges
heading.anchorLabel- CRUD-operasjoner (arkiver, oppdater, slett)
- Leseoperasjoner (list, get, view)
- Hoeyfrekvente events (scroll, tap, navigasjon)
- Interne AI-workloads (distillation, narrative, pulse) — sporet i DB, ikke logger
- Brukerinnhold (PII scrubbed)
Logging-standarder
heading.anchorLabel| Lag | Produksjon | Utvikling |
|---|---|---|
| API (Pino) | Strukturert JSON til stdout → Railway logs | Pretty-printed med pino-pretty |
| iOS (AppLogger) | Kun error() og warning() | debug() tilgjengelig |
| KMP (Logger) | LogLevel.WARN | LogLevel.INFO |
Rate Limiting
heading.anchorLabelTre nivaaer av rate limiting, drevet av Redis (fallback til in-memory):
| Type | Grense | Tidsvindu | Endepunkter |
|---|---|---|---|
| Global | 100 requests | 1 minutt | Alle |
| AI | 20 requests | 1 minutt | AI-endepunkter |
| GET | 200 requests | 1 minutt | Leseoperasjoner |
Verdiene kan overstyres via environment-variabler:
RATE_LIMIT_GLOBAL_MAX(default: 100)RATE_LIMIT_AI_MAX(default: 20)RATE_LIMIT_GET_MAX(default: 200)RATE_LIMIT_TIME_WINDOW(default: “1 minute”)
Abuse detection
heading.anchorLabelBrukere som treffer 429-grensen 10+ ganger innen 5 minutter rapporteres automatisk til Sentry som RateLimitAbuse. Cooldown paa 15 minutter foer re-rapportering.
Response headers
heading.anchorLabelAlle responses inkluderer rate limit headers:
X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-ResetRetry-After(kun ved 429)
AI-kostnadsmodell
heading.anchorLabelPer sesjon
heading.anchorLabel~$0.056 per sesjonssyklus (klassifisering + 5 steg guidance + summary).
Per aktiv bruker per maaned
heading.anchorLabel| Brukere | AI/bruker/mnd | Reduksjon | Mekanisme |
|---|---|---|---|
| 10K | $0.38 | — | Ingen caching |
| 100K | $0.25 | -35% | Prompt caching |
| 1M | $0.18 | -28% | Batch API + caching |
AI-kostnad utgjoer ~9% av revenue (blandet paa tvers av tiers).
Infrastrukturkostnader
heading.anchorLabelNaavaerende drift (~$38-53/mnd)
heading.anchorLabel| Tjeneste | Staging | Prod | Totalt |
|---|---|---|---|
| Supabase | Gratis | $25/mnd | $25/mnd |
| Railway (API + Redis) | Inkludert | $5-20/mnd | $5-20/mnd |
| Vercel | Gratis | Gratis | $0 |
| GitHub Actions | 2000 min/mnd gratis | Inkludert | $0 |
| Sentry | — | Gratis (5K events) | $0 |
| TelemetryDeck | — | Gratis (100K signals) | $0 |
| Apple Developer | — | $99/aar | $8/mnd |
Skaleringsgrenser
heading.anchorLabel| Brukere | Flaskehals | Tiltak | Ekstra kostnad |
|---|---|---|---|
| 0-10K | Ingenting | Naavaerende oppsett | $0/mnd |
| 10K-50K | Sentry + TelemetryDeck gratis-tier | Oppgrader begge | ~$35/mnd |
| 50K-200K | Railway single instance | Skaler til 3 instanser | ~$30/mnd |
| 200K-500K | Supabase connections | Oppgrader til Team plan | ~$300/mnd |
| 500K-1M | Anthropic rate limits | Volumavtale med Anthropic | Varierer |
Observability-kostnad per MAU
heading.anchorLabel| MAU | Sentry | TelemetryDeck | Totalt |
|---|---|---|---|
| 1K | $0 | $0 | $0 |
| 5K | $0 | $0 | $0 |
| 7K | $26/mnd | ~$19/mnd | ~$47/mnd |
| 10K | $26/mnd | ~$19/mnd | ~$47/mnd |
Begge verktoeyen forblir gratis til ~5-7K MAU.
Nyttige lenker
heading.anchorLabel| Tjeneste | Dashboard | Status |
|---|---|---|
| Railway | railway.app | status.railway.app |
| Supabase | supabase.com/dashboard | status.supabase.com |
| Anthropic | console.anthropic.com | status.anthropic.com |
| Sentry | sentry.io | status.sentry.io |
| TelemetryDeck | dashboard.telemetrydeck.com | — |
| App Store Connect | appstoreconnect.apple.com | developer.apple.com/system-status |