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

er0-l0gmachine

v1.0.0

Published

Frontend error monitoring package with OpenTelemetry integration and secure authentication (JWT/SSO)

Readme

Frontend Error Monitoring SDK

A comprehensive TypeScript npm package for frontend error monitoring with OpenTelemetry integration, secure authentication (JWT/SSO), and real-time observability features inspired by Grafana Faro Web SDK.

🚀 Features

Core Monitoring

  • Error Tracking: Automatic capture of JavaScript errors, unhandled promise rejections, and console errors
  • OpenTelemetry Tracing: Full distributed tracing support with auto-instrumentations
  • Performance Monitoring: Web Vitals, resource timing, and custom metrics
  • Session Tracking: User session management with interaction tracking
  • Breadcrumbs: Detailed debugging context with customizable breadcrumb trails

Security & Authentication

  • JWT Authentication: Secure endpoint authentication with automatic token validation
  • SSO Integration: Support for Okta, Auth0, Azure AD, and custom providers
  • Token Management: Automatic token refresh and expiration handling
  • Custom Token Providers: Flexible authentication with custom token logic

Advanced Features

  • CORS Support: Configurable trace header propagation for cross-origin requests
  • Batch Processing: Efficient data transmission with configurable batching
  • Real-time Monitoring: Live error reporting and performance metrics
  • Custom Instrumentation: Extensible architecture for custom monitoring needs

📦 Installation

npm install frontend-error-monitoring

🔧 Quick Start

Basic Setup with JWT Authentication

import { createMonitoring } from 'frontend-error-monitoring';

const monitoring = await createMonitoring({
  endpoint: 'https://your-monitoring-api.com/api/v1',
  app: {
    name: 'my-webapp',
    version: '1.2.0',
    environment: 'production'
  },
  auth: {
    jwt: 'your-jwt-token-here'
  },
  tracing: {
    enabled: true,
    sampleRate: 0.1, // Sample 10% of traces
    propagateTraceHeaderCorsUrls: [
      'https://api.example.com',
      /https:\/\/.*\.example\.com/
    ]
  },
  errorTracking: {
    enabled: true,
    captureUnhandledRejections: true,
    captureConsoleErrors: true
  },
  performance: {
    enabled: true,
    webVitals: true,
    resourceTiming: true
  }
});

// The SDK is now monitoring your application!

SSO Authentication Examples

Okta Integration

const monitoring = await createMonitoring({
  endpoint: 'https://monitoring.company.com/api',
  app: {
    name: 'corporate-dashboard',
    version: '2.0.0'
  },
  auth: {
    sso: {
      provider: 'okta',
      clientId: 'your-okta-client-id',
      domain: 'https://your-company.okta.com',
      config: {
        scope: 'openid profile email'
      }
    }
  }
});

Auth0 Integration

const monitoring = await createMonitoring({
  endpoint: 'https://api.myapp.com/monitoring',
  app: {
    name: 'mobile-app-web',
    version: '1.0.0'
  },
  auth: {
    sso: {
      provider: 'auth0',
      clientId: 'your-auth0-client-id',
      domain: 'https://your-tenant.auth0.com',
      config: {
        audience: 'https://api.myapp.com',
        clientSecret: 'your-client-secret'
      }
    }
  }
});

Azure AD Integration

const monitoring = await createMonitoring({
  endpoint: 'https://monitoring.enterprise.com/api',
  app: {
    name: 'enterprise-app',
    version: '3.0.0'
  },
  auth: {
    sso: {
      provider: 'azure-ad',
      clientId: 'your-azure-client-id',
      domain: 'https://login.microsoftonline.com/your-tenant-id',
      config: {
        clientSecret: 'your-client-secret',
        scope: 'https://graph.microsoft.com/.default'
      }
    }
  }
});

📖 Usage Examples

Error Tracking

// Manual error capture
try {
  throw new Error('Something went wrong!');
} catch (error) {
  monitoring.captureError(error, {
    component: 'user-profile',
    action: 'save-profile',
    userId: '12345'
  });
}

// Exception with severity level
monitoring.captureException(new Error('Critical error'), 'error');

// Add debugging breadcrumbs
monitoring.addBreadcrumb('User clicked save button', 'ui', 'info', {
  button_id: 'save-btn',
  form_data: { name: 'John', email: '[email protected]' }
});

Custom Tracing

// Start a custom trace
const span = monitoring.startSpan('database-query', {
  query_type: 'user_lookup',
  table: 'users',
  user_id: '12345'
});

// Perform operation
const result = await fetchUserData('12345');

span?.end();

// Or use the convenience method
const result = monitoring.withSpan('api-call', async () => {
  return await fetch('/api/data');
}, {
  endpoint: '/api/data',
  method: 'GET'
});

Performance Monitoring

// Send custom metrics
await monitoring.sendMetric('page_load_time', 1250, 'ms', {
  page: 'dashboard',
  user_type: 'premium'
});

// Monitor operation performance
const startTime = performance.now();
await performComplexOperation();
const duration = performance.now() - startTime;

await monitoring.sendMetric('operation_duration', duration, 'ms', {
  operation: 'data_processing',
  complexity: 'high'
});

User Context & Events

// Set user context
monitoring.setUser('[email protected]', {
  role: 'admin',
  department: 'engineering',
  subscription: 'enterprise'
});

// Add custom context
monitoring.setContext('feature_flag', 'new-ui-enabled');
monitoring.setContext('ab_test_variant', 'variant-b');

// Send custom events
await monitoring.sendEvent('user_action', {
  action: 'button_click',
  component: 'navigation',
  feature: 'export_data'
});

⚙️ Configuration Options

Complete Configuration Interface

interface ErrorMonitoringConfig {
  // Required
  endpoint: string;
  app: {
    name: string;
    version?: string;
    environment?: string;
  };

  // Authentication
  auth?: {
    jwt?: string;
    sso?: {
      provider: 'okta' | 'auth0' | 'azure-ad';
      clientId: string;
      domain: string;
      config?: Record<string, any>;
    };
    tokenProvider?: () => Promise<string> | string;
  };

  // Tracing
  tracing?: {
    enabled?: boolean;
    sampleRate?: number;
    propagateTraceHeaderCorsUrls?: (string | RegExp)[];
    exporter?: {
      headers?: Record<string, string>;
      timeout?: number;
    };
  };

  // Error Tracking
  errorTracking?: {
    enabled?: boolean;
    captureUnhandledRejections?: boolean;
    captureConsoleErrors?: boolean;
    maxBreadcrumbs?: number;
  };

  // Performance
  performance?: {
    enabled?: boolean;
    webVitals?: boolean;
    resourceTiming?: boolean;
  };

  // Session
  session?: {
    enabled?: boolean;
    timeout?: number;
    trackInteractions?: boolean;
  };

  debug?: boolean;
}

Default Values

{
  tracing: {
    enabled: true,
    sampleRate: 1.0,
    propagateTraceHeaderCorsUrls: []
  },
  errorTracking: {
    enabled: true,
    captureUnhandledRejections: true,
    captureConsoleErrors: false,
    maxBreadcrumbs: 100
  },
  performance: {
    enabled: true,
    webVitals: true,
    resourceTiming: false
  },
  session: {
    enabled: true,
    timeout: 30,
    trackInteractions: true
  },
  debug: false
}

🔐 Endpoint Verification & Security

How Endpoint Verification Works

The SDK verifies endpoints through multi-layered authentication that ensures your monitoring data reaches only authorized servers:

1. Token-Based Authentication

Every request includes an Authorization header:

Authorization: Bearer your-jwt-token
// or
Authorization: Bearer sso-generated-token

2. Endpoint Health Monitoring

// Verify endpoint connectivity and authentication
const health = await monitoring.verifyEndpoint();
console.log(health.status); // 'healthy' | 'unhealthy' | 'unauthorized'

// Test with actual data
const test = await monitoring.testEndpoint();
if (test.success) {
  console.log(`Endpoint verified in ${test.responseTime}ms`);
}

// Validate auth configuration
const validation = monitoring.validateAuthConfig();
if (!validation.valid) {
  console.error('Auth errors:', validation.errors);
}

3. Continuous Monitoring

// Start periodic health checks (every 60 seconds)
monitoring.startEndpointMonitoring(60000);

// Stop monitoring
monitoring.stopEndpointMonitoring();

4. Backend Verification Requirements

Your backend must validate the authentication token:

// Express.js example
app.post('/api/v1/errors', authenticateToken, (req, res) => {
  if (!req.user) {
    return res.status(401).json({ error: 'Invalid token' });
  }
  
  // Process authenticated monitoring data
  const { errors, session, app } = req.body;
  console.log(`Received ${errors.length} errors from ${app.name}`);
  res.json({ success: true });
});

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  
  if (!token) return res.sendStatus(401);
  
  jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
}

5. Security Features

  • Automatic token validation and expiration checking
  • Token refresh for SSO providers
  • HTTPS-only communication
  • CORS header propagation for authenticated cross-origin requests
  • Request signing with JWT/SSO tokens
  • Endpoint health monitoring with authentication testing

🔐 Authentication Details

JWT Token Format

The SDK expects JWT tokens in standard format. Tokens are automatically validated for expiration and refreshed when needed.

SSO Provider Requirements

| Provider | Required Config | Optional Config | |----------|----------------|-----------------| | Okta | clientId, domain | scope, audience | | Auth0 | clientId, domain, clientSecret, audience | scope | | Azure AD | clientId, domain, clientSecret | scope |

Custom Token Provider

For custom authentication flows:

auth: {
  tokenProvider: async () => {
    // Your custom logic to get token
    const response = await fetch('/api/auth/token', {
      method: 'POST',
      credentials: 'include'
    });
    const data = await response.json();
    return data.access_token;
  }
}

📊 API Endpoints

The SDK sends data to these endpoint paths:

  • POST /errors - Error events and exceptions
  • POST /traces - OpenTelemetry trace data
  • POST /metrics - Performance metrics
  • POST /events - Custom application events

Request Format

All requests include authentication headers and follow this structure:

{
  "data": [...], // Event/error/metric data
  "session": {
    "id": "session-id",
    "userId": "user-id",
    "startTime": 1699123456789
  },
  "app": {
    "name": "my-app",
    "version": "1.0.0",
    "environment": "production"
  },
  "trace": {
    "traceId": "trace-id",
    "spanId": "span-id"
  }
}

🧪 Testing

Unit Tests

npm test

Watch Mode

npm run test:watch

Type Checking

npm run type-check

Linting

npm run lint
npm run lint:fix

🏗️ Building

Development Build

npm run build:watch

Production Build

npm run build

The build generates multiple formats:

  • dist/index.js - CommonJS
  • dist/index.esm.js - ES Modules
  • dist/index.umd.js - UMD (Universal)

🌐 Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+

📋 API Reference

Core Methods

createMonitoring(config: ErrorMonitoringConfig): Promise<FrontendErrorMonitoring>

Creates and initializes a monitoring instance.

captureError(error: Error, context?: Record<string, any>): void

Manually capture an error with optional context.

captureException(error: Error, level?: 'debug' | 'info' | 'warning' | 'error'): void

Capture an exception with severity level.

startSpan(name: string, attributes?: Record<string, any>): Span

Start a new OpenTelemetry span.

withSpan<T>(name: string, fn: () => T, attributes?: Record<string, any>): T

Execute a function within a span context.

addBreadcrumb(message: string, category?: string, level?: string, data?: Record<string, any>): void

Add a debugging breadcrumb.

setUser(userId: string, userData?: Record<string, any>): void

Set user context for error tracking.

setContext(key: string, value: any): void

Add custom context to all future events.

sendEvent(name: string, data?: Record<string, any>): Promise<void>

Send a custom application event.

sendMetric(name: string, value: number, unit?: string, tags?: Record<string, string>): Promise<void>

Send a performance metric.

getSession(): SessionData

Get current session information.

flush(): Promise<void>

Flush all pending data immediately.

shutdown(): Promise<void>

Shutdown the SDK and clean up resources.

Endpoint Verification Methods

verifyEndpoint(): Promise<EndpointHealth>

Verify endpoint connectivity and authentication status.

const health = await monitoring.verifyEndpoint();
// Returns: { status: 'healthy' | 'unhealthy' | 'unauthorized', responseTime: number, timestamp: number, error?: string }

testEndpoint(): Promise<{ success: boolean; error?: string; responseTime: number }>

Test endpoint with sample monitoring data.

const result = await monitoring.testEndpoint();
if (result.success) {
  console.log(`Endpoint working: ${result.responseTime}ms`);
} else {
  console.error(`Endpoint failed: ${result.error}`);
}

validateAuthConfig(): { valid: boolean; errors: string[] }

Validate the authentication configuration.

const validation = monitoring.validateAuthConfig();
if (!validation.valid) {
  console.error('Config errors:', validation.errors);
}

startEndpointMonitoring(intervalMs?: number): void

Start periodic endpoint health monitoring (default: 60 seconds).

monitoring.startEndpointMonitoring(30000); // Check every 30 seconds

stopEndpointMonitoring(): void

Stop periodic endpoint health monitoring.

monitoring.stopEndpointMonitoring();

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Run the test suite
  6. Submit a pull request

📄 License

MIT License - see LICENSE file for details.

🔗 Related Projects

💬 Support

For questions, issues, or contributions:


Built with ❤️ for better frontend observability and secure error monitoring.