@vantatrace/sdk · Node.js SDK Reference

SDK Documentation

npm install @vantatrace/sdkNode.js ≥ 16TypeScript support

Introduction

VantaTrace is a real-time error tracking, telemetry, and observability SDK for Node.js applications and microservices. It captures exceptions, runtime metrics, and request context, then streams them to your centralized VantaTrace dashboard.

Zero Blocking

All payloads are dispatched asynchronously via setImmediate — no request latency added.

🔁

Smart Batching

Events are batched and flushed every 500 ms, or immediately for critical severity.

🛡️

Fail-Safe

SDK errors are caught internally — it will never crash your host application.

🔍

Auto Deduplication

Duplicate error objects are filtered via WeakSet to prevent double-reporting.

Installation

Install the SDK from npm. It has zero runtime dependencies and works with any Node.js framework.

bash
npm install @vantatrace/sdk
Requires Node.js 16+. TypeScript types are bundled — no @types/ package needed.

Initialization

Create a single VantaTrace instance in your main entry file (e.g. app.js or server.ts) and export it for use across your service.

typescript
import { VantaTrace } from '@vantatrace/sdk';

const vantaTrace = new VantaTrace({
  apiKey: 'ep_live_xxxxxxxxxxxxxxxxxxxxxxxx', // Your project API key
  serviceName: 'my-api-service',
  debug: false, // Enable verbose SDK logs in development
});

Configuration Options

OptionTypeRequiredDefaultDescription
apiKeystringYesYour project API key from the VantaTrace dashboard. Prefix determines environment (ep_live_ → live, ep_test_ → test).
serviceNamestringYesHuman-readable identifier for this service. Appears in the dashboard as the error source.
debugbooleanNofalseWhen true, the SDK prints verbose logs to stdout (trace IDs, payloads, transport status).

Environments & API Keys

VantaTrace derives the environment directly from your API key — no manual environment config needed:

ep_live_…live
ep_test_…test

Global Handlers

Call initGlobalHandlers() once after initialization to register a safety net that automatically captures:

  • Synchronous uncaught exceptions process.on('uncaughtException') — runtime crashes, typos, undefined refs.
  • Unhandled promise rejections process.on('unhandledRejection') — re-thrown errors inside async catch blocks.
  • console.error() calls Auto-patched — any Error passed to console.error is forwarded.
  • Winston logger errors Auto-patched at runtime if the winston package is installed.
  • Pino logger errors Auto-patched at runtime if the pino package is installed.
typescript
// Call once, right after initialization
vantaTrace.initGlobalHandlers();

// This registers:
//  1. process.on('uncaughtException', ...)   – synchronous crashes
//  2. process.on('unhandledRejection', ...)  – async/await rejections
//  3. console.error patch                     – errors via console.error
//  4. Winston auto-patch (if installed)
//  5. Pino auto-patch (if installed)
For uncaughtException, the process exits after 1.5 seconds to allow the batched transport to complete flushing before shutdown.

Express Middleware

VantaTrace provides two Express middlewares that work together to capture full HTTP request context alongside every error.

requestHandler()

Mount this at the very top of your middleware stack, before any routes or body parsers. It seeds an AsyncLocalStorage context with request metadata (route, method, IP, sanitized headers, sanitized body).

Sensitive fields like password, token, and headers such as authorization and cookie are automatically redacted before being stored or transmitted.

errorHandler()

Mount this at the very bottom of your middleware stack, after all routes and controllers. It intercepts any error passed to next(err) and forwards it to VantaTrace while calling next(err) so your own error handler still runs.

typescript
import express from 'express';
import { VantaTrace } from '@vantatrace/sdk';

const app = express();

const vantaTrace = new VantaTrace({
  apiKey: process.env.VANTATRACE_API_KEY!,
  serviceName: 'checkout-service',
});

// ① Mount requestHandler FIRST — before any routes or body parsers
app.use(vantaTrace.requestHandler());

app.use(express.json());

// ... your routes ...
app.get('/api/orders', async (req, res) => {
  const orders = await fetchOrders(); // any thrown error is auto-captured
  res.json(orders);
});

// ② Mount errorHandler LAST — after all routes and controllers
app.use(vantaTrace.errorHandler());

// Your own error response handler (still called via next(err))
app.use((err, req, res, next) => {
  res.status(500).json({ message: 'Internal Server Error' });
});

app.listen(3000);

Capturing Errors

captureException(error, context?)

The primary method for manual error capture. Use inside try/catch blocks to send errors with rich business context.

typescript
try {
  await chargeCard(userId, amount);
} catch (error) {
  vantaTrace.captureException(error, {
    userId: 'user_482',
    route: '/api/checkout',
    method: 'POST',
    severity: 'critical',
    metadata: {
      amount: 29.99,
      currency: 'USD',
    },
  });
  throw error; // re-throw if needed
}

Severity Helpers

Convenience wrappers that set the severity field automatically:

typescript
// Equivalent to captureException with severity: 'critical'
vantaTrace.captureCritical(error, { userId: 'user_42' });

// Equivalent to captureException with severity: 'warning'
vantaTrace.captureWarning(error, { route: '/api/webhook' });

// Equivalent to captureException with severity: 'info'
vantaTrace.captureInfo(error, { metadata: { source: 'scheduler' } });
OptionTypeRequiredDefaultDescription
captureCritical()methodNoForwards error with severity: "critical". Dashboard shows a red badge.
captureWarning()methodNoForwards error with severity: "warning". Dashboard shows an amber badge.
captureInfo()methodNoForwards error with severity: "info". Dashboard shows a blue badge.

Context Object

The optional second argument to all capture methods accepts a VantaTraceContext object:

typescript
// The full VantaTraceContext object you can pass to captureException:
{
  userId?: string;       // Authenticated user ID
  route?: string;        // API route (e.g. '/api/checkout')
  method?: string;       // HTTP method (e.g. 'POST')
  ip?: string;           // Client IP address
  headers?: Record<string, any>;  // Sanitized HTTP headers
  severity?: 'critical' | 'warning' | 'info';
  metadata?: Record<string, any>; // Any custom key-value payload
}
When using Express middlewares, userId, route, method, ip, and headers are auto-populated from the request via AsyncLocalStorage — you only need to pass additional metadata.

Logger Integrations

When initGlobalHandlers() is called, VantaTrace automatically detects and patches popular loggers. No additional configuration is required.

Winston

A custom winston-transport is injected at runtime. Any Error object logged via logger.error() is forwarded to VantaTrace.

typescript
import winston from 'winston';
import { VantaTrace } from '@vantatrace/sdk';

const vantaTrace = new VantaTrace({
  apiKey: process.env.VANTATRACE_API_KEY!,
  serviceName: 'my-service',
});

// Auto-patches Winston when initGlobalHandlers() is called.
// Any logger.error(error) call where the argument is an Error
// will be automatically forwarded to VantaTrace.
vantaTrace.initGlobalHandlers();

const logger = winston.createLogger({
  transports: [new winston.transports.Console()],
});

// This error will appear in your VantaTrace dashboard:
logger.error(new Error('Database connection refused'));

Pino

Pino's write() prototype method is patched. Errors passed directly or inside { err } / { error } objects are captured.

typescript
import pino from 'pino';
import { VantaTrace } from '@vantatrace/sdk';

const vantaTrace = new VantaTrace({
  apiKey: process.env.VANTATRACE_API_KEY!,
  serviceName: 'my-service',
});

// Auto-patches Pino when initGlobalHandlers() is called.
vantaTrace.initGlobalHandlers();

const logger = pino();

// Any of these patterns will forward errors to VantaTrace:
logger.error(new Error('Connection timeout'));
logger.error({ err: new Error('DB query failed') }, 'Database error');
logger.error({ error: new Error('Payment failed') }, 'Payment error');

console.error Patch

console.error is monkey-patched to intercept any Error argument. The original console.error is still called — VantaTrace only adds its own capture on top.

All three interceptors include a reentrance guard — if the SDK itself triggers a log during capture, it won't cause an infinite loop.

Trace ID Correlation

Every captured error is tagged with a unique 32-character hex Trace ID. You can retrieve the ID bound to the current async request context using the static method VantaTrace.getActiveTraceId().

This allows you to correlate your own log lines (Winston, Pino, or custom) with the exact error event visible in the VantaTrace dashboard.

typescript
import { VantaTrace } from '@vantatrace/sdk';

// Get the active trace ID bound to the current async request context.
// Use this to correlate your own log entries with the VantaTrace dashboard event.
const traceId = VantaTrace.getActiveTraceId();

// Example: attach traceId to your response headers for distributed tracing
app.use(vantaTrace.requestHandler());

app.get('/api/orders', (req, res) => {
  const traceId = VantaTrace.getActiveTraceId();
  res.setHeader('X-Trace-Id', traceId ?? '');
  // ...
});
The Trace ID is scoped to the AsyncLocalStorage context of each HTTP request. It persists across any async/await hops within the same request lifecycle.

Ready to get started?

Create a free account