Getting started
Start the unified collector and get multiple signal types flowing into one dashboard.
This guide gets you from a fresh checkout to unified observability in the dashboard. The goal is not just to send a trace or a log; it is to see multiple signal types connected through the same collector and identity chain. There are two decisions:
- How do you want to run obs-unified? Use the all-in-one Docker image, or install and run the repo locally.
- What data do you want to look at? Use seeded sample data, the Astronomy Shop demo, or telemetry from your own app.
Choose how to run
| Runtime path | Use when | Starts |
|---|---|---|
| Option 1 — Docker image | You want the quickest first run with the fewest host dependencies. | Postgres, collector, dashboard, and filesystem blob store in one container: pull the prebuilt image from GHCR, or build the local image to include sample data. |
| Option 2 — local install | You want to edit code, run dev servers, or inspect internals while using the repo. | Local collector, demo API, and Vite dashboard from the workspace. |
Choose what to observe
| Data path | Use when | Start here |
|---|---|---|
| Seeded sample data | You want populated dashboards immediately. | Built into Option 1, or run pnpm run seed with Option 2. |
| Astronomy Shop demo | You want realistic microservice traffic and service-map edges. | Run the OpenTelemetry demo against your local collector. |
| Your own app | You want to validate obs-unified against a real application. | Add SDKs or OpenTelemetry exporters pointing at your collector. |
Prerequisites
- Docker: required for the Docker image and Astronomy Shop demo.
- Node.js 22+ and pnpm 10+: required for local install and repo scripts.
Option 1 — Docker image
This packages the full local stack into one container. It is the lowest-friction first run.
Prebuilt image from GHCR
No clone needed. The release image is published as
ghcr.io/dev-sawan-ruparel/obs-unified
and fails closed without your own credentials:
export INGEST_KEY="pick-a-long-random-ingest-key"
export DASHBOARD_PASSWORD="pick-a-dashboard-password"
export DASHBOARD_TOKEN="pick-a-read-token-for-mcp-and-cli"
docker run --rm \
-p 5173:5173 \
-p 8790:8790 \
-e INGEST_KEY \
-e DASHBOARD_PASSWORD \
-e DASHBOARD_TOKEN \
-e OBS_LOCAL_SEED=true \
-v obs-unified-db:/var/lib/postgresql \
-v obs-unified-blobs:/data \
ghcr.io/dev-sawan-ruparel/obs-unified:latestDashboard at http://localhost:5173, collector at http://localhost:8790.
Passing -e OBS_LOCAL_SEED=true populates all demo scenarios (traces, logs, AI
calls, Agent Action Graph, and AutoSRE Scenario D) immediately on first boot;
omit it when you want an empty collector for Astronomy Shop or your own app.
Build the local image with sample data
Build and run from the personal monorepo:
git clone https://github.com/dev-sawan-ruparel/obs-unified.git
cd obs-unified
pnpm install --frozen-lockfile
pnpm local:image
pnpm local:runOr use Docker directly:
docker build -f Dockerfile.local -t obs-unified/local:dev .
docker run --rm -p 5173:5173 -p 8790:8790 obs-unified/local:devAccess the interfaces:
| Interface | URL |
|---|---|
| Dashboard | http://localhost:5173 |
| Collector ingest | http://localhost:8790 |
To log in from a script, POST the dashboard password and keep the obs_session cookie. Logout only clears the browser cookie; the signed session stays valid until it expires (7 days) or DASHBOARD_PASSWORD is rotated.
curl -i -X POST http://localhost:5173/auth/login \
-H 'Content-Type: application/json' \
-d '{"password":"<DASHBOARD_PASSWORD>"}'
# set-cookie: obs_session=...; HttpOnly; SameSite=Strict; Max-Age=604800Credentials for the locally built image (pnpm local:run only; the prebuilt GHCR image rejects these values and requires your own, see Installation):
| Credential | Environment Variable | Local image value |
|---|---|---|
| Ingest write key | INGEST_KEY / OBS_INGEST_KEY | dev-ingest-key |
| Dashboard password | DASHBOARD_PASSWORD | e2e-test-pass |
| Read bearer token | DASHBOARD_TOKEN on the collector | e2e-dashboard-token |
Tokens and env vars
| Where | Variable | Purpose |
|---|---|---|
| Collector | INGEST_KEY | Write-only key that SDKs and exporters present to ingest telemetry. |
| Collector | DASHBOARD_PASSWORD | Browser login for the dashboard (POST /auth/login). |
| Collector | DASHBOARD_TOKEN | Read bearer token for /internal/*, the CLI, and MCP. |
| Client (CLI, MCP) | OBS_DASHBOARD_TOKEN | Canonical name for the value of the collector's DASHBOARD_TOKEN. Accepted by the CLI (doctor, keys, changes list), and @obsunified/mcp-server. |
| Client (CLI) | OBS_ADMIN_TOKEN, OBS_API_TOKEN | Aliases for OBS_DASHBOARD_TOKEN (verified against CLI 1.1.3 with doctor, keys list, and changes list). |
| Client (SDKs, CLI) | OBS_INGEST_KEY | The collector's INGEST_KEY, used by the SDKs and obs-unified changes record (OBS_API_KEY is also accepted by the CLI). |
To persist local database and blob storage state across container restarts:
docker volume create obs-unified-local-db
docker volume create obs-unified-local-blobs
docker run --rm \
-p 5173:5173 \
-p 8790:8790 \
-v obs-unified-local-db:/var/lib/postgresql \
-v obs-unified-local-blobs:/data \
obs-unified/local:devVerify the full first-run path:
pnpm smoke:local-imageThe smoke test builds the image, boots a fresh container, seeds data, and verifies collector health, dashboard HTML, and login from outside Docker.
Option 2 — local install
Use this when you are modifying dashboard code, collector code, or SDK packages.
git clone https://github.com/dev-sawan-ruparel/obs-unified.git
cd obs-unified
pnpm install
pnpm run setup
pnpm run devpnpm run setup creates apps/collector/.dev.vars from
apps/collector/.dev.vars.example if needed, then runs local migrations. If you
change the local dashboard password or ingest key later, pnpm run seed reads
the same file automatically.
The local dev stack exposes:
| Service | URL |
|---|---|
| Dashboard | http://localhost:5173 |
| Demo API | http://localhost:8787 |
| Collector | http://localhost:8790 |
Seeded sample data
Use this when you want populated dashboards immediately.
- Docker image: sample data is seeded automatically on startup.
- Local install: run the seeder in a second terminal.
pnpm run seedExpected result: Traces, Logs, AI Calls, Usage, and Issues show sample data. Replays require browser interaction, so open the dashboard's Playground tab and trigger a replay-producing interaction once.
Astronomy Shop demo
Use this when you want realistic microservice traffic and service-map edges. It runs the official OpenTelemetry Astronomy Shop demo and points its exporters at your local obs-unified collector.
This path assumes the collector is already running. For local development, start it with:
pnpm dev:collectorPrepare the upstream demo services:
pnpm demo:setup
pnpm demo:preflightLaunch the microservices:
pnpm demo:upAccess URLs:
| Interface | URL |
|---|---|
| Dashboard | http://localhost:5173 |
| Shop web interface | http://localhost:8080 |
The load generator takes roughly 30 seconds to begin driving traffic. Once running, Traces, Service Maps, Issues, Logs, and Metrics populate dynamically from active microservice calls.
Stop and remove the compose stack:
pnpm demo:downYour own app
This is a data path that sends telemetry to whichever collector you started above.
| Target | Setup guide |
|---|---|
| React/Vite frontend + Hono API | React + Hono walkthrough |
| Python Flask API | Python Flask walkthrough |
| Browser-only application | Analytics SDK reference |
| TypeScript backend | Telemetry SDK reference |
| Polyglot recipes | Examples |
Application compatibility & signal matrix
Before instrumenting an application (or when an AI agent scouts your repository), use this matrix to verify which signals are supported for your architecture:
| Tier | Application shape | Supported signals | Notes & constraints |
|---|---|---|---|
| Tier 1 — Full First-Party Unified Stack | Browser SPAs & SSR web apps (React, Next.js, Vite, Vue, Svelte, Vanilla TS/JS) + TypeScript/Node/Edge backends (Cloudflare Workers, Hono, Express, Fastify) or Go/Rust services | Traces, Structured Logs, Metrics, Usage Events, rrweb DOM Session Replay, Click-to-Trace (x-obs-interaction), AI Calls, Agent Action Graph, CPU Profiles, AutoSRE Release Lineage & Feature Flags | Full out-of-the-box correlation via @obsunified/analytics-sdk, @obsunified/telemetry-sdk, @obsunified/sdk, sdks/go, and sdks/rust. |
| Tier 2 — Standard OpenTelemetry Backends | Python (Flask, FastAPI, Django), Java/Kotlin (Spring Boot), .NET, Ruby, PHP, C++ | OTLP HTTP Traces (/v1/traces), Logs (/v1/logs), Metrics (/v1/metrics), plus HTTP JSON ingest for AI Calls (/v1/ai), Agent Action Graph (/v1/actions, /v1/agent-runs, /v1/tool-calls), and Release Changes (/v1/changes) | Supports both OTEL_EXPORTER_OTLP_PROTOCOL=http/json and http/protobuf (with optional gzip). For browser click-to-trace correlation, read the incoming x-obs-interaction HTTP header and set span attribute obs.interaction.id. |
| Tier 3 — Partial or Constrained Shapes | Native Mobile (iOS, Android, React Native, Flutter) Headless / CLI / Cron Async Message Queues (Kafka, SQS, RabbitMQ, BullMQ) gRPC-only OTLP | Backend traces, logs, metrics, AI calls, and Action Graph (startAgentRun({ agentId, agentName, ... }, fn)) | Native mobile: No rrweb session replay (requires browser DOM).Queues: Producer must propagate traceparent / x-obs-interaction / x-obs-action-id in message headers or consumer spans appear as disconnected roots.gRPC OTLP: Collector endpoints speak HTTP ( application/json and application/x-protobuf); place an OTel Collector gateway in front if agents only emit gRPC. |
Common wiring & non-interactive scaffolding
- Deploy or run an accessible collector endpoint.
- Scaffold a pre-wired template (supports non-interactive flags for CI and AI agents) or install the SDKs into an existing app:
pnpm dlx @obsunified/cli create my-app \
--template react-vite \
--collector-url http://localhost:8790 \
--yesAvailable --template (-t) values: react-vite, vanilla-ts, hono-workers.
- Configure
OBS_COLLECTOR_URLand a write-only ingest key (INGEST_KEY). - Ensure API CORS policies allow
x-obs-interactionand your app's local dev origin (the Docker images allowlocalhost/127.0.0.1on ports5173,5174, and3000by default; add more with-e ALLOWED_ORIGINS="http://localhost:5173,http://localhost:4173", a comma-separated list that replaces the default). - Verify connectivity and CORS headers:
pnpm dlx @obsunified/cli doctor http://localhost:8790 --origin http://localhost:3000Autonomous AI agent setup & verification playbook
If you are an AI coding agent (Claude Code, Cursor, Codex, Antigravity, Windsurf) tasked with setting up Observability Unified for a user:
- Machine-readable documentation: Fetch
https://obsunified.com/llms.txt,https://docs.obsunified.com/llms.txt, orhttps://docs.obsunified.com/llms-full.txt, or install the prebuilt.skillbundles from theskills-v0.1.4release. - Step 1 (Assess fit): Inspect the user's
package.json,pyproject.toml,go.mod, orCargo.tomlagainst the Application compatibility & signal matrix above. Report clearly to the user which signals are supported and call out any Tier 3 constraints before editing code. - Step 2 (Boot collector & verify): Start the GHCR container with
INGEST_KEY,DASHBOARD_PASSWORD, andDASHBOARD_TOKENset, then runpnpm dlx @obsunified/cli doctor http://localhost:8790 --origin <user-app-origin>. - Step 3 (Instrument without blocking on TTY prompts): Always pass
--yes(-y) and--templatewhen runningpnpm dlx @obsunified/cli create. When instrumenting Cloudflare Workers or Hono, registerapp.use("*", async (c, next) => { await next(); c.executionCtx.waitUntil(flushSpans()); }). - Step 4 (Verify ingestion end-to-end): Trigger a test request or record a release change (
pnpm dlx @obsunified/cli changes record --url http://localhost:8790 --api-key $INGEST_KEY --service my-api --version 0.1.0 --environment <env> --summary "Agent onboarding verification";--environmentdefaults todefault, so pass the environment your instrumented service reports), then confirm non-zero telemetry withpnpm dlx @obsunified/cli changes list --url http://localhost:8790 --token $DASHBOARD_TOKENandcurl -fsSL -H "Authorization: Bearer $DASHBOARD_TOKEN" http://localhost:8790/internal/telemetry/overview. - Step 5 (Connect MCP server): Configure
@obsunified/mcp-serverwithOBS_COLLECTOR_URLandOBS_DASHBOARD_TOKEN($DASHBOARD_TOKEN); it only reads, so do not give it the ingest key — see MCP Server.
What is autonomous vs. what requires human intervention
| Phase | What the AI agent does autonomously | When human intervention is needed |
|---|---|---|
| 1. Discovery & stack fit | Inspects repo manifests (package.json, pyproject.toml, go.mod, Cargo.toml) against the 3-Tier Compatibility Matrix. | Only if the app has Tier 3 constraints (e.g., native mobile without browser DOM for rrweb replay, or unpropagated message queues) and needs scope confirmation. |
| 2. Collector startup | Checks docker info, boots ghcr.io/dev-sawan-ruparel/obs-unified:latest on 5173/8790 with credentials it generates, and runs pnpm dlx @obsunified/cli doctor. | • If Docker Desktop is stopped or not installed on the machine. • For production cloud deploys requiring interactive OAuth ( wrangler login), DNS setup, or cloud billing/account selection. |
| 3. Code instrumentation & env | Scaffolds with pnpm dlx @obsunified/cli create --yes or installs SDKs, wires middleware (flushSpans()), and populates .env.local / .dev.vars + .env.example. | • Adding encrypted production secrets in remote CI/CD or hosting providers (Vercel, Netlify, GitHub Actions, Cloudflare Worker secrets). • Confirming privacy consent before enabling continuous DOM recording ( startReplay()) in production. |
| 4. End-to-end verification | Starts the app server, fires synthetic HTTP requests, captures x-obs-trace-id, and queries GET /internal/telemetry/overview (Authorization: Bearer $DASHBOARD_TOKEN). | Only if verifying visual rrweb DOM replay when the agent has no headless browser tool (human clicks once in a real browser tab). |
| 5. MCP & AutoSRE operations | Registers @obsunified/mcp-server, investigates traces/logs/blast radius, and proposes governed remediations. | Approving pending_human_approval remediation proposals in the dashboard when causal proof is below cohort isolation or counterfactual verification. |
Standalone Node collector variant
The all-in-one Docker image is the recommended first-run Docker path. If you only want the collector service backed by Postgres and RustFS/S3, use the standalone Node collector:
cd apps/collector-node
docker compose up -d
docker compose logs -f collector