featurely-error-tracker
v1.0.12
Published
Advanced error tracking SDK for Featurely with breadcrumbs, device info, and complete context
Maintainers
Readme
featurely-error-tracker
Advanced error tracking SDK for Featurely with automatic breadcrumb tracking, device information, network conditions, and complete context for error reproduction.
Features
✨ Automatic Error Tracking - Catches unhandled errors and promise rejections
🍞 Breadcrumb Tracking - Records the last 50 user actions before errors
📱 Device & Browser Info - Captures device type, OS, browser, and screen resolution
🌐 Network Conditions - Tracks connection type and quality
🎯 User Context - Associates errors with specific users
🔔 Toast Notifications - Optional visual error alerts with customizable styles and positions
⚛️ React Integration - Error Boundary helper included
📊 Severity Levels - Categorize errors by importance
🔒 TypeScript - Fully typed for better DX
Installation
npm install featurely-error-trackeror
yarn add featurely-error-trackeror
pnpm add featurely-error-trackerQuick Start
1. Get Your API Key
Get your API key from Featurely Dashboard Settings:
- Go to Settings → API Keys
- Create a new API key with
errors:writepermission - Copy your API key (format:
ft_live_xxxorft_test_xxx)
2. Initialize the Tracker
import { ErrorTracker } from "featurely-error-tracker";
const tracker = new ErrorTracker({
apiKey: "ft_live_your_api_key_here",
environment: "production",
appVersion: "1.0.0",
});
// Install automatic tracking
tracker.install();3. That's it! 🎉
Errors will now be automatically tracked and reported to Featurely with full context.
4. Optional: Enable Toast Notifications
Want visual feedback when errors occur? Enable toast notifications:
const tracker = new ErrorTracker({
apiKey: "ft_live_your_api_key_here",
environment: "production",
appVersion: "1.0.0",
toast: {
enabled: true,
position: "top-right", // Choose position
duration: 5000, // Auto-dismiss after 5 seconds
showOnAutoCapture: true, // Show toasts for caught errors
},
});
tracker.install();
// Manually show toasts anytime
tracker.showToast({
message: "Operation completed successfully!",
style: "success",
});Usage Examples
Basic Setup (JavaScript)
import { ErrorTracker } from "featurely-error-tracker";
const tracker = new ErrorTracker({
apiKey: "ft_live_your_api_key",
environment: "production",
appVersion: "1.0.0",
});
tracker.install();TypeScript Setup
import { ErrorTracker, ErrorTrackerConfig } from "featurely-error-tracker";
const config: ErrorTrackerConfig = {
apiKey: process.env.FEATURELY_API_KEY!,
environment: process.env.NODE_ENV as "development" | "staging" | "production",
appVersion: "1.0.0",
releaseId: process.env.GIT_COMMIT_SHA,
maxBreadcrumbs: 50,
enabled: process.env.NODE_ENV === "production",
onError: (error) => {
console.error("Featurely SDK error:", error);
},
};
const tracker = new ErrorTracker(config);
tracker.install();Manual Error Reporting
try {
await riskyOperation();
} catch (error) {
await tracker.reportError(error, "high", {
userId: currentUser.id,
action: "risky_operation",
});
}Setting User Context
// After user login
tracker.setUser(user.id, user.email);
// Clear user context on logout
tracker.setUser();Adding Custom Breadcrumbs
tracker.addBreadcrumb({
type: "custom",
message: "User clicked checkout button",
category: "navigation",
level: "info",
data: {
cartTotal: 99.99,
itemCount: 3,
},
});Tracking Async Operations
import { trackOperation } from "featurely-error-tracker";
const result = await trackOperation(
tracker,
async () => {
return await fetchUserData();
},
{ action: "fetch_user_data" }
);React Integration
Error Boundary
import { Component, ErrorInfo, ReactNode } from 'react';
import { ErrorTracker, ErrorBoundaryTracker } from 'featurely-error-tracker';
const tracker = new ErrorTracker({
apiKey: 'ft_live_your_api_key',
environment: 'production',
appVersion: '1.0.0'
});
const boundaryTracker = new ErrorBoundaryTracker(tracker);
interface Props {
children: ReactNode;
}
interface State {
hasError: boolean;
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
boundaryTracker.captureError(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;Usage in App
import ErrorBoundary from './components/ErrorBoundary';
function App() {
return (
<ErrorBoundary>
<YourApp />
</ErrorBoundary>
);
}Next.js Integration
App Router (app directory)
Create app/providers.tsx:
'use client';
import { useEffect } from 'react';
import { ErrorTracker } from 'featurely-error-tracker';
let tracker: ErrorTracker | null = null;
export function ErrorTrackingProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
if (!tracker) {
tracker = new ErrorTracker({
apiKey: process.env.NEXT_PUBLIC_FEATURELY_API_KEY!,
environment: process.env.NODE_ENV as 'production' | 'development',
appVersion: '1.0.0'
});
tracker.install();
}
return () => {
tracker?.uninstall();
};
}, []);
return <>{children}</>;
}Use in app/layout.tsx:
import { ErrorTrackingProvider } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<ErrorTrackingProvider>
{children}
</ErrorTrackingProvider>
</body>
</html>
);
}Pages Router
Create pages/_app.tsx:
import { ErrorTracker } from 'featurely-error-tracker';
import type { AppProps } from 'next/app';
import { useEffect } from 'react';
const tracker = new ErrorTracker({
apiKey: process.env.NEXT_PUBLIC_FEATURELY_API_KEY!,
environment: process.env.NODE_ENV as 'production' | 'development',
appVersion: '1.0.0'
});
function MyApp({ Component, pageProps }: AppProps) {
useEffect(() => {
tracker.install();
return () => tracker.uninstall();
}, []);
return <Component {...pageProps} />;
}
export default MyApp;API Reference
ErrorTracker
Main class for error tracking.
Constructor Options
interface ErrorTrackerConfig {
apiKey: string; // Required: Your Featurely API key
apiUrl?: string; // Optional: Custom API endpoint
environment?: string; // Optional: 'development' | 'staging' | 'production'
appVersion?: string; // Optional: Your app version
releaseId?: string; // Optional: Git commit SHA or release ID
maxBreadcrumbs?: number; // Optional: Max breadcrumbs to keep (default: 50)
enabled?: boolean; // Optional: Enable/disable tracking (default: true)
validateApiKey?: boolean; // Optional: Validate API key format (default: true)
onError?: (error: Error) => void; // Optional: Callback for SDK errors
toast?: {
// Optional: Toast notification configuration
enabled?: boolean; // Enable toast notifications (default: false)
position?: ToastPosition; // Default position: 'top-right'
duration?: number; // Auto-dismiss duration in ms (default: 5000)
showOnAutoCapture?: boolean; // Show toasts for auto-captured errors (default: true)
};
}Methods
install(): void
Installs automatic error tracking. This will track:
- Navigation events
- User clicks
- Console errors
- HTTP requests (fetch)
- Unhandled errors and promise rejections
tracker.install();uninstall(): void
Removes all tracking and restores original functions.
tracker.uninstall();reportError(error, severity?, context?): Promise<void>
Manually report an error.
await tracker.reportError(new Error("Something went wrong"), "high", {
userId: "123",
action: "checkout",
});Parameters:
error: Error- The error object to reportseverity?: 'low' | 'medium' | 'high' | 'critical'- Severity level (default: 'medium')context?: Record<string, unknown>- Additional context data
addBreadcrumb(data): void
Manually add a breadcrumb.
tracker.addBreadcrumb({
type: "custom",
message: "User performed action",
category: "user-action",
level: "info",
data: { key: "value" },
});Breadcrumb Types:
navigation- Page navigationclick- User clicksinput- Form inputshttp- HTTP requestsconsole- Console messagescustom- Custom events
setUser(userId?, userEmail?): void
Set user context for error attribution.
tracker.setUser("user_123", "[email protected]");getSessionId(): string
Get the current session ID.
const sessionId = tracker.getSessionId();isTrackerInstalled(): boolean
Check if automatic tracking is installed.
if (tracker.isTrackerInstalled()) {
console.log("Tracking is active");
}showToast(options): void
Display a toast notification with customizable style and position.
Note: Toast notifications must be enabled in the config (toast.enabled: true).
// Show error toast
tracker.showToast({
message: "Failed to save data",
style: "error",
position: "top-right",
duration: 5000,
closable: true,
});
// Show success toast
tracker.showToast({
message: "Data saved successfully!",
style: "success",
position: "top-center",
duration: 3000,
});
// Show warning that stays until manually closed
tracker.showToast({
message: "Please review your changes",
style: "warning",
duration: 0, // 0 = no auto-dismiss
});Toast Options:
interface ToastOptions {
message: string; // Toast message to display
style?: ToastStyle; // 'error' | 'warning' | 'success' | 'info' (default: 'error')
position?: ToastPosition; // Position on screen (default: from config)
duration?: number; // Auto-dismiss in ms, 0 to disable (default: 5000)
closable?: boolean; // Show close button (default: true)
}
type ToastPosition =
| "top-left"
| "top-center"
| "top-right"
| "bottom-left"
| "bottom-center"
| "bottom-right";
type ToastStyle = "error" | "warning" | "success" | "info";Toast Styles:
error- Red gradient backgroundwarning- Orange gradient backgroundsuccess- Green gradient backgroundinfo- Blue gradient background
Example with Auto-Capture:
const tracker = new ErrorTracker({
apiKey: "ft_live_xxx",
toast: {
enabled: true,
position: "top-right",
duration: 5000,
showOnAutoCapture: true, // Auto-show toasts for caught errors
},
});
tracker.install();
// Now any unhandled error will automatically show a toast notification
// You can also manually trigger toasts:
try {
await riskyOperation();
} catch (error) {
await tracker.reportError(error, "high");
tracker.showToast({
message: "Operation failed. Please try again.",
style: "error",
});
}trackOperation<T>(tracker, operation, context?): Promise<T>
Utility function to wrap async operations with automatic error tracking.
import { trackOperation } from "featurely-error-tracker";
const data = await trackOperation(tracker, async () => await fetchData(), {
action: "fetch_data",
});ErrorBoundaryTracker
Helper class for React Error Boundaries.
import { ErrorBoundaryTracker } from 'featurely-error-tracker';
const boundaryTracker = new ErrorBoundaryTracker(tracker);
// In your Error Boundary:
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
boundaryTracker.captureError(error, errorInfo);
}Error Handling
Missing API Key
try {
const tracker = new ErrorTracker({
apiKey: "", // ❌ Invalid
});
} catch (error) {
console.error(error.message);
// "API key is required. Get your API key from: https://featurely.no/dashboard/settings"
}Invalid API Key Format
try {
const tracker = new ErrorTracker({
apiKey: "invalid_key", // ❌ Wrong format
});
} catch (error) {
console.error(error.message);
// "Invalid API key format. Expected format: ft_live_xxx or ft_test_xxx"
}Disable API Key Validation
const tracker = new ErrorTracker({
apiKey: "custom_key",
validateApiKey: false, // ✅ Skip validation
});Environment Variables
Store your API key in environment variables:
# .env.local
NEXT_PUBLIC_FEATURELY_API_KEY=ft_live_your_api_key_hereThen use it:
const tracker = new ErrorTracker({
apiKey: process.env.NEXT_PUBLIC_FEATURELY_API_KEY!,
environment: process.env.NODE_ENV as "production" | "development",
});Best Practices
1. Initialize Early
Initialize the tracker as early as possible in your application lifecycle.
// ✅ Good: Initialize in app entry point
// src/index.tsx or app/layout.tsx2. Use Environment Variables
Never hardcode API keys in your source code.
// ❌ Bad
const tracker = new ErrorTracker({ apiKey: "ft_live_123..." });
// ✅ Good
const tracker = new ErrorTracker({ apiKey: process.env.FEATURELY_API_KEY });3. Disable in Development
Avoid sending development errors to production.
const tracker = new ErrorTracker({
apiKey: process.env.FEATURELY_API_KEY!,
enabled: process.env.NODE_ENV === "production",
});4. Set User Context
Always set user context after login for better error attribution.
// After successful login
tracker.setUser(user.id, user.email);
// After logout
tracker.setUser();5. Add Meaningful Breadcrumbs
Add custom breadcrumbs for critical user actions.
tracker.addBreadcrumb({
type: "custom",
message: "User initiated payment",
category: "payment",
level: "info",
data: { amount: 99.99, currency: "USD" },
});Troubleshooting
Errors Not Being Tracked
- Check if tracking is enabled:
console.log(tracker.isTrackerInstalled()); // Should be true- Verify API key is correct:
console.log(process.env.FEATURELY_API_KEY); // Should start with ft_live_ or ft_test_- Check browser console for SDK errors.
High Memory Usage
Reduce the number of breadcrumbs:
const tracker = new ErrorTracker({
apiKey: "ft_live_xxx",
maxBreadcrumbs: 20, // Default is 50
});TypeScript Errors
Make sure you have TypeScript installed:
npm install --save-dev typescriptTypeScript Support
This package is written in TypeScript and includes full type definitions.
import {
ErrorTracker,
ErrorTrackerConfig,
BreadcrumbData,
DeviceInfo,
NetworkInfo,
AppContext,
InvalidApiKeyError,
ConfigurationError,
} from "featurely-error-tracker";Examples
Complete example files are available in the examples/ directory:
basic.example.js- Basic JavaScript usagereact.example.tsx- React with Error Boundarynextjs.example.tsx- Next.js (App Router + Pages Router)
Browser Support
- Chrome ≥ 90
- Firefox ≥ 88
- Safari ≥ 14
- Edge ≥ 90
License
MIT © Featurely
Support
- 📧 Email: [email protected]
- 🌐 Website: featurely.no
- 📖 Documentation: featurely.no/docs
- 🐛 Issues: GitHub Issues
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Made with ❤️ by Featurely
