Abrova
☰ Docs menu · Node.js SDK

Node.js SDK

Server-side error tracking for Node.js applications with Express middleware, breadcrumbs, scoped context, and TypeScript support.

Node.js 0.2.4Node 14+Express 4+ (optional)Last updated: 27 Oct 2026
Server-Side Error Tracking

Comprehensive error monitoring for Node.js applications

Automatic Error Capture

Catches uncaught exceptions and unhandled promise rejections

Express.js Middleware

Built-in middleware for Express.js request/error handling

Breadcrumbs

Track events leading up to an error for better context

Scoped Context

Temporarily set context for a block of code with withScope

User Context

Associate errors with user information

Error Filtering

Filter and modify events with beforeSend, ignoredExceptions and ignoredPaths

TypeScript Support

Full TypeScript definitions included

Installation#

Packages come from Abrova Center. Two steps:

1. Add the Abrova registry to .npmrc in your project root (npm, yarn and pnpm all read it):

# .npmrc
@abrova-trace:registry=https://center.abrova.ir/api/packages/abrova/npm/

2. Install the package:

bash
npm install @abrova-trace/nodejs-sdk
# or
yarn add @abrova-trace/nodejs-sdk
# or
pnpm add @abrova-trace/nodejs-sdk

Quick Start#

javascript
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');

// Initialize AbrovaTrace
AbrovaTrace.init({
  apiKey: 'ab_live_your_api_key',            // project API key
  serverSecret: process.env.ABROVA_SERVER_SECRET, // ab_srv_... (required)
  environment: 'production',
  release: '1.0.0'
});

// Capture exceptions
try {
  throw new Error('Something went wrong!');
} catch (error) {
  AbrovaTrace.captureException(error);
}

// Capture messages
AbrovaTrace.captureMessage('User completed checkout');

Capture Errors#

Capture Exceptions

javascript
AbrovaTrace.captureException(error, {
  extra: {
    userId: 123,
    feature: 'checkout'
  }
});

Capture Messages

javascript
AbrovaTrace.captureMessage('Something happened', {
  level: 'warning',                   // 'debug' | 'info' (default) | 'warning' | 'error'
  extra: { context: 'additional info' },
  tags: { feature: 'checkout' }
});
Where messages show up.

Messages appear in the Console under Abrova Trace → Messages, with their level, platform, extra data and breadcrumbs. They never create an issue. 'warn' is sent as warning, 'fatal' as error and 'trace' as debug; anything else as info. Use messages for things your app reports on purpose ("checkout started", "sync finished"); for high-volume diagnostics use Logs.

Breadcrumbs track events leading up to an error, helping you understand what happened before the error occurred.

Manual Breadcrumbs

javascript
AbrovaTrace.addBreadcrumb({
  message: 'User clicked checkout',
  category: 'user-action',
  level: 'info',
  data: { cartTotal: 99.99 }
});

Breadcrumb Helpers

javascript
const { Breadcrumb } = require('@abrova-trace/nodejs-sdk');

// HTTP request breadcrumb
AbrovaTrace.addBreadcrumb(Breadcrumb.http('POST', '/api/order', 200, 150));

// Database query breadcrumb
AbrovaTrace.addBreadcrumb(Breadcrumb.database('SELECT * FROM users', 25));

// User action breadcrumb
AbrovaTrace.addBreadcrumb(Breadcrumb.user('clicked_button', { buttonId: 'submit' }));

User Context#

javascript
AbrovaTrace.setUser({
  id: 123,
  email: 'user@example.com',
  username: 'john_doe'
});

Scoped Context#

Use scoped context to set a user and extra values for one synchronous block of code. The user and extra values are restored when the callback returns; breadcrumbs added inside the block are kept.

javascript
AbrovaTrace.withScope((scope) => {
  scope.setUser({ id: 456 });
  scope.setExtra('operation', 'bulk_import');
  scope.addBreadcrumb({ message: 'Starting import' });

  // Errors captured here include this context
  AbrovaTrace.captureException(new Error('Import failed'));
});
// Context is restored after the block

Express.js Integration#

Built-in middleware for automatic request tracking and error handling in Express.js applications.

javascript
const express = require('express');
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');

const app = express();

// Initialize
AbrovaTrace.init({
  apiKey: 'ab_live_your_api_key',
  serverSecret: process.env.ABROVA_SERVER_SECRET,
  environment: process.env.NODE_ENV
});

// Add middleware
const middleware = AbrovaTrace.expressMiddleware();
app.use(middleware.requestHandler());

// Your routes
app.get('/api/users/:id', async (req, res) => {
  // Your route logic
});

// Error handler (must be last)
app.use(middleware.errorHandler());

app.listen(3000);
Important: Error Handler Placement.

The error handler middleware must be added after all routes. Express requires error-handling middleware to be defined last. Call AbrovaTrace.init() before AbrovaTrace.expressMiddleware(): middleware created before init() does nothing.

Errors reported by errorHandler() include the request method, URL, path, matched route (for example /api/users/:id), query and route parameters, user agent, IP address and the response status (err.status / err.statusCode when it is 4xx or 5xx, otherwise 500). Request headers and the request body are never sent. Query and route parameters whose name looks sensitive (password, token, secret, auth, API key, session, cookie, signature, OTP, code) are sent as [REDACTED]. The same applies to the request address sent with errors and breadcrumbs: the values of sensitive query parameters in it are replaced with [REDACTED] (for example /reset?token=[REDACTED]&page=2), while parameter names and other values are kept (since 0.2.3).

Database Query Tracking#

javascript
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');

async function executeQuery(sql, params) {
  const startTime = Date.now();

  try {
    AbrovaTrace.addBreadcrumb({
      message: 'Executing query',
      category: 'database',
      data: { sql: sql.substring(0, 100) }
    });

    const results = await db.query(sql, params);

    AbrovaTrace.addBreadcrumb({
      message: 'Query completed',
      category: 'database',
      data: { duration_ms: Date.now() - startTime }
    });

    return results;
  } catch (error) {
    AbrovaTrace.captureException(error, {
      extra: { sql, duration_ms: Date.now() - startTime }
    });
    throw error;
  }
}

Error Filtering#

Use the beforeSend hook to filter or modify events before they are sent to AbrovaTrace. It runs for exceptions and for captureMessage() events; return null to drop one. To skip whole exception classes or request paths, use the ignoredExceptions and ignoredPaths options instead.

javascript
AbrovaTrace.init({
  apiKey: 'ab_live_your_api_key',
  serverSecret: process.env.ABROVA_SERVER_SECRET,
  beforeSend(event) {
    // Don't send network errors
    if (event.message.includes('ECONNREFUSED')) {
      return null;
    }

    // Add custom data (errors are AbrovaTraceError objects; messages from
    // captureMessage() arrive as plain objects without setExtra)
    if (typeof event.setExtra === 'function') {
      event.setExtra('server_id', process.env.SERVER_ID);
    }

    return event;
  }
});

Graceful Shutdown#

Errors, messages, logs and performance spans are sent in the background. flush() sends everything that is still waiting, so call it before the process exits: before process.exit(), at the end of a serverless handler, and in your shutdown handlers.

javascript
process.on('SIGTERM', async () => {
  console.log('Shutting down...');
  const sent = await AbrovaTrace.flush(2000); // false if 2 seconds pass before everything is sent
  await AbrovaTrace.close();                  // Sends buffered logs and performance spans, then resets the SDK
  process.exit(0);
});

flush(timeout) takes a timeout in milliseconds (default: 5000) and returns a Promise<boolean>: true when sending finished within the timeout, false when the timeout passed first. It never rejects. close() also returns a Promise; it sends buffered logs and performance spans but does not wait for errors and messages that are still being sent, so call flush() first. After close(), call init() again before you use the SDK.

In a serverless function, flush before the handler returns:

javascript
exports.handler = async (event) => {
  try {
    return await processEvent(event);
  } catch (error) {
    AbrovaTrace.captureException(error);
    throw error;
  } finally {
    await AbrovaTrace.flush();
  }
};

Source Maps#

If you're using TypeScript, bundlers (webpack, esbuild), or Babel, enable source maps for accurate stack traces:

bash
node --enable-source-maps app.js

Or programmatically in your app:

javascript
process.setSourceMapsEnabled(true);

Logging#

Structured server-side logging, batched with exponential backoff and zero dependencies. Logs go to Abrova Trace → Logs and are separate from captureMessage() (Messages). After init(), enable logging once and log from anywhere:

javascript
AbrovaTrace.enableLogging({ sourceId: 'api-server' });

AbrovaTrace.info('Server started on port 3000');
AbrovaTrace.warn('Database connection slow', { latency: 2500 });
AbrovaTrace.logError('Failed to process payment', { orderId: '12345' });

See Node.js SDK Logging for the full pipeline — log levels, Express integration, batching, and graceful shutdown.

Configuration Options#

javascript
AbrovaTrace.init({
  apiKey: 'ab_live_your_api_key',        // Required
  serverSecret: 'ab_srv_your_secret',     // Required
  environment: 'production',              // Default: NODE_ENV or 'development'
  release: '1.0.0',                       // Default: npm_package_version or '1.0.0'
  enabled: true,                          // Default: true
  debug: false,                           // Default: false
  timeout: 5000,                          // Default: 5000ms
  captureUncaughtExceptions: true,        // Default: true
  captureUnhandledRejections: true,       // Default: true
  maxBreadcrumbs: 50,                     // Default: 50 (max 100)
  sampleRate: 1.0,                        // Default: 1.0 (captureException and captureMessage)
  ignoredExceptions: ['ValidationError'], // Error class, error.name, or RegExp
  ignoredPaths: ['/health*'],             // Express paths not reported
  beforeSend: (event) => event,           // Filter/modify events
});
OptionTypeRequiredDescription
apiKeystringYesYour project API key (ab_live_xxx)
serverSecretstringYesYour server secret (ab_srv_xxx); keep it on the server
environmentstringNoEnvironment name (default: NODE_ENV or "development")
releasestringNoApp version (default: npm_package_version or "1.0.0")
enabledbooleanNoEnable/disable tracking (default: true)
debugbooleanNoEnable debug logging (default: false)
timeoutnumberNoHTTP timeout in milliseconds, 1000-30000 (default: 5000)
captureUncaughtExceptionsbooleanNoAuto-capture uncaught exceptions (default: true)
captureUnhandledRejectionsbooleanNoAuto-capture unhandled rejections (default: true)
maxBreadcrumbsnumberNoMax breadcrumbs to keep, up to 100 (default: 50). The 10 most recent are sent with each event
sampleRatenumberNoFraction of captureException() and captureMessage() events sent, 0.0-1.0 (default: 1.0)
ignoredExceptionsarrayNoExceptions that captureException() and the Express error handler do not report: an error class (matched with instanceof), a string equal to error.name, or a RegExp tested against error.name. Uncaught exceptions and unhandled rejections are always reported
ignoredPathsarrayNoRequest paths the Express middleware skips: glob, exact path, or RegExp
beforeSendfunctionNoHook to filter/modify errors and messages before sending; return null to drop

SDK Stats#

javascript
const stats = AbrovaTrace.getStats();
console.log(stats);
// {
//   isEnabled: true,
//   breadcrumbCount: 5,
//   rateLimiter: { totalErrorsInWindow: 3, uniqueErrorsInWindow: 2, totalLimit: 100, errorLimit: 10, windowMs: 60000 },
//   config: { environment: 'production', release: '1.0.0', apiKey: 'ab_live_abc1234...' }
// }

TypeScript Support#

The SDK includes full TypeScript definitions. Import types as needed:

typescript
import AbrovaTrace, {
  AbrovaTraceInitOptions,
  AbrovaTraceError,
  Breadcrumb,
  BreadcrumbOptions,
  UserContext
} from '@abrova-trace/nodejs-sdk';

Requirements#

  • Node.js — >= 14.0.0
  • Express (optional) — >= 4.0.0

API Reference#

AbrovaTrace

  • init(config) — Initialize SDK
  • captureException(error, options?) — Capture an error
  • captureMessage(message, options?) — Send a message to Abrova Trace → Messages (options: level, extra, tags)
  • addBreadcrumb(breadcrumb) — Add a breadcrumb
  • setUser(user) — Set user context
  • setRequestContext(context) — Set request context attached to captured events
  • withScope(callback) — Run code with isolated scope
  • expressMiddleware() — Get Express.js middleware
  • flush(timeout?) — Send pending errors, messages, logs and performance spans; timeout in milliseconds (default: 5000). Returns Promise<boolean>: false if the timeout passes first
  • close() — Flush logs and performance spans, then clean up (returns a Promise)
  • getStats() — Get SDK statistics
  • enableLogging(options?), log(), trace(), logDebug(), info(), warn(), logError(), fatal(), flushLogs() — Logging (see Node.js SDK Logging)
  • trackOperation(name, fn, options?), reportPerformanceSpan(span), reportPerformanceSpanBatch(spans), flushPerformance() — Performance spans

Breadcrumb Helpers

  • Breadcrumb.http(method, url, status?, duration?) — HTTP request breadcrumb
  • Breadcrumb.database(query, duration, error?) — Database query breadcrumb
  • Breadcrumb.user(action, data?) — User action breadcrumb
  • Breadcrumb.console(level, message, ...args) — Console output breadcrumb
  • Breadcrumb.navigation(from, to, method?) — Navigation breadcrumb
  • Breadcrumb.custom(message, category, data?) — Breadcrumb with your own category

Express Middleware

  • requestHandler() — Returns request tracking middleware
  • errorHandler() — Returns error handling middleware
  • userMiddleware() — Sets user context from req.user (id, email, username)
  • transactionMiddleware(name) — Adds start and completion breadcrumbs (duration, status) for a named route

Complete Example#

javascript
const express = require('express');
const AbrovaTrace = require('@abrova-trace/nodejs-sdk');
const { Breadcrumb } = require('@abrova-trace/nodejs-sdk');

// Initialize AbrovaTrace
AbrovaTrace.init({
  apiKey: 'ab_live_your_api_key',
  serverSecret: process.env.ABROVA_SERVER_SECRET,
  environment: process.env.NODE_ENV || 'development',
  release: '1.0.0',
  captureUncaughtExceptions: true,
  captureUnhandledRejections: true,
  maxBreadcrumbs: 50,
  debug: process.env.NODE_ENV === 'development',
});

const app = express();

// Add AbrovaTrace middleware
const middleware = AbrovaTrace.expressMiddleware();
app.use(middleware.requestHandler());

app.use(express.json());

// Set user context from auth
app.use((req, res, next) => {
  if (req.user) {
    AbrovaTrace.setUser({
      id: req.user.id,
      email: req.user.email,
    });
  }
  next();
});

app.get('/api/users/:id', async (req, res) => {
  AbrovaTrace.addBreadcrumb(Breadcrumb.user('view_user', {
    userId: req.params.id,
  }));

  try {
    const user = await db.query('SELECT * FROM users WHERE id = ?', [req.params.id]);
    AbrovaTrace.addBreadcrumb(Breadcrumb.database('SELECT * FROM users', 15));
    res.json(user);
  } catch (error) {
    AbrovaTrace.captureException(error, {
      extra: { userId: req.params.id },
    });
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

// Error handler (must be last)
app.use(middleware.errorHandler());

// Graceful shutdown
process.on('SIGTERM', async () => {
  await AbrovaTrace.flush(2000);
  await AbrovaTrace.close();
  process.exit(0);
});

app.listen(3000, () => console.log('Server running on port 3000'));

Best Practices#

Initialize Early

Initialize AbrovaTrace at the top of your application entry point to catch all errors

Use Express Middleware

Add the request handler first and error handler last for comprehensive Express.js tracking

Set User Context

Associate errors with user information for easier debugging

Use Scoped Context

Use withScope to set temporary context for a synchronous block; the SDK context is process-wide, so it is restored when the callback returns

Add Breadcrumbs

Track important operations (DB queries, HTTP calls, user actions) as breadcrumbs

Graceful Shutdown

Await flush() and close() on SIGTERM/SIGINT so pending errors, logs and spans are sent

Enable Source Maps

Use --enable-source-maps for accurate stack traces in TypeScript/bundled apps

Use beforeSend

Filter out noisy errors and enrich error data with custom context

Was this page helpful?
Report a problem