Error Tracking

Catch and debug JavaScript errors in production with full context, stack traces, and session replays.

Overview

StatusRadar RUM automatically captures:

  • JavaScript errors: Uncaught exceptions
  • Promise rejections: Unhandled async errors
  • Network errors: Failed fetch/XHR requests
  • Resource errors: Failed scripts, styles, images
  • Custom errors: Application-specific errors

Automatic Error Tracking

Enabled by default:

const rum = new StatusRadarRUM({
  apiKey: 'your-api-key',
  appId: 'your-app-id',
  endpoint: 'https://rum.statusradar.dev/v1/ingest',

  trackErrors: true,  // Enabled by default
  captureStackTrace: true,
  captureSourceContext: true
});

Error Information Captured

1. Error Details

  • Message: Error message
  • Type: TypeError, ReferenceError, etc.
  • Stack trace: Full call stack
  • Source: File, line, column

2. Context

  • Browser: User agent, version
  • URL: Page where error occurred
  • Session: Session ID for replay
  • User: User ID (if set)
  • Custom: Any custom context

3. Environment

  • Timestamp: When error occurred
  • Network: Online/offline status
  • Memory: Available heap size
  • Performance: Page load state

Error Types

JavaScript Errors

Automatically caught:

// This error is automatically captured
function buggyFunction() {
  undefinedVariable.doSomething();  // ReferenceError
}

buggyFunction();

Captured info:

{
  "type": "ReferenceError",
  "message": "undefinedVariable is not defined",
  "stack": "at buggyFunction (app.js:123:5)\n  at onClick (app.js:456:3)",
  "file": "app.js",
  "line": 123,
  "column": 5
}

Promise Rejections

Unhandled async errors:

// Automatically captured
async function fetchData() {
  const response = await fetch('/api/data');
  if (!response.ok) {
    throw new Error('API request failed');
  }
}

fetchData();  // Unhandled rejection captured

Network Errors

Failed HTTP requests:

rum.configure({
  trackNetwork: true,  // Enable network tracking
  networkErrorsOnly: false  // Track all requests or only errors
});

// Failed requests automatically tracked
fetch('/api/endpoint').catch(err => {
  // Error already captured by RUM
});

Captured info:

{
  "type": "NetworkError",
  "url": "/api/endpoint",
  "method": "GET",
  "status": 500,
  "statusText": "Internal Server Error",
  "duration": 1234
}

Resource Loading Errors

Failed assets:

<!-- Failed image automatically tracked -->
<img src="/missing-image.jpg" alt="Product" />

<!-- Failed script -->
<script src="/missing-script.js"></script>

Manual Error Tracking

Custom Errors

Track application-specific errors:

try {
  processPayment(order);
} catch (error) {
  rum.captureError(error, {
    context: {
      order_id: order.id,
      payment_method: order.paymentMethod,
      amount: order.total
    },
    level: 'error',  // error, warning, info
    fingerprint: ['payment', order.paymentMethod]
  });
}

Error Levels

// Critical error
rum.captureError(error, { level: 'critical' });

// Warning
rum.captureError(error, { level: 'warning' });

// Info (non-error event)
rum.captureMessage('Payment processing started', {
  level: 'info',
  context: { order_id: '12345' }
});

Error Grouping

Group similar errors with fingerprints:

rum.captureError(error, {
  fingerprint: ['database', 'connection', 'timeout']
});

// Errors with same fingerprint are grouped in dashboard

Error Context

Add Custom Context

// Set global context (applied to all errors)
rum.setContext({
  environment: 'production',
  version: '1.2.3',
  build: '4567'
});

// Add tags
rum.setTags({
  server: 'us-east-1',
  deployment: 'blue'
});

// Set user context
rum.setUser({
  id: 'user-123',
  email: '[email protected]',
  subscription: 'pro'
});

Per-Error Context

rum.captureError(error, {
  context: {
    action: 'checkout',
    step: 'payment',
    cart_value: 249.99
  },
  tags: {
    payment_provider: 'stripe',
    currency: 'USD'
  }
});

Source Maps

Enable Source Map Upload

Original source code for minified errors:

// 1. Generate source maps during build
// webpack.config.js
module.exports = {
  devtool: 'source-map',
  output: {
    sourceMapFilename: '[file].map'
  }
};

// 2. Upload source maps to StatusRadar
// Using CLI
npx @statusradar/cli upload-sourcemaps \
  --api-key YOUR_API_KEY \
  --app-id YOUR_APP_ID \
  --release 1.2.3 \
  --dir ./dist

// 3. Set release version in RUM
rum.configure({
  release: '1.2.3'  // Match uploaded source maps
});

Automatic Upload (Webpack Plugin)

// webpack.config.js
const StatusRadarPlugin = require('@statusradar/webpack-plugin');

module.exports = {
  plugins: [
    new StatusRadarPlugin({
      apiKey: process.env.STATUSRADAR_API_KEY,
      appId: process.env.STATUSRADAR_APP_ID,
      release: process.env.GIT_SHA,
      uploadSourceMaps: true,
      deleteAfterUpload: true  // Remove maps from build
    })
  ]
};

Error Filtering

Client-Side Filtering

Ignore known errors:

rum.configure({
  ignoreErrors: [
    // Ignore by message
    'ResizeObserver loop limit exceeded',
    'Non-Error promise rejection captured',

    // Ignore by regex
    /^Script error\.?$/,
    /chrome-extension:\/\//,

    // Ignore by custom function
    (error) => {
      return error.message.includes('AdBlock');
    }
  ]
});

Ignore Patterns

rum.configure({
  // Ignore errors from specific files
  denyUrls: [
    /extensions\//i,
    /^chrome:\/\//i,
    /^moz-extension:\/\//i
  ],

  // Only capture errors from your domain
  allowUrls: [
    /https?:\/\/((www|app)\.)?yoursite\.com/
  ]
});

Server-Side Filtering

Configure in Dashboard:

  1. Dashboard → Observability → Apps → Settings
  2. Error Filters section
  3. Add rules to drop errors by pattern

Error Alerts

Set Up Alerts

  1. Dashboard → Alerts → Create Alert
  2. Select "Error Rate" trigger
  3. Configure threshold:
    • Errors per minute > 10
    • Error rate increase > 50%
    • New error type detected
  4. Choose notification channel (Email, Slack, etc.)

Alert Channels

  • Email
  • Slack
  • Telegram
  • Discord
  • Webhooks
  • SMS (Twilio)
  • Voice calls

See: Alert Channels

Error Dashboard

View Errors

Dashboard → Observability → Apps → [Your App] → Errors

Displays:

  • Error rate timeline: Errors over time
  • Top errors: Most frequent errors
  • New errors: Recently introduced errors
  • Error distribution: By browser, OS, page

Error Details

Click any error to view:

  • Full stack trace
  • Session replay (if enabled)
  • User context
  • Device/browser info
  • Similar errors

Search & Filter

Filter errors by:

  • Error type
  • URL pattern
  • User
  • Browser
  • Date range
  • Custom tags

Integration with Session Replay

Errors automatically link to session replay:

  1. View error in dashboard
  2. Click "View Session"
  3. Watch replay leading up to error
  4. See exact user actions that triggered error

Debugging Patterns

Identify Error Patterns

Group similar errors:

// 1. Add error fingerprint
rum.captureError(error, {
  fingerprint: [error.name, error.code]
});

// 2. Dashboard shows grouped errors
// 3. Click group to see all instances

User-Reported Errors

Collect user feedback with errors:

window.addEventListener('error', (event) => {
  const feedback = prompt('An error occurred. Can you describe what happened?');

  rum.captureError(event.error, {
    context: {
      user_feedback: feedback,
      user_action: 'reported_error'
    }
  });
});

Error Recovery Tracking

Track how users recover from errors:

try {
  submitForm();
} catch (error) {
  rum.captureError(error);
  showErrorMessage();

  // Track recovery attempt
  retryButton.onclick = () => {
    rum.trackEvent('error_recovery_attempted', {
      error_type: error.name
    });
    submitForm();
  };
}

Performance Considerations

Sampling

Sample errors to reduce volume:

rum.configure({
  errorSampleRate: 0.1  // Capture 10% of errors
});

// Or sample by error type
rum.configure({
  beforeSend: (event) => {
    if (event.type === 'error') {
      // Sample low-priority errors
      if (event.level === 'warning' && Math.random() > 0.1) {
        return null;  // Drop 90% of warnings
      }
    }
    return event;
  }
});

Batch Errors

Errors batched with other events:

rum.configure({
  batchSize: 50,
  batchInterval: 10000  // Send every 10 seconds
});

Best Practices

DO ✅

  • Set user context for better debugging
  • Use error fingerprints for grouping
  • Upload source maps for production
  • Add custom context to errors
  • Set up alerts for critical errors
  • Enable session replay for visual context

DON'T ❌

  • Capture every warning (use sampling)
  • Include sensitive data in error context
  • Ignore CORS errors from extensions
  • Track errors from development environment
  • Log passwords/tokens in error messages

API Reference

// Capture error
rum.captureError(error: Error, options?: object)

// Capture message
rum.captureMessage(message: string, options?: object)

// Set context
rum.setContext(context: object)

// Set tags
rum.setTags(tags: object)

// Set user
rum.setUser(user: object)

// Ignore errors
rum.configure({
  ignoreErrors: string[] | RegExp[] | Function[]
})

Next Steps