Skip to content

bconti123/RuntimeCatch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RuntimeCatch

A self-hostable observability platform for runtime errors, service health, and deployments: a single-developer answer to "where did this break, and why?"

Live demo: https://runtimecatch.up.railway.app

Built with Next.js 16 (App Router, Server Components, Server Actions), Prisma 7 + PostgreSQL 16, TypeScript, Tailwind v4, and Zod. Auth is credentials-based; ingestion is project-scoped behind hashed API keys. No third-party auth or telemetry SDKs, just node:crypto.


Demo credentials

Sign in to the live demo with:

  • Email: owner@runtimecatch.dev
  • Password: runtimecatch

All demo data is seeded and fake. Services, issues, deployments, and events are generated by prisma/seed.ts and a background simulator. Nothing in the demo represents real traffic.


Screenshots

Dashboard Issue detail
Dashboard: stat cards, hourly event volume, severity / category breakdowns Issue detail: stack trace, metadata, deploy correlation, resolve / mute / reopen
Service detail API keys
Service detail: health, deploy history, event timeline API keys: create-once flow, SHA-256 hashed at rest, project-scoped, revocable

Technical highlights

  • Credentials auth: passwords hashed with scrypt (node:crypto), opaque httpOnly session cookies, Secure in production.
  • Project-scoped API keys: generated once, stored only as SHA-256 hashes; the plaintext is never reachable from the database.
  • Bearer-protected ingestion: POST /api/events authenticates every request against a key's project before accepting an event.
  • Fingerprint-based issue grouping: events collapse into issues by a deterministic fingerprint, so recurring errors increment an occurrence count instead of flooding the feed.
  • Prisma / PostgreSQL schema: a relational model for projects, services, issues, alerts, deployments, and runtime events.
  • Docker local development: web + Postgres run in Compose, isolated from any other local stack.
  • TypeScript SDK and CLI: a typed client (@runtimecatch/client) and a dependency-free CLI for wiring services in and firing test events.

Architecture overview

  SDK / CLI  ->  POST /api/events  ->  PostgreSQL   ->  Next.js dashboard
 (your apps)     (Bearer-authed)      (via Prisma)      (Server Components)
  • A Next.js dashboard (App Router + Server Components) renders services, issues, and metrics.
  • PostgreSQL + Prisma form the data layer for every entity in the system.
  • The /api/events ingestion endpoint authenticates a project API key, validates the payload with Zod, and persists a runtime event.
  • The TypeScript SDK and CLI send events to that endpoint from any application.
  • On ingestion, each event is fingerprinted and grouped into an issue; the same data feeds the dashboard's charts and per-service health.

SDK integration

Install the local client (@runtimecatch/client), configure it once at module load, then capture from anywhere:

// lib/runtimecatch.ts
import "server-only";
import { configureRuntimeCatch } from "@runtimecatch/client";

configureRuntimeCatch({
  apiUrl: process.env.RUNTIMECATCH_API_URL!,   // e.g. https://your-instance.up.railway.app
  apiKey: process.env.RUNTIMECATCH_API_KEY!,   // project key from /settings/api-keys
  service: process.env.RUNTIMECATCH_SERVICE!,  // must exist in the key's project
  environment: process.env.RUNTIMECATCH_ENVIRONMENT ?? "development",
});

export { captureEvent, captureException } from "@runtimecatch/client";
// report a structured event from a server action
await captureEvent("post.published", { title, userId: "usr_123" });

// report a caught exception from a route handler
try {
  // ...
} catch (err) {
  await captureException(err, { route: "GET /api/widgets" });
}

A copy-paste-ready example lives in examples/nextjs-app/. The SDK isn't on npm yet: vendor packages/runtimecatch-client/dist/ or install via a local path (npm install file:...); the example walks through both.


Quick start (local, npm)

Clone to a live dashboard with streaming events in about five minutes:

git clone https://github.com/bconti123/RuntimeCatch.git && cd RuntimeCatch
npm install
cp .env.example .env
npm run db:up && npm run db:migrate && npm run db:seed
npm run dev

Then open localhost:3000, sign in with the demo credentials above, and run npm run simulate in another terminal to stream realistic events. The seeded demo API key (local dev only) is:

rc_live_demo_key_for_local_testing_only

Send an event to confirm the ingestion path:

curl -X POST http://localhost:3000/api/events \
  -H "Authorization: Bearer rc_live_demo_key_for_local_testing_only" \
  -H "Content-Type: application/json" \
  -d '{
    "service": "playback-service",
    "severity": "CRITICAL",
    "category": "PLAYBACK_ERROR",
    "message": "DRM license timeout",
    "metadata": { "region": "us-west", "device": "smart-tv" }
  }'

Drop the Authorization header and the same request returns 401.


Docker local development

Web + Postgres run together in Compose, isolated from any other local stack:

cp .env.example .env                       # host ports + database config live here
docker compose up --build
# once the web container is healthy, in another terminal:
docker compose exec web npx prisma migrate dev
docker compose exec web npm run db:seed

Then visit localhost:3000 and sign in. Host ports are configurable in .env (WEB_PORT, POSTGRES_HOST_PORT) without affecting anything inside the Compose network. The web service uses a Docker-internal DATABASE_URL (the postgres service name) that overrides the host value from .env, so switching between npm run dev and docker compose up needs no edits.

docker compose logs -f web    # tail dev server output
docker compose down           # stop (data persists)
docker compose down -v        # stop and wipe the database

CI/CD and Deployment

GitHub Actions (.github/workflows/ci.yml) runs on every push and pull request and must pass before changes ship. It installs with npm ci, generates the Prisma client, then runs npm run lint, npm run typecheck, and npm run build — so a broken lint, type error, or build failure is caught in CI rather than after it's live. The standalone examples/ app is a copy-paste SDK sample, not part of the deployed build, and is excluded from both lint and typecheck.

Railway auto-deploys from main: a web service plus a managed PostgreSQL service. A merge to main triggers a deploy once CI is green.

A railway.json builds with Nixpacks (the local-only Dockerfile.dev is never used by Railway) and starts with npm run start:prod, which runs prisma migrate deploy immediately before next start. Migrations therefore apply on every deploy, with no separate release step. The production database must be Railway's managed Postgres (${{Postgres.DATABASE_URL}}) — never a localhost URL.

Required environment variables:

Variable Notes
DATABASE_URL Reference the Postgres service as ${{Postgres.DATABASE_URL}}.
SESSION_SECRET Secret for session/CSRF signing; generate with openssl rand -hex 32.
NODE_ENV Set to production (Railway does this), enabling Secure cookies and quieter Prisma logs.

PORT is injected by Railway and bound automatically by next start. To deploy: create a Railway project from this GitHub repo, add a PostgreSQL service, set the variables above, and deploy. Seed demo data once with npm run db:seed (via Run a command or railway run), then generate a public domain.


API: POST /api/events

Authenticated with Authorization: Bearer <project-api-key>.

Field Type Required
service string yes, must exist in the API key's project
severity enum yes: DEBUG | INFO | WARNING | ERROR | CRITICAL
category enum yes: RUNTIME_ERROR | API_LATENCY | PLAYBACK_ERROR | DEPLOYMENT | DATABASE | NETWORK | AUTH | APP_EVENT
message string yes, up to 2,000 chars
stackTrace string no, up to 20,000 chars
metadata object no, arbitrary JSON
fingerprint string no, overrides the auto-computed value
occurredAt ISO 8601 no, defaults to now()

Responses: 201 with { eventId, issueId, fingerprint, occurrenceCount }, 400 on validation failure, 401 on a missing/invalid/revoked key, 404 if the service isn't in the key's project.


CLI: runtimecatch

A dependency-free developer CLI for wiring a service in and firing test events without hand-writing curl. Run npm link once to put it on your PATH, or use npm run cli -- <command>.

runtimecatch init          # create / update .runtimecatchrc.json
runtimecatch env           # print current config (API key masked)
runtimecatch test          # send a simple INFO event to /api/events
runtimecatch send-error    # send a sample ERROR event with stackTrace + metadata

Scripts

Command Purpose
npm run dev Next.js dev server
npm run build Production build
npm run db:up / db:down Start / stop the Postgres container
npm run db:migrate Apply Prisma migrations
npm run db:reset Drop, migrate, reseed in one shot
npm run db:seed Run prisma/seed.ts
npm run db:studio Open Prisma Studio
npm run simulate Stream realistic events into the DB
npm run cli -- <cmd> Run the runtimecatch CLI without a global link

Roadmap

Ordered roughly by what's most worth doing next given the current codebase:

  • Saved views + full-text search: tsvector indexes on issues; Postgres can carry this without a separate search service.
  • Slack / webhook notifications on alert transitions: route Alert.status changes through an outbox table so retries and dedupe are explicit.
  • Per-IP rate limiting on /login and /api/events, plus CSRF tokens on the logout form.
  • Multi-tenant teams + org roles: the schema already centers on Project.ownerId; adding Membership(userId, projectId, role) is mostly a join.
  • Source-map symbolication for stack traces, run as a background job after ingestion (the point where a queue starts to earn its place).
  • Argon2id in place of scrypt once the auth surface stabilizes; lib/auth.ts is already shaped for the swap.

License

MIT. See LICENSE.

About

Full-stack observability platform for monitoring service health, runtime events, API failures, and deployment activity in realtime.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors