NestJS
NestJS apps use the Node.js package. Start the built app with the Argus flag, then report the errors Nest's exception filters catch.
Install
npm install @naijacloud/argusStart
Start with the Argus flag, on the built app:
ARGUS_DSN=https://<public key>@argus-in.naijacloud.com/<project id> node --import @naijacloud/argus/register dist/main.jsOn Naijacloud, the service's Send errors to Argus switch sets the DSN,
release and environment. Put the flag in your start script and leave out
ARGUS_DSN:
{
"scripts": {
"start:prod": "node --import @naijacloud/argus/register dist/main.js"
}
}Report errors from a filter
Nest catches errors in its exception filters, so they never reach Node's
uncaught-error hook. Report the ones you want from a global filter with
captureException:
import { ArgumentsHost, Catch, HttpException } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';
import { captureException } from '@naijacloud/argus';
@Catch()
export class ArgusFilter extends BaseExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
// 4xx answers such as NotFoundException are not errors.
if (!(exception instanceof HttpException) || exception.getStatus() >= 500) {
captureException(exception);
}
super.catch(exception, host);
}
}import { HttpAdapterHost, NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ArgusFilter } from './argus.filter';
const app = await NestFactory.create(AppModule);
const { httpAdapter } = app.get(HttpAdapterHost);
app.useGlobalFilters(new ArgusFilter(httpAdapter));
await app.listen(3000);The filter passes every error on to Nest's own handling, so responses don't change.
Send a test event
npx @naijacloud/argus test --dsn https://<public key>@argus-in.naijacloud.com/<project id>It sends one test event and says whether Argus accepted it. Without --dsn
it uses ARGUS_DSN.
What it captures
- Every request, traced, because Nest runs on a
node:httpserver, with atraceparentheader from the caller continuing its trace. - Errors you report from the filter, and uncaught exceptions and unhandled rejections outside requests.
- Outgoing
fetch()calls as child spans, andconsolecalls as breadcrumbs.
Logs, metrics and traces
import { Injectable } from '@nestjs/common';
import { log, metrics, trace } from '@naijacloud/argus';
@Injectable()
export class OrdersService {
async place(order: Order) {
log.info('order placed', { orderId: order.id, total: order.total });
metrics.count('orders.placed', 1, { method: 'card' });
return trace('charge card', async (span) => {
span?.setAttribute('provider', 'paystack');
return this.paystack.charge(order);
});
}
}Logs and spans written inside a request carry its trace id. Logs are sent every 5 seconds and metrics every 10. More in Node.js.
Cron check-ins and feature flags
import { cron, flags } from '@naijacloud/argus';
// Create the monitor in Argus first.
await cron.withMonitor('nightly-invoices', () => this.sendInvoices());
if (await flags.isOn('new-checkout', user.id)) {
// …
}withMonitor reports the start, then success or failure, and rethrows the
job's error. A flag check returns your fallback (false here) if Argus can't
be reached.
Release and environment
Set ARGUS_RELEASE (your commit) and ARGUS_ENVIRONMENT next to
ARGUS_DSN. The SDK falls back to SENTRY_RELEASE and SENTRY_ENVIRONMENT,
and the environment is production when none is set.
Privacy
Passwords, tokens, cookies, card numbers and other secrets are replaced with
[Filtered] before they leave your app, query strings are removed from URLs,
and the user's IP address isn't sent. To change or drop events with
beforeSend, start the SDK with init() at the top of main.ts instead of
the flag. See Node.js privacy.
Already on Sentry
Keep @sentry/nestjs or @sentry/node. In your Sentry.init call, change
the dsn line:
dsn: 'https://<public key>@argus-in.naijacloud.com/<project id>',Source maps
Stack traces point at the compiled files in dist/ that Node runs. To map
them back to your TypeScript, upload the build's .js.map files as described
in Source maps.