logique-ai-monitor
v0.2.0
Published
Node/TypeScript SDK for AI Usage Monitor
Maintainers
Readme
logique-ai-monitor — Node/TypeScript SDK
Lightweight, non-blocking SDK for reporting AI usage events to the AI Usage Monitor ingestion API.
Emits AUM Event Contract v1 — the same event format as the Laravel SDK (logique/ai-usage-monitor-sdk): buffered, batched, async/non-blocking, with retry.
Getting an API key
Each application authenticates with its own key, minted from the Monitor dashboard:
- Sign in to the Monitor dashboard and open API keys in the top nav.
- Click Create key, enter your application slug (lowercase
a-z 0-9 -, e.g.ams-whatsapp), an optional label, and an optional expiry. - The full key (
aum_…) is shown once — copy it immediately. The server stores only a hash and can never display it again; if you lose it, mint a new one. - Put the key in your app's environment as
AUM_API_KEY(see below). Never commit it.
The app you report (see Quick start) must match the slug the key was minted for, or the
event is rejected with 403. Rotate by minting a new key, deploying it, then revoking the
old one from the dashboard — revoked or expired keys are rejected with 401.
Install
npm install logique-ai-monitorRequires Node 18+ (uses the global fetch and AbortSignal.timeout).
Quick start
import { AiMonitor } from 'logique-ai-monitor';
const monitor = new AiMonitor({
apiKey: process.env.AUM_API_KEY!,
endpoint: process.env.AUM_ENDPOINT!, // base URL, e.g. https://YOUR-MONITOR-HOST/api/v1
// environment is read from process.env.AUM_ENVIRONMENT automatically
// (production | staging | development, default production) — set it in .env,
// or pass `environment: '...'` here to override.
batchSize: 50, // optional, default 50
flushIntervalMs: 10_000, // optional: also flush every 10s (low-volume apps)
onError: (info) => console.warn('AUM', info), // optional: surface delivery failures
});
// call after each AI operation — non-blocking, returns void
monitor.report({
// app defaults to process.env.AUM_APP — pass `app: '...'` to override per call.
provider: 'google', // google | openai | anthropic | azure_openai | other
model: 'gemini-2.5-flash', // exact provider model name
usage: {
input_tokens: 1240,
output_tokens: 320,
},
// optional:
service: 'lead-classifier', // sub-component slug
operation: 'chat', // chat | completion | embedding | image_generation | audio | other
status: 'success', // success | error
timing: { duration_ms: 867 },
metadata: { feature: 'intent-classification' },
});
// flush remaining buffer on graceful shutdown — flush() AWAITS delivery
process.on('SIGTERM', async () => {
await monitor.flush();
monitor.close();
process.exit(0);
});Reporting an error call:
monitor.report({
app: 'ams-whatsapp',
provider: 'openai',
model: 'gpt-4o',
status: 'error',
error: { type: 'rate_limit', message: 'Too many requests' },
usage: { input_tokens: 0, output_tokens: 0 }, // report tokens consumed, or 0 on total failure
});Environment variables
| Variable | Required | Description |
|----------|----------|-------------|
| AUM_API_KEY | Yes | Per-app Bearer token issued by Monitor. |
| AUM_ENDPOINT | Yes | Monitor base URL, e.g. https://YOUR-MONITOR-HOST/api/v1. The SDK appends /events/batch. |
| AUM_APP | No | Registered application slug used as the default app for report() calls. Must be exactly the slug entered in the Application field when the key was created on /api-keys — a mismatch rejects every event with 403. An explicit app config option or per-report param overrides it. |
| AUM_ENVIRONMENT | No | Deployment environment reported on every event — any lowercase slug (production, staging, development, dev, uat, …). Default production. An explicit environment config option overrides it; a malformed value falls back to production. |
Config options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiKey | string | — | Bearer token. |
| endpoint | string | — | Monitor API base URL (no /events/batch, no trailing slash). |
| app | string | AUM_APP | Default app for report() calls. Must equal the Application slug the key was minted for. |
| environment | string (lowercase slug) | AUM_ENVIRONMENT, else production | Reported on every event — dynamic, not limited to an enum. content is suppressed when production. |
| batchSize | number | 50 | Auto-flush when the buffer reaches this size. |
| timeoutMs | number | 5000 | HTTP request timeout in ms. |
| flushIntervalMs | number | — | If set, also auto-flush on this interval (delivers low-volume buffers). |
| onError | (info) => void | — | Called on terminal delivery failure (client / oversized / exhausted). |
Event fields
| Field | Required | Description |
|-------|----------|-------------|
| app | Yes | App slug, e.g. ams-whatsapp. Must match the API key. |
| provider | Yes | google | openai | anthropic | azure_openai | other. |
| model | Yes | Exact model name from provider, e.g. gpt-4o. |
| usage.input_tokens | Yes* | Input tokens (default 0). |
| usage.output_tokens | Yes* | Output tokens (default 0). |
| usage.cached_input_tokens / reasoning_tokens / images / audio_seconds / raw | No | Extra usage dimensions for pricing. |
| service | No | Sub-component slug, e.g. lead-classifier. |
| operation | No | Defaults to chat. |
| status | No | success (default) or error. |
| error | When status=error | { type, message? }. |
| trace_id / span_id | No | Auto-generated (UUID) when omitted; pass to correlate multi-step traces. |
| parent_span_id | No | Parent span id, or null for a root span. |
| timing | No | { start_time?, end_time?, duration_ms? }. |
| content | No | { prompt?, completion?, redacted? } — only sent when environment !== production. |
| metadata | No | Arbitrary key-value pairs. |
* Auto-filled to 0 when omitted, so failed calls can still be reported.
The SDK auto-sets event_id (UUID v4), schema_version ("1.0"), and timestamp on every event.
Behavior
- Non-blocking:
report()returns immediately; auto-flush atbatchSizesends in the background viasetImmediate. - Never throws into your app: invalid input is dropped (reported via
onError), never thrown. - Buffered: events accumulate until
batchSize(orflushIntervalMs), then flush as one batch. flush()awaits delivery: use it on graceful shutdown so the final batch is not lost.- Retry: 429 and 5xx trigger up to 3 retries with exponential backoff (5s → 30s → 60s) + jitter;
Retry-Afteris honored on 429. - Oversized batches: a
413splits the batch and re-sends; a lone oversized event is dropped and reported. - Resilient: after retries are exhausted, delivery failures are swallowed — the host app is never affected.
- Idempotent: each event carries a stable
event_id(UUID v4) for Monitor-side deduplication.
Build output
Dual ESM + CJS via tsup:
dist/index.js — ESM
dist/index.cjs — CommonJS
dist/index.d.ts — TypeScript declarationsDevelopment
npm install
npm test # run Vitest suite (incl. schema conformance vs docs/contract/event.schema.json)
npm run typecheck # tsc --noEmit
npm run build # tsup ESM+CJS