npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

api-reporter

v1.1.7

Published

Client-side API error reporter with support for Sumo Logic or custom services.

Readme

API Reporter

A comprehensive JavaScript library for monitoring, reporting, and debugging API calls, network requests, and application performance in web applications. Features intelligent error detection, P1 incident monitoring with visual context capture, performance tracking, and real-time alerting.

🚀 Features

Core Monitoring

  • HTTP Request Intercepting: Automatic monitoring of fetch() and XMLHttpRequest calls
  • Resource Error Detection: Monitor failed CSS, JS, image, and other resource loads
  • PostMessage Monitoring: Track cross-origin and iframe communications
  • Performance Monitoring: Detect slow requests and performance degradation
  • User Context Tracking: Automatically extract and maintain user profile data

Advanced Capabilities

  • P1 Incident Detection: Intelligent critical failure detection with visual context
  • Screenshot Capture: Automatic screenshot capture during P1 incidents
  • DOM Snapshot: Capture page state for debugging
  • Console Error Tracking: Monitor and correlate console errors with incidents
  • Real-time Alerting: Immediate notifications for critical issues

Data Management

  • Event Deduplication: Prevent duplicate error reports
  • Local Storage Persistence: Offline-capable event queuing
  • Batch Processing: Efficient event transmission
  • Retry Logic: Automatic retry with exponential backoff

📁 Project Structure

api-reporter/
├── src/
│   ├── api-reporter.js              # Main entry point and ApiReporter class
│   ├── index.js                     # Public API exports
│   ├── constants.js                 # Configuration constants and defaults
│   ├── ConfigManager.js             # Configuration validation and management
│   ├── EventManager.js              # Event queuing and deduplication
│   ├── ServiceManager.js            # Service abstraction layer
│   ├── UserProfileManager.js        # User context and profile management
│   │
│   ├── interceptors/                # Request/response interceptors
│   │   ├── index.js                 # Interceptor exports and setup
│   │   ├── BaseInterceptor.js       # Base interceptor functionality
│   │   ├── FetchInterceptor.js      # Fetch API monitoring
│   │   ├── XHRInterceptor.js        # XMLHttpRequest monitoring
│   │   ├── ResourceInterceptor.js   # Resource load error detection
│   │   └── PostMessageInterceptor.js # PostMessage communication tracking
│   │
│   ├── services/                    # External service integrations
│   │   ├── index.js                 # Service exports
│   │   ├── BaseService.js           # Base service interface
│   │   └── SumoLogicService.js      # SumoLogic integration
│   │
│   ├── monitors/                    # Specialized monitoring components
│   │   └── P1FlowMonitor.js         # P1 incident detection and visual capture
│   │
│   └── utils/                       # Utility functions and helpers
│       ├── Logger.js                # Centralized logging with debug modes
│       ├── PerformanceMonitor.js    # Performance tracking and alerting
│       ├── request-utils.js         # Request parsing utilities
│       └── validation-utils.js      # Configuration validation helpers
│
├── types/
│   └── index.d.ts                   # TypeScript definitions
│
├── dist/                            # Built distribution files
│   ├── api-reporter.js              # ES modules build
│   ├── api-reporter.min.js          # Minified build
│   └── api-reporter.umd.js          # UMD build for browsers
│
├── docs/                            # Documentation
│   ├── API.md                       # API reference
│   ├── CONFIGURATION.md             # Configuration guide
│   └── EXAMPLES.md                  # Usage examples
│
├── tests/                           # Test files
│   ├── unit/                        # Unit tests
│   ├── integration/                 # Integration tests
│   └── fixtures/                    # Test data
│
├── package.json                     # Package configuration
├── README.md                        # This file
├── LICENSE                          # License file
├── CHANGELOG.md                     # Version history
└── rollup.config.js                 # Build configuration

📦 Installation

npm install api-reporter

Or include via CDN:

<script src="https://unpkg.com/api-reporter/dist/api-reporter.min.js"></script>

🏗️ Quick Start

Basic Setup

import apiReporter from 'api-reporter';

// Initialize with basic monitoring
await apiReporter.init({
  // Required: Define which endpoints to monitor
  endpoints: ['/api/', '/graphql'],
  
  // Or monitor specific domains
  domainsToTrack: ['api.yourapp.com'],
  
  // Required: Service configuration
  service: 'sumologic',
  serviceOptions: {
    endpoint: 'https://endpoint.sumologic.com/receiver/v1/http/YOUR_COLLECTOR_CODE'
  },
  
  // Optional: App identification
  appName: 'MyApp',
  environment: 'production',
  
  // Enable debug logging
  debug: true
});

🆕 Dynamic Configuration (NEW!)

Fetch configuration dynamically from your backend while maintaining local fallbacks:

await apiReporter.init({
  // Backend configuration endpoint
  remoteConfigUrl: '/api/reporter-config',
  
  // Local configuration (fallback + local-only fields)
  appName: 'MyApp',
  environment: 'production',
  service: 'sumologic',
  serviceOptions: {
    endpoint: 'https://collectors.sumologic.com/receiver/v1/http/YOUR_CODE'
  },
  
  // These will be merged with backend config
  domainsToTrack: ['myapp.com'],
  endpoints: ['/api/users']
});

// Check configuration source
console.log('Config source:', apiReporter.getQueueStatus().configSource);
// Outputs: 'backend', 'local', or 'backend+local'

Backend Endpoint Example:

// Your backend should respond to GET /api/reporter-config
app.get('/api/reporter-config', (req, res) => {
  res.json({
    configVersion: '1.0.0',
    configSource: 'backend',
    domainsToTrack: ['api.myapp.com', 'cdn.myapp.com'],
    endpoints: ['/api/critical/*', '/api/payments/*'],
    monitorPerformance: true,
    slowRequestThreshold: 2000,
    // ... other configuration
  });
});

Configuration Merging Rules:

  • 🏠 Local-only: appName, environment, service, addCustomUserData
  • 🔄 Arrays combined: domainsToTrack, endpoints (deduplicated)
  • 🎯 Backend takes precedence: Performance settings, monitoring rules
  • 🛡️ Graceful fallback: Uses local config if backend unavailable

Dynamic Domain Tracking

The API reporter supports dynamic domain expressions that are evaluated at runtime. This is particularly useful when your backend configuration needs to track the current hostname:

// Backend returns this configuration:
{
  domainsToTrack: [
    'window.location.hostname',  // Evaluated to actual hostname
    'avatrade.com',
    'avarnd.com',
    'avatrade.io',
    'avaapiweb.com',
    'hqliveassets.com'
  ]
}

// The final domainsToTrack will include:
// - The actual hostname (e.g., 'myapp.com' if that's your current domain)
// - All the static domains from the backend
// - Any local domains you've configured

Supported Dynamic Expressions:

  • 'window.location.hostname' - Evaluates to the current page's hostname
  • 'location.hostname' - Alternative syntax for the same

Safety Features:

  • ✅ Safe evaluation - no arbitrary code execution
  • ✅ Fallback to original string if evaluation fails
  • ✅ Works in both browser and server environments
  • ✅ Automatic deduplication after evaluation

Advanced Configuration

await apiReporter.init({
  // Monitoring targets
  endpoints: ['*'], // Monitor all endpoints
  domainsToTrack: ['api.example.com', 'cdn.example.com'],
  
  // Service configuration
  service: 'sumologic',
  serviceOptions: {
    endpoint: 'https://collectors.sumologic.com/receiver/v1/http/YOUR_CODE'
  },
  
  // Performance monitoring
  monitorPerformance: true,
  slowRequestThreshold: 2000, // 2 seconds
  averageAlertThreshold: 2500, // 2.5 seconds
  
  // User data extraction
  fieldsToExtract: [
    {
      api: '/api/login',
      source: 'response',
      fields: ['userId', 'email', 'role']
    },
    {
      api: '*',
      source: 'request',
      fields: {
        'customerId': 'customer_id', // Map field names
        'sessionId': 'session_id'
      }
    }
  ],
  
  // Resource monitoring
  logResourceErrors: true,
  
  // PostMessage monitoring
  monitorPostMessages: {
    postMessageOriginWhitelist: ['https://trusted-domain.com'],
    excludePostMessagesEvents: ['heartbeat', 'ping'],
    monitorSpecificPostMessagesEvents: ['payment', 'auth']
  },
  
  // P1 Flow Monitoring
  enableP1FlowMonitoring: true,
  p1Config: {
    enabled: true,
    captureScreenshot: true,
    screenshotScale: 0.5,
    screenshotQuality: 0.7,
    captureDomSnapshot: true,
    captureConsoleErrors: true,
    flows: [
      {
        flow: 'checkout',
        enabled: true,
        failureThreshold: 2,
        completionWindow: 30000,
        criticalEndpoints: ['/api/payment', '/api/order'],
        criticalPostMessageEvents: ['payment_failed', 'order_error'],
        exclude: ['/api/analytics']
      }
    ],
    realTimeNotificationApi: 'https://alerts.yourcompany.com/p1',
    apiKey: 'your-api-key'
  },
  
  // Event management
  maxQueueSize: 1000,
  batchSize: 10,
  retryIntervalMs: 30000,
  deduplicationWindowMs: 60000,
  maxRetries: 3,
  
  // Custom user data
  addCustomUserData: () => ({
    sessionId: getSessionId(),
    experimentGroup: getUserExperiment(),
    customerId: getCustomerId()
  }),
  
  // Local storage enrichment
  localStorageEnrichmentKeys: ['userId', 'sessionData', 'preferences']
});

📊 Core APIs

Event Logging

// Manual event logging
apiReporter.logEvent({
  type: 'custom_error',
  message: 'Something went wrong',
  context: {
    component: 'checkout',
    action: 'submit_payment'
  },
  extraData: {
    orderId: '12345',
    errorCode: 'PAYMENT_FAILED'
  }
});

// Custom API error events
window.dispatchEvent(new CustomEvent('apiError', {
  detail: {
    type: 'business_logic_error',
    message: 'Invalid coupon code',
    request: {
      url: '/api/apply-coupon',
      method: 'POST',
      status: 400
    }
  }
}));

User Profile Management

// Set user profile
apiReporter.setUserProfile({
  userId: '12345',
  email: '[email protected]',
  role: 'premium',
  segment: 'enterprise'
});

// Get current profile
const profile = apiReporter.getUserProfile();
console.log('Current user:', profile);

Performance Monitoring

// Get performance metrics
const metrics = apiReporter.getPerformanceMetrics();
console.log('Average response time:', metrics.averageSeconds);
console.log('Slow request percentage:', metrics.slowRequestPercentage);
console.log('Slowest endpoints:', metrics.slowestEndpoints);

Queue Management

// Check queue status
const status = apiReporter.getQueueStatus();
console.log('Events pending:', status.queueSize);
console.log('Is sending:', status.isSending);

// Force send events
await apiReporter.sendEvents();

// Clear all queued events
apiReporter.clearEvents();

🔥 P1 Flow Monitoring

P1 Flow Monitoring provides intelligent critical failure detection with rich visual context for debugging.

Flow Configuration

const p1Config = {
  enabled: true,
  flows: [
    {
      flow: 'user-registration',
      enabled: true,
      failureThreshold: 1, // Any failure triggers P1
      criticalEndpoints: ['/api/register', '/api/verify-email'],
      criticalPostMessageEvents: ['registration_failed'],
      exclude: ['/api/analytics', '/api/tracking']
    },
    {
      flow: 'payment-processing',
      enabled: true,
      failureThreshold: 2, // 2 failures trigger P1
      criticalEndpoints: ['/api/payment', '/api/billing'],
      criticalPostMessageEvents: ['payment_declined', 'fraud_detected']
    }
  ],
  
  // Visual context capture
  captureScreenshot: true,
  screenshotScale: 0.5, // Reduce size
  screenshotQuality: 0.7,
  maxScreenshotSize: 500000, // 500KB limit
  
  // DOM state capture
  captureDomSnapshot: true,
  
  // Console error tracking
  captureConsoleErrors: true,
  maxConsoleErrors: 50,
  
  // Real-time alerting
  realTimeNotificationApi: 'https://alerts.company.com/p1',
  screenshotUploadEndpoint: 'https://uploads.company.com/screenshots',
  apiKey: 'your-p1-api-key'
};

P1 Event Structure

When a P1 incident is detected, the following data is captured:

{
  type: 'p1_incident_alert',
  severity: 'critical',
  p1Data: {
    flow: 'checkout',
    reason: 'Critical endpoint failed: /api/payment',
    failedEndpoints: [
      {
        url: '/api/payment',
        status: 500,
        method: 'POST',
        type: 'http'
      }
    ],
    flowConfig: {
      failureThreshold: 1,
      criticalEndpoints: ['/api/payment']
    },
    userContext: {
      userId: '12345',
      email: '[email protected]'
    },
    visualContext: {
      hasScreenshot: true,
      screenshotSize: 245,
      hasDomSnapshot: true,
      consoleErrorCount: 3,
      viewport: { width: 1920, height: 1080 },
      performanceMetrics: { ... }
    }
  },
  metrics: {
    totalRequests: 5,
    failedRequests: 1,
    successRate: '80.0'
  }
}

🎛️ Configuration Options

Core Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | endpoints | string[] | string | [] | URL patterns to monitor | | domainsToTrack | string[] | string | [] | Domains to monitor (supports dynamic expressions like 'window.location.hostname') | | service | string | object | - | Service type or custom service | | serviceOptions | object | {} | Service-specific configuration | | appName | string | 'unknown' | Application name | | environment | string | 'unknown' | Environment (dev/staging/prod) | | debug | boolean | false | Enable debug logging |

Performance Monitoring

| Option | Type | Default | Description | |--------|------|---------|-------------| | monitorPerformance | boolean | false | Enable performance monitoring | | slowRequestThreshold | number | 2000 | Slow request threshold (ms) | | averageAlertThreshold | number | 2500 | Average response time alert (ms) |

Event Management

| Option | Type | Default | Description | |--------|------|---------|-------------| | maxQueueSize | number | 1000 | Maximum events in queue | | batchSize | number | 10 | Events per batch | | retryIntervalMs | number | 30000 | Retry interval | | deduplicationWindowMs | number | 60000 | Deduplication window | | maxRetries | number | 3 | Maximum retry attempts |

Resource Monitoring

| Option | Type | Default | Description | |--------|------|---------|-------------| | logResourceErrors | boolean | false | Monitor resource load failures | | logPreflight | boolean | false | Log OPTIONS requests |

PostMessage Monitoring

interface PostMessageConfig {
  postMessageOriginWhitelist?: string[];
  excludePostMessagesEvents?: string[];
  monitorSpecificPostMessagesEvents?: string[];
}

Field Extraction

interface FieldExtractionRule {
  api: string; // URL pattern or '*'
  source: 'request' | 'response' | '*';
  fields: string[] | Record<string, string> | RegExp[];
}

📡 Service Integrations

SumoLogic

apiReporter.init({
  service: 'sumologic',
  serviceOptions: {
    endpoint: 'https://collectors.sumologic.com/receiver/v1/http/YOUR_COLLECTOR_CODE'
  }
});

Custom Service

class CustomService {
  async send(event) {
    // Send event to your custom endpoint
    const response = await fetch('/api/errors', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(event)
    });
    
    if (!response.ok) {
      throw new Error(`Failed to send: ${response.status}`);
    }
  }
}

apiReporter.init({
  service: new CustomService()
});

🔄 Event Types

The library automatically captures various event types:

HTTP Errors

  • fetch_http_error - HTTP error from fetch requests
  • xhr_http_error - HTTP error from XMLHttpRequest
  • fetch_network_error - Network failure in fetch
  • xhr_network_error - Network failure in XHR
  • xhr_timeout_error - Request timeout
  • xhr_aborted_error - Request aborted

Performance Events

  • fetch_slow_request - Slow fetch request
  • xhr_slow_request - Slow XHR request
  • performance_degradation_alert - Overall performance issues

Resource Events

  • resource_load_error - Failed CSS/JS/image loads

PostMessage Events

  • postmessage_communication - PostMessage activity
  • postmessage_cross_origin - Cross-origin communication

P1 Events

  • p1_incident_alert - Critical flow failure

Custom Events

  • custom_api_error - Manual error logging
  • Any custom type you define

🎨 Event Structure

Each event contains:

{
  id: "uuid-string",
  type: "error_type",
  timestamp: 1234567890,
  appVersion: "1.0.0",
  appName: "MyApp",
  environment: "production",
  interceptor: "fetch|xhr|resource|manual",
  
  request: {
    method: "POST",
    url: "https://api.example.com/endpoint",
    domain: "api.example.com",
    path: "/endpoint",
    status: 500,
    statusText: "Internal Server Error",
    response: {...},
    headers: {...}
  },
  
  context: {
    scriptOrigin: "https://myapp.com",
    pageUrl: "https://myapp.com/checkout",
    userAgent: "Mozilla/5.0...",
    isMonitored: true,
    
    user: {
      userId: "12345",
      email: "[email protected]",
      // ... extracted fields
    },
    
    localStorage: {
      // ... enrichment data
    }
  },
  
  // Optional performance data
  performance: {
    duration: 3500,
    durationSeconds: 3.5
  },
  
  // Optional P1 data
  p1Data: {
    flow: "checkout",
    reason: "Critical failure",
    visualContext: {...}
  }
}

🔧 Advanced Usage

Custom User Data Extraction

apiReporter.init({
  // Extract specific fields from API responses
  fieldsToExtract: [
    {
      api: '/api/login',
      source: 'response',
      fields: ['token', 'userId', 'permissions']
    },
    {
      api: '/api/user/profile',
      source: 'response',
      fields: {
        'customerId': 'customer_id', // Rename fields
        'tier': 'subscription_tier'
      }
    },
    {
      api: '*',
      source: 'request',
      fields: [/^\w+@\w+\.\w+$/] // Extract emails with regex
    }
  ],
  
  // Add custom context to every event
  addCustomUserData: () => ({
    sessionId: getSessionId(),
    experimentGroup: getABTestGroup(),
    feature: getCurrentFeature()
  })
});

Sensitive Data Masking

P1 screenshots automatically mask sensitive data:

<!-- These will be automatically blurred in screenshots -->
<input type="password" />
<input type="credit-card" />
<div data-sensitive="true">Secret info</div>
<div data-mask="true">PII data</div>
<div class="credit-card-number">4111-1111-1111-1111</div>

Manual P1 Monitoring

const p1Monitor = apiReporter.getP1FlowMonitor();

// Track custom events
p1Monitor.trackRequest({
  url: '/api/critical-operation',
  method: 'POST',
  status: 500
});

// Update flow configuration
p1Monitor.updateConfig({
  flows: [...newFlows]
});

Performance Optimization

// Monitor specific performance metrics
const metrics = apiReporter.getPerformanceMetrics();

if (metrics.averageSeconds > 3.0) {
  // Alert development team
  apiReporter.logEvent({
    type: 'performance_alert',
    message: `High average response time: ${metrics.averageSeconds}s`,
    context: {
      slowestEndpoints: metrics.slowestEndpoints
    }
  });
}

🔐 Privacy & Security

Data Protection

  • Automatic masking of sensitive form fields in screenshots
  • Configurable field extraction with explicit rules
  • No automatic collection of PII without configuration
  • Local storage encryption options

GDPR Compliance

// Clear user data
apiReporter.setUserProfile({});
apiReporter.clearEvents();

// Disable tracking
apiReporter.destroy();

🚀 Production Deployment

Performance Considerations

apiReporter.init({
  // Optimize for production
  debug: false,
  maxQueueSize: 500,
  batchSize: 20,
  retryIntervalMs: 60000,
  
  // Reduce screenshot impact
  p1Config: {
    screenshotScale: 0.3,
    screenshotQuality: 0.5,
    maxScreenshotSize: 200000
  }
});

Error Handling

try {
  apiReporter.init(config);
} catch (error) {
  console.error('Failed to initialize API Reporter:', error);
  // Fallback logging
}

// Monitor initialization
setTimeout(() => {
  const status = apiReporter.getQueueStatus();
  if (!status.isInitialized) {
    console.warn('API Reporter failed to initialize');
  }
}, 5000);

🧪 Testing

Development Mode

apiReporter.init({
  debug: true,
  environment: 'development',
  service: 'sumologic',
  serviceOptions: {
    endpoint: 'https://test-endpoint.sumologic.com/...'
  }
});

// Test manual events
apiReporter.logEvent({
  type: 'test_event',
  message: 'Testing API Reporter'
});

Disable in Tests

if (process.env.NODE_ENV === 'test') {
  // Don't initialize in test environment
} else {
  apiReporter.init(config);
}

📚 API Reference

Main Methods

  • init(config) - Initialize the reporter
  • destroy() - Clean up and stop monitoring
  • logEvent(data) - Log custom events
  • setUserProfile(profile) - Set user context
  • getUserProfile() - Get current user context
  • sendEvents() - Force send queued events
  • clearEvents() - Clear event queue
  • debugMode(enabled) - Toggle debug logging
  • getQueueStatus() - Get queue information
  • getPerformanceMetrics() - Get performance data
  • getP1FlowMonitor() - Get P1 monitor instance

Configuration Validation

The library validates all configuration options and provides helpful error messages for invalid configurations.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

📄 License

MIT License - see LICENSE file for details.

🆘 Support