Node.js SDK

Full reference for the @justanalyticsapp/node SDK.

Installation#

npm install @justanalyticsapp/node

Quick Start#

import JA from '@justanalyticsapp/node';

JA.init({
  siteId: process.env.JUSTANALYTICS_SITE_ID!,
  apiKey: process.env.JUSTANALYTICS_API_KEY!,
  serviceName: 'my-api-server',
  environment: process.env.NODE_ENV,
});

Once initialized, the SDK automatically instruments:

  • HTTP requests (incoming and outgoing via http/https modules)
  • PostgreSQL queries (via pg module)
  • Redis commands (via ioredis or redis module)

Configuration#

JA.init({
  // Required
  siteId: 'your-site-id',
  apiKey: 'ja_sk_your_api_key',
  serviceName: 'api-server',

  // Optional
  environment: 'production',       // default: 'production'
  debug: false,                     // default: false
  sampleRate: 1.0,                  // default: 1.0 (100%)
  ingestUrl: 'https://justanalytics.app/api/ingest', // override ingestion endpoint
  flushInterval: 5000,              // batch flush interval in ms (default: 5000)
  maxBatchSize: 100,                // max spans per batch (default: 100)
  metrics: { enabled: true },       // infrastructure metrics (default: true)
});

Tracing#

Manual Spans#

const result = await JA.startSpan('process-order', async (span) => {
  span.setAttribute('order.id', orderId);
  span.setAttribute('order.total', total);

  const user = await JA.startSpan('fetch-user', async () => {
    return await db.users.findUnique({ where: { id: userId } });
  });

  return { success: true, user };
});

Span Options#

JA.startSpan('external-call', {
  kind: 'client',             // 'internal' | 'server' | 'client'
  attributes: {                // initial attributes
    'http.method': 'POST',
    'http.url': 'https://api.stripe.com/charges',
  },
}, async (span) => {
  const result = await fetch('https://api.stripe.com/charges');
  span.setAttribute('http.status_code', result.status);
  return result;
});

Error Tracking#

// Automatic: unhandled exceptions and rejections are captured

// Manual capture
try {
  await riskyOperation();
} catch (error) {
  JA.captureException(error, {
    tags: { module: 'payments' },
    extra: { orderId: '123' },
  });
}

// Capture a message
JA.captureMessage('Rate limit exceeded', 'warning', {
  tags: { endpoint: '/api/checkout' },
});

Logging#

// Built-in structured logger
JA.logger.info('Request processed', { path: '/api/orders', duration: 245 });
JA.logger.warn('Slow query', { table: 'orders', duration_ms: 2500 });
JA.logger.error('Payment failed', { orderId: '123', reason: 'declined' });

Custom Metrics#

JA.recordMetric('custom.queue_size', 42, { queue: 'emails' });
JA.recordMetric('custom.request_duration_ms', 150.5);

User Context#

JA.setUser({ id: 'user-123', email: 'alice@example.com' });
JA.setTag('feature', 'checkout');

Framework Integrations#

Express.js#

import express from 'express';
import JA from '@justanalyticsapp/node';

JA.init({ siteId: '...', apiKey: '...', serviceName: 'api' });

const app = express();
app.use(JA.expressMiddleware());

app.get('/api/users/:id', async (req, res) => {
  const user = await db.users.findUnique({ where: { id: req.params.id } });
  res.json(user);
});

Next.js#

// instrumentation.ts
import JA from '@justanalyticsapp/node';

export function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    JA.init({
      siteId: process.env.JUSTANALYTICS_SITE_ID!,
      apiKey: process.env.JUSTANALYTICS_API_KEY!,
      serviceName: 'nextjs-app',
    });
  }
}
// Wrap API routes
import { withJustAnalytics } from '@justanalyticsapp/node/next';

export const GET = withJustAnalytics(async (req) => {
  return Response.json({ status: 'ok' });
});

Graceful Shutdown#

process.on('SIGTERM', async () => {
  await JA.flush();  // Send any pending data
  await JA.close();  // Clean up resources
  process.exit(0);
});

API Reference#

| Method | Description | |--------|-------------| | JA.init(options) | Initialize the SDK | | JA.startSpan(name, callback) | Create and execute a span | | JA.captureException(error, options?) | Capture an error | | JA.captureMessage(msg, level?, options?) | Capture a message | | JA.setUser(user) | Set user context | | JA.setTag(key, value) | Set a tag | | JA.getActiveSpan() | Get current active span | | JA.getTraceId() | Get current trace ID | | JA.recordMetric(name, value, tags?) | Record a custom metric | | JA.logger | Structured logger instance | | JA.expressMiddleware() | Express middleware | | JA.flush() | Flush pending data | | JA.close() | Shut down the SDK | | JA.isInitialized() | Check if SDK is initialized |