Telescope
Laravel Telescope, redesigned for NestJS — a headless observability console that correlates every request, query, job, mail, cache hit, and exception under one batch, with a pluggable store and an optional dashboard.
@dudousxd/nestjs-telescope is an application observability console for NestJS. A set of watchers capture what happens inside a request — every query, queued job, sent email, cache hit, and thrown exception — correlate it all under one batch via AsyncLocalStorage, persist it through a pluggable storage provider, and expose it through a headless JSON API plus an optional dashboard. It's the missing Telescope for NestJS, designed framework-idiomatically rather than ported.
The unit of value is the batch
The thing you click into is never a lone log line — it's one request and everything it caused. Open an entry and you see the exact queries, jobs, mails, and exceptions it produced, in capture order, on a single waterfall.
The problem it solves
Backend developers reach for Telescope in two moments. Locally, debugging "why did this request do 47 queries?" — the answer lives across a dozen scattered log lines that you have to mentally stitch back together. In production, where an admin needs to inspect a failing flow without SSHing into a pod to grep logs after the fact.
Telescope answers both by recording correlated entries you click into, not time-series aggregates. You install core plus one adapter, add one module import, and within five minutes you're stepping through a request — in dev with full detail, in prod with redaction always on and a closed-by-default gate.
It complements metrics and tracing; it doesn't replace them. Metrics tell you that p95 latency rose. Telescope tells you which request, and shows you the SQL that did it.
How it's built
Four design choices define the library:
- Watchers, correlated under one batch. Each watcher (request, query, job, mail, cache, schedule, HTTP-client, exception) records an entry;
AsyncLocalStorageties them to the request that triggered them. See Capture & correlation. - Off the response path. Request capture fires after the response is flushed and query capture costs microseconds, so Telescope never slows the app it observes — and it surfaces its own host-path cost on a
/healthcard. See Performance. - Pluggable storage. Every store implements one
StorageProviderSPI with a self-healing schema: zero-config SQLite by default, swap in Redis for multi-instance, or write your own. See Storage. - Headless API, optional dashboard. Everything the UI shows comes from a plain JSON API you can curl, script, or build your own admin against. The bundled React dashboard is a separate module you opt into — no frontend dependency imposed on your app.
Quickstart
The whole loop — install, register two modules, open the dashboard — in three steps. For prerequisites, the headless API, storage adapters, and watchers, see Getting Started.
Install core and the dashboard:
pnpm add @dudousxd/nestjs-telescope @dudousxd/nestjs-telescope-uiRegister both modules in your root module. TelescopeModule.forRoot() wires request and exception capture and turns on the zero-config SQLite store and pruner; TelescopeUiModule.forRoot() serves the dashboard SPA:
import { Module } from '@nestjs/common';
import { TelescopeModule } from '@dudousxd/nestjs-telescope';
import { TelescopeUiModule } from '@dudousxd/nestjs-telescope-ui';
@Module({
imports: [
TelescopeModule.forRoot({
// dev: rich capture, open gate. prod: flip enabled + supply an authorizer.
enabled: process.env.NODE_ENV !== 'production',
authorizer: () => true, // gates the API; defaults to deny in production
prune: { after: '24h' },
}),
TelescopeUiModule.forRoot(),
],
})
export class AppModule {}Boot the app and open http://localhost:3000/telescope. The dashboard polls /telescope/api/*, shows captured entries with live polling, and — on any entry — the correlated batch: the request and everything it caused. Prefer JSON? Hit GET /telescope/api/entries/:id for the same data.
Production gate
The API gate denies in production by default. In prod you must set enabled: true and supply an authorizer (or wire dashboard auth) — otherwise the dashboard returns 403. This is a default, not an afterthought: capture runs with redaction always on, and the gate stays closed until you open it.
Beyond capture
Once entries are flowing, the rest of the console builds on the same pipeline:
- A Horizon-style queue console — browse BullMQ and SQS queues in real time, and (behind a second default-deny gate) retry / remove / promote / redrive jobs.
- A Pulse-style health dashboard — per-type counts, slowest entries, top exceptions, N+1 hotspots, and a throughput sparkline, rolled up from captured entries.
- Error alerting — a genuinely new exception family pages you via Slack (Block Kit, route/user, deep link), a webhook, or your own sink, plus rate and slow-route rules.
- AI diagnosis —
@dudousxd/nestjs-telescope-aiturns an exception into a probable-cause / suggested-fix report (Bedrock, OpenAI, any Vercel AI SDK model). - MCP for coding agents — an optional Model Context Protocol server lets Claude Code, Cursor, or any MCP client debug straight from the captured data.
- Archive before prune — per-type retention plus an
archive.sinkships doomed entries to S3 before the pruner deletes them.
Where to go next
Getting Started
Install core + ui, import two modules, open /telescope, hit the headless API, and pick a storage adapter.
Capture & correlation
How watchers, batches, and AsyncLocalStorage turn scattered events into one navigable flow.
Storage
The StorageProvider SPI, the self-healing schema, and the full adapter table.
Performance
Off-the-response-path capture, and the /health card that proves the overhead.
Dashboard
The full UI tour: overview, entries, traces, the queues console, schedules, and alerts.
Dashboard auth
Gate the dashboard to your logged-in admins, all the way to production.
Packages
One page per watcher, storage, queue manager, AI diagnoser, and the testing kit.
MCP server
Let coding agents query the captured data over the Model Context Protocol.
Recipes
Custom storage and watchers, tags & redaction, S3 archiving, frontend errors, and AI diagnosis.
Configuration reference
Every forRoot() option in one table.