npm package: @shrimp-kit/monitor
Description: > Health monitoring framework with pluggable inspectors.
Latest version: 0.1.0

# @shrimp-kit/monitor

> Health monitoring framework with pluggable inspectors.

## Install

```bash
bun add @shrimp-kit/monitor
```

## Features

- **Pluggable inspectors** — Register custom health checks
- **Built-in inspectors** — File age, heartbeat, disk space, process
- **Inspection reports** — Structured pass/fail results with details
- **Cross-platform** — Works on Windows and Linux

## Usage

### Basic Health Checking

```typescript
import { Logger } from "@shrimp-kit/core";
import {
  HealthChecker,
  fileAgeInspector,
  heartbeatInspector,
  diskSpaceInspector,
  processInspector,
} from "@shrimp-kit/monitor";

const logger = new Logger({ name: "monitor", level: "info" });
const checker = new HealthChecker({ logger });

// Register built-in inspectors
checker.register(
  "heartbeat",
  heartbeatInspector("agent-heartbeat", "./data/heartbeat.json", 180_000),
);

checker.register(
  "disk",
  diskSpaceInspector("disk-c", "C:", 10), // warn if < 10 GB free
);

checker.register(
  "service",
  processInspector("telegram-bridge", "python.*bridge.py"),
);

checker.register(
  "log-freshness",
  fileAgeInspector("agent-log", "./logs/agent.log", 600_000), // warn if > 10 min old
);

// Run all checks
const report = await checker.runAll();
console.log(`${report.passed}/${report.total} passed`);

for (const result of report.results) {
  console.log(`${result.status} — ${result.name}: ${result.message}`);
}
// ok — agent-heartbeat: Alive (PID 1234, 45s ago)
// ok — disk-c: 128.5 GB free
// critical — telegram-bridge: Process not found
// ok — agent-log: Updated 30s ago
```

### Custom Inspectors

An inspector is an async function returning a `HealthCheckResult`:

```typescript
import type { Inspector } from "@shrimp-kit/monitor";

const apiInspector: Inspector = async () => {
  try {
    const start = Date.now();
    const res = await fetch("https://api.example.com/health");
    const latency = Date.now() - start;

    return {
      name: "api-health",
      status: res.ok ? "ok" : "warning",
      message: `${res.status} in ${latency}ms`,
      timestamp: new Date().toISOString(),
      details: { latency, statusCode: res.status },
    };
  } catch (err) {
    return {
      name: "api-health",
      status: "critical",
      message: `Unreachable: ${err}`,
      timestamp: new Date().toISOString(),
    };
  }
};

checker.register("api", apiInspector);
```

### Running Single Checks

```typescript
const result = await checker.runOne("heartbeat");
// → { name: "agent-heartbeat", status: "ok", message: "Alive (PID 1234, 45s ago)", ... }
```

## Built-in Inspectors

| Factory | Description | Parameters |
|---------|-------------|------------|
| `fileAgeInspector(name, path, maxAgeMs)` | Check file modification time | Path to file, max age in ms |
| `heartbeatInspector(name, path, maxAgeMs?)` | Check heartbeat JSON `{timestamp, pid}` | Path to heartbeat file |
| `diskSpaceInspector(name, path, minFreeGb?)` | Check available disk space | Drive/path, minimum free GB |
| `processInspector(name, pattern)` | Check if process is running | Process command line pattern |

## Health Statuses

| Status | Meaning |
|--------|---------|
| `ok` | Everything is healthy |
| `warning` | Non-critical issue, attention needed |
| `critical` | Service down or major problem |
| `unknown` | Could not determine status |

## API Reference

### `HealthChecker`

| Method | Returns | Description |
|--------|---------|-------------|
| `register(name, inspector)` | `void` | Register a health check |
| `unregister(name)` | `void` | Remove a health check |
| `runAll()` | `Promise<InspectionReport>` | Run all registered checks |
| `runOne(name)` | `Promise<HealthCheckResult \| null>` | Run a single check |
| `getCheckNames()` | `string[]` | List registered check names |

See [`src/index.ts`](./src/index.ts) for all exports.