@forgrit/ops-monitor
v0.1.0
Published
Local/dev health monitoring for ForGrit foundries — deployment adapter status, env validation, queue/worker health, DB connectivity, and a CLI/API summary. Framework-agnostic; NestJS adapter is optional.
Maintainers
Readme
@forgrit/ops-monitor
Local/dev health monitoring for ForGrit foundries.
5 health surfaces, framework-agnostic, zero runtime dependencies.
Install
pnpm add -D @forgrit/ops-monitor
# or
npm install --save-dev @forgrit/ops-monitorIf you're wiring the NestJS controller adapter, also install
@nestjs/common@^10 || ^11 (declared as an optional peer dep — non-NestJS
consumers don't need it).
What it monitors
| # | Surface | Description |
| --- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------------------- |
| 1 | Deployment adapters | Polls each Vercel/Railway/Neon/etc. adapter's health concurrently. Discriminated-union supports both compute providers and database provisioners. |
| 2 | Env validation | Required env-var presence + non-empty. Returns missing vs empty separately so wiring bugs are distinguishable from undeclared vars. |
| 3 | Queue/worker health | BullMQ depth + oldest-job age + worker liveness via the local IQueueMetricsService interface (Decision 6 — observer defines its own observation contract). |
| 4 | DB connectivity | Lightweight SELECT 1 ping with AbortController timeout. Closure-driven so consumers wire in their own Prisma / pg / mysql2 / etc. |
| 5 | Combined summary card | All 4 monitors aggregated into a single HealthCard with overall: 'healthy' | 'degraded' | 'down'. CLI binary prints color-coded summary; JSON output disables colors. |
Quick example
import {
monitorDeploymentAdapters,
validateEnv,
monitorQueueHealth,
monitorDbConnectivity,
runHealthSummary,
} from '@forgrit/ops-monitor';
const card = await runHealthSummary({
env: { required: ['DATABASE_URL', 'NEON_API_KEY'] },
adapters: {
adapters: [
{
kind: 'compute',
name: 'vercel',
healthCheck: async () => ({ status: 'ok', latencyMs: 12 }),
},
{
kind: 'database',
name: 'neon',
healthCheck: async () => ({ status: 'ok' }),
},
],
},
db: {
ping: async () => {
await prisma.$queryRaw`SELECT 1`;
},
},
queues: {
queueService: myQueueMetricsAdapter,
queues: ['design', 'codegen', 'deploy'],
},
});
console.log(card.overall); // 'healthy' | 'degraded' | 'down'CLI
forgrit-ops-monitor # uses ./ops-monitor.config.js if present
forgrit-ops-monitor --env DATABASE_URL,REDIS_URL # ad-hoc env check only
forgrit-ops-monitor --json # JSON output (no colors)Exit codes: 0 healthy, 1 degraded, 2 down, 3 internal error.
NestJS adapter (optional)
import { OpsMonitorModule } from '@forgrit/ops-monitor/nestjs';
@Module({
imports: [
OpsMonitorModule.forRoot({
env: { required: ['DATABASE_URL', 'NEON_API_KEY'] },
// adapters / db / queues...
}),
],
})
export class AppModule {}Then GET /admin/ops/health → HealthCard JSON.
Architectural decisions
- D1 Hybrid extract: 3 surfaces greenfield, 2 surfaces "convention-extract" (queue health + db ping algorithms lifted from apps/api without source-of-truth-reversal).
- D2 NestJS optional:
@nestjs/commonis a peer dep, not a runtime dep. Tree-shake-friendly. - D3 Discriminated
DeploymentAdapterunion: handles both compute (Vercel/Railway withIDeploymentProvider) and database (Neon with its own provisioner shape per plan #23b Decision 3). - D4 CLI read-only: no write/mutate ops. The CLI observes; it never publishes deploys, rotates credentials, or executes destructive actions. Defends the moat.
- D5 JSON-friendly types: returns plain TS objects, not Prometheus exposition format. v0.2.0+ may add a Prometheus exporter.
- D6 Observer owns its observation contract:
IQueueMetricsServicelives in this package, not in@forgrit/shared-contracts-jobs-queue. That contract stays narrow (4 of 35 methods, 11.4% surface) — see plan #5.05.
What's NOT in this package
- Prometheus exposition format → deferred to v0.2.0+
- Distributed tracing (OpenTelemetry) → out of scope
- Log aggregation → out of scope
- Write/mutate ops (force-restart, rotate-credentials, etc.) → never (Decision 4)
- 6th
process.memoryUsage()heap-usage check → deferred to v0.1.1 (founder Q3 decision lock)
License
MIT. See LICENSE.
Related ForGrit packages
@forgrit/deploy-vercel,@forgrit/deploy-railway,@forgrit/deploy-neon— wire these adapters into themonitorDeploymentAdaptershealth-check closures@forgrit/shared-contracts-jobs-queue— narrow queue contract (this package'sIQueueMetricsServiceis a superset for metrics)
See plan #28 for design rationale + the 6 architectural decisions.
Engines
Node ≥ 20. Uses AbortController (Node 20+) for timeouts.
