@6digit/browser-error-reporter
v1.2.1
Published
A lightweight, platform-agnostic runtime error tracking package for browser-based applications
Downloads
3
Maintainers
Readme
@6digit/browser-error-reporter
A lightweight, platform-agnostic runtime error tracking package for browser-based applications, designed to emit structured error events and support LLM-assisted diagnostics.
Features
- 🚀 Lightweight: Zero dependencies, minimal footprint
- 🔧 Framework-agnostic: Works with any frontend framework
- 📊 Structured logging: Emits typed error events
- 🔄 Session tracking: Detects clean runs after application reloads
- 🎯 Configurable: Filter, throttle, and customize error capture
- 🧪 TypeScript support: Fully typed with TypeScript definitions
Installation
npm install @6digit/browser-error-reporterQuick Start
import { installErrorReporter } from '@6digit/browser-error-reporter';
installErrorReporter({
onReport: (log) => {
// Send error to your logging service
fetch('/api/log', {
method: 'POST',
body: JSON.stringify(log),
});
},
onCleanRun: (sessionId) => {
// Signal successful load
fetch('/api/log/clean-run', {
method: 'POST',
body: JSON.stringify({ sessionId })
});
},
ignorePatterns: [/ResizeObserver/, /deprecated/],
});API Reference
installErrorReporter(options)
Installs the error reporter and returns an instance that can be destroyed.
Options
interface ErrorReporterOptions {
onReport: (event: BrowserLogEvent) => void;
onCleanRun?: (sessionId: string) => void;
captureLevels?: Array<'log' | 'warn' | 'error'>;
ignorePatterns?: RegExp[];
cleanRunTimeoutMs?: number;
includeUnhandledRejections?: boolean;
contextProvider?: () => Record<string, any>;
}BrowserLogEvent
interface BrowserLogEvent {
level: 'log' | 'warn' | 'error' | 'exception';
message: string;
stack?: string;
source?: string;
lineno?: number;
colno?: number;
url: string;
timestamp: number;
context?: Record<string, any>;
}Examples
Basic Usage
import { installErrorReporter } from '@6digit/browser-error-reporter';
installErrorReporter({
onReport: (event) => {
console.log('Error captured:', event);
},
});With Convex
import { api } from '../convex/_generated/api';
import { useMutation } from 'convex/react';
const logError = useMutation(api.errors.log);
const markClean = useMutation(api.errors.clean);
installErrorReporter({
onReport: (e) => logError(e),
onCleanRun: (sessionId) => markClean({ sessionId }),
});With Custom Context
import { installErrorReporter } from '@6digit/browser-error-reporter';
installErrorReporter({
onReport: (event) => {
// Send to Sentry or similar service
Sentry.captureException({
message: event.message,
stack: event.stack,
extra: {
level: event.level,
context: event.context,
},
});
},
contextProvider: () => ({
userId: getCurrentUserId(),
route: window.location.pathname,
version: APP_VERSION,
}),
captureLevels: ['error', 'warn', 'log'],
});Copy Errors to Clipboard (Development)
import { installErrorReporter, createClipboardErrorHandler } from '@6digit/browser-error-reporter';
installErrorReporter({
onReport: createClipboardErrorHandler({
formatError: (event) => {
return `[${new Date(event.timestamp).toLocaleTimeString()}] ${event.level.toUpperCase()}: ${event.message}${
event.stack ? '\n\n' + event.stack : ''
}`;
},
notification: 'Error copied!',
notificationDuration: 3000,
onlyWhenTabActive: true, // Only copy when tab is active (default: true)
}),
captureLevels: ['error', 'warn'],
});Custom Clipboard Notification
import { installErrorReporter, createClipboardErrorHandler } from '@6digit/browser-error-reporter';
// Create a custom notification element
function showNotification(message: string, duration: number) {
const notification = document.createElement('div');
notification.textContent = message;
notification.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
background: #4CAF50;
color: white;
padding: 12px 20px;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
z-index: 9999;
font-family: monospace;
font-size: 14px;
`;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.opacity = '0';
notification.style.transition = 'opacity 0.3s';
setTimeout(() => notification.remove(), 300);
}, duration);
}
installErrorReporter({
onReport: createClipboardErrorHandler({
customNotification: showNotification,
notificationDuration: 2000,
onlyWhenTabActive: true, // Only copy when tab is active (default: true)
}),
captureLevels: ['error'],
});Advanced Configuration
Filtering Errors
installErrorReporter({
onReport: (event) => {
// Handle error
},
ignorePatterns: [
/ResizeObserver loop limit exceeded/,
/Warning:.*deprecated/,
/Script error/,
],
});Custom Clean Run Timeout
installErrorReporter({
onReport: (event) => {
// Handle error
},
onCleanRun: (sessionId) => {
// Handle clean run
},
cleanRunTimeoutMs: 15000, // 15 seconds
});Disabling Unhandled Rejections
installErrorReporter({
onReport: (event) => {
// Handle error
},
includeUnhandledRejections: false,
});Promoting Logs Between Levels
You can define patterns to match in log messages and promote them to different log levels. This is useful for detecting important logs that should be treated with higher or lower priority.
installErrorReporter({
onReport: (event) => {
// Handle promoted logs the same as regular logs
sendToMonitoringService(event);
},
promotionPatterns: [
{
// Match Convex error logs and promote to exceptions
pattern: /\[CONVEX.*?\]\s*\[ERROR\]/,
promotionLevel: 'exception',
messageExtractor: (match) => {
return `Convex Exception Detected: ${match[0]}`;
},
contextExtractor: (match) => ({
service: 'convex',
originalLog: match[0]
})
},
{
// Match specific error patterns and promote to errors
pattern: /TypeError:.*?is not a function/,
promotionLevel: 'error',
contextExtractor: (match) => ({
errorType: 'TypeError',
functionName: match[1] || 'unknown'
})
},
{
// Match warnings and promote them to errors
pattern: /DEPRECATED:.*?/,
promotionLevel: 'error',
messageExtractor: (match) => {
return `DEPRECATION ERROR: ${match[0]}`;
}
},
{
// Match debug info and promote to warnings
pattern: /Slow query detected.*?/,
promotionLevel: 'warn',
contextExtractor: (match) => ({
performance: true,
queryTime: match[1]
})
}
],
});Pattern Configuration Options
- pattern: Regular expression to match against log messages
- promotionLevel: Level to promote to ('log', 'warn', 'error', or 'exception'). Defaults to 'error'
- messageExtractor: Function to extract a custom message from the regex match
- contextExtractor: Function to extract additional context from the regex match
Example Use Cases
- Convex Exception Detection:
{
pattern: /\[CONVEX.*?\]\s*\[ERROR\]/,
promotionLevel: 'exception',
contextExtractor: (match) => ({
service: 'convex',
severity: 'error'
})
}- API Error Detection:
{
pattern: /API Error \d{3}:/,
promotionLevel: 'error',
contextExtractor: (match) => ({
apiError: true,
statusCode: match[1]
})
}- Performance Warning Detection:
{
pattern: /Slow query detected.*?(\d+)ms/,
promotionLevel: 'warn',
contextExtractor: (match) => ({
performance: true,
queryTime: match[1],
category: 'slow-query'
})
}- Security Log Detection:
{
pattern: /Failed login attempt.*?from (\d+\.\d+\.\d+\.\d+)/,
promotionLevel: 'error',
contextExtractor: (match) => ({
security: true,
ip: match[1],
category: 'authentication-failure'
})
}- Debug to Warning Promotion:
{
pattern: /Cache miss for key: (.*)/,
promotionLevel: 'warn',
contextExtractor: (match) => ({
cache: true,
missingKey: match[1],
category: 'cache-performance'
})
}Browser Support
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
Development
# Install dependencies
npm install
# Build the package
npm run build
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Lint code
npm run lintLicense
MIT
