| name | telescope-alerts-ai |
| description | Alerting and AI exception diagnosis in nestjs-telescope. Configure alerts with channel helpers (slackChannel, webhookChannel, customChannel) and rules (new-exception, exception-rate, slow-request-rate, dropped-entries, metric-threshold); understand the default that 4xx HttpExceptions are NOT recorded as exception entries (exceptions.captureHttp4xx restores it); wire AI diagnosis with ai.{diagnoser,mode} + createAiSdkDiagnoser({ model }) from @dudousxd/nestjs-telescope-ai over any Vercel AI SDK model (Bedrock/OpenAI/ Anthropic); enable public client-error ingestion. Use for "Slack alert on new errors", "AI diagnose exceptions", "why is my 403 not in the exceptions tab". |
| license | MIT |
| metadata | {"type":"core","library":"@dudousxd/nestjs-telescope","library_version":"1.12.0","framework":"nestjs"} |
Alerting & AI diagnosis
Telescope can page you when a genuinely new exception family appears (or a rate
threshold trips) and, optionally, attach an AI probable-cause report to the
exception. Both are forRoot options.
Setup
Fan alerts to one or more channels; rules selects what fires. A configured
alerts with no destination or empty rules is a fail-closed boot error.
import { TelescopeModule, slackChannel } from '@dudousxd/nestjs-telescope';
TelescopeModule.forRoot({
alerts: {
channels: [slackChannel(process.env.SLACK_WEBHOOK_URL!)],
dashboardUrl: 'https://telescope.example.com/telescope/',
rules: [
{ type: 'new-exception', window: '1h' },
{ type: 'exception-rate', window: '5m', threshold: 10 },
],
},
});
Source: packages/core/src/alerts/alert-rule.ts (AlertsOptions, AlertRule),
packages/core/src/alerts/alert-channel.ts (slackChannel / webhookChannel /
customChannel).
Core patterns
Pattern 1 — the alert rule types
rules is a non-empty array of discriminated unions:
rules: [
{ type: 'new-exception', window: '1h' },
{ type: 'exception-rate', window: '5m', threshold: 10 },
{ type: 'slow-request-rate', window: '5m', thresholdMs: 1000, count: 5 },
{ type: 'dropped-entries', threshold: 100 },
];
Source: packages/core/src/alerts/alert-rule.ts (AlertRule).
Pattern 2 — AI exception diagnosis
Add the AI package and supply a diagnoser. mode: 'on-demand' (default) only
runs on the dashboard button; mode: 'auto' also diagnoses a NEW family on the
flush path and enriches its new-exception alert.
import { TelescopeModule } from '@dudousxd/nestjs-telescope';
import { createAiSdkDiagnoser } from '@dudousxd/nestjs-telescope-ai';
import { openai } from '@ai-sdk/openai';
TelescopeModule.forRoot({
ai: {
diagnoser: createAiSdkDiagnoser({ model: openai('gpt-4o-mini'), maxOutputTokens: 1024 }),
mode: 'on-demand',
},
});
The diagnoser is provider-agnostic via the Vercel AI SDK (swap openai(...) for
bedrock(...) / anthropic(...)). It runs on already-redacted exception data.
Source: packages/ai/src/ai-sdk-diagnoser.ts (createAiSdkDiagnoser),
packages/core/src/ai/diagnoser.ts (TelescopeAiOptions),
website/content/docs/recipes/ai-exception-diagnosis.mdx.
Pattern 3 — public client-error ingestion
Let browsers POST errors to <telescope>/api/client-errors; they become
client_exception entries through the same pipeline. Disabled by default.
TelescopeModule.forRoot({
clientErrors: {
enabled: true,
maxBodyBytes: 32_768,
rateLimit: { perMinute: 60 },
authorize: (req) => hasValidSession(req),
},
});
Source: packages/core/src/nest/telescope.options.ts (ClientErrorsOptions).
Common mistakes
Mistake 1 — expecting every 4xx in the exceptions tab
TelescopeModule.forRoot({ alerts: { channels: [slackChannel(url)], rules: [{ type: 'new-exception', window: '1h' }] } });
TelescopeModule.forRoot({
exceptions: { captureHttp4xx: true },
alerts: { channels: [slackChannel(url)], rules: [{ type: 'new-exception', window: '1h' }] },
});
Mechanism: a 4xx HttpException is expected control flow; recording it would open
a new family and page Slack for every permission denial. The 4xx is still on the
request entry's statusCode. Source:
packages/core/src/nest/telescope.options.ts (ExceptionsOptions).
Mistake 2 — alerts with rules but no channel
TelescopeModule.forRoot({ alerts: { rules: [{ type: 'new-exception', window: '1h' }] } });
TelescopeModule.forRoot({
alerts: { channels: [slackChannel(url)], rules: [{ type: 'new-exception', window: '1h' }] },
});
Mechanism: a configured alerts with no destination (neither channels nor the
legacy webhookUrl) or empty rules throws at boot rather than silently never
alerting. Source: packages/core/src/alerts/alert-rule.ts (AlertsOptions).
Mistake 3 — hand-rolling a Slack POST instead of the channel helper
alerts: { channels: [customChannel(async (a) => fetch(url, { method: 'POST', body: a.title }))], rules };
alerts: {
channels: [slackChannel(process.env.SLACK_WEBHOOK_URL!)],
dashboardUrl: 'https://telescope.example.com/telescope/',
rules,
};
Mechanism: slackChannel renders Block Kit with route/user and builds an
${dashboardUrl}#/entries/exception/${id} deep link when dashboardUrl is set;
customChannel is the escape hatch for non-Slack sinks. Source:
packages/core/src/alerts/alert-channel.ts, packages/core/src/alerts/alert-rule.ts.