@lavarage/telemetry
v1.2.2
Published
Production telemetry SDK for Lavarage and partner applications
Downloads
56
Maintainers
Readme
@lavarage/telemetry
Production telemetry SDK for Lavarage and partner applications. Track user activity, network requests, and errors with comprehensive filtering and privacy controls.
Installation
npm install @lavarage/telemetryQuick Start
import { LavarageTelemetry } from '@lavarage/telemetry';
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
});
// Intercept network requests
telemetry.interceptFetch();
// Connect wallet (triggers login event)
// Wallet platform is automatically detected (MetaMask, Phantom, etc.)
// or you can specify it manually:
telemetry.setWallet('YourWalletAddress123...', 'MetaMask');
// Track trading pair views
telemetry.trackPairView('SOL/USDC', { source: 'homepage' });Configuration
Basic Configuration
const telemetry = new LavarageTelemetry({
apiEndpoint: string; // Required: Backend API endpoint
platform: string; // Required: Platform identifier (e.g., 'lavarage-web')
captureHosts?: HostFilterInput; // Optional: Host filtering configuration
errorFilters?: ErrorFilterConfig; // Optional: Error filtering configuration
batchSize?: number; // Optional: Max events per batch (default: 50)
flushInterval?: number; // Optional: Flush interval in ms (default: 5000)
});Host Filtering
Control which network requests are captured using flexible host filtering.
String Configuration
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
captureHosts: 'api.lavarage.com', // Only capture requests to this host
});Array Configuration
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
captureHosts: [
'api.lavarage.com',
'partner-api.com',
'*.example.com' // Wildcard: matches any subdomain
],
});Object Configuration
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
captureHosts: {
mode: 'include', // 'all' | 'none' | 'include' | 'exclude'
hosts: ['api.lavarage.com', '*.partner.com'],
patterns: ['^api\\..*\\.lavarage\\.com$'] // Regex patterns
},
});Wildcard Matching
*.example.com- Matches any subdomain (e.g.,api.example.com,www.example.com)example.com- Matches the domain and all subdomains
Update Host Filter at Runtime
telemetry.updateHostFilter({
mode: 'exclude',
hosts: ['analytics.google.com', '*.tracking.com']
});Error Filtering
Filter which errors are captured using include/exclude patterns.
Example 1: Only Capture Specific Errors
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
errorFilters: {
include: [
'Failed to fetch',
'Network error',
'Transaction.*failed',
'RPC.*error'
]
}
});Example 2: Exclude Noisy Errors
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
errorFilters: {
exclude: [
'ResizeObserver',
'Extension context invalidated',
'Script error',
'Non-Error promise rejection'
]
}
});Example 3: Combined Filtering
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
errorFilters: {
include: ['.*'], // Capture everything
exclude: [
'chrome-extension://',
'moz-extension://',
'webkit-masked-url://',
'ResizeObserver loop',
'Script error\\.'
]
}
});Filter Logic:
- If
includepatterns are provided, ONLY errors matching those patterns are captured - If
excludepatterns are provided, all errors EXCEPT those matching patterns are captured - If both are provided,
includeis applied first, thenexclude
Axios Integration
If you're using Axios, you can intercept Axios requests:
import axios from 'axios';
import { LavarageTelemetry } from '@lavarage/telemetry';
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
});
const axiosInstance = axios.create({
baseURL: 'https://api.lavarage.com',
});
// Intercept Axios requests
telemetry.interceptAxios(axiosInstance);Security Features
Automatic Data Sanitization
The SDK automatically sanitizes sensitive data in all payloads and responses:
privateKeymnemonicpasswordsecrettokenapiKeyauthorization
Sensitive fields are replaced with [REDACTED] recursively in nested objects and arrays.
Silent Error Handling
All telemetry operations are wrapped in try-catch blocks. Telemetry errors will never disrupt your application.
API Reference
Methods
setWallet(walletAddress: string, walletPlatform?: string)
Set the current wallet address and trigger a login event. The wallet platform (e.g., 'MetaMask', 'Phantom', 'WalletConnect') is automatically detected from the browser environment, but you can also specify it manually.
Supported auto-detected platforms:
- MetaMask
- Coinbase Wallet
- Trust Wallet
- WalletConnect
- Phantom (Solana)
- Solflare (Solana)
- Generic Ethereum/Solana providers
// Auto-detect wallet platform
telemetry.setWallet('YourWalletAddress123...');
// Or specify manually
telemetry.setWallet('YourWalletAddress123...', 'MetaMask');interceptFetch()
Intercept the global fetch API to capture network requests.
telemetry.interceptFetch();interceptAxios(axiosInstance: any)
Intercept an Axios instance to capture network requests.
telemetry.interceptAxios(axiosInstance);trackPairView(pair: string, metadata?: object)
Track a trading pair view event.
telemetry.trackPairView('SOL/USDC', {
source: 'homepage',
category: 'trending'
});trackSystemEvent(category: string, message: string, level?: string, metadata?: object)
Track a system event (not tied to any wallet address). System events are displayed in a separate panel in the dashboard.
// Track app startup
telemetry.trackSystemEvent('app_start', 'Application initialized', 'info');trackStateChange(stateName: string, previousValue?: any, newValue?: any, action?: string, metadata?: object)
Track a React state change. Useful for debugging and understanding user interactions.
// Track a state change manually
telemetry.trackStateChange(
'userPreferences',
{ theme: 'light' },
{ theme: 'dark' },
'TOGGLE_THEME',
{ source: 'settings-panel' }
);// Track feature usage telemetry.trackSystemEvent('feature_used', 'User enabled dark mode', 'info', { feature: 'dark_mode', version: '1.2.3' });
// Track configuration changes telemetry.trackSystemEvent('config_change', 'API endpoint updated', 'warning', { old_endpoint: 'https://api.example.com', new_endpoint: 'https://api2.example.com' });
// Track errors telemetry.trackSystemEvent('system_error', 'Failed to load configuration', 'error', { error_code: 'CONFIG_LOAD_FAILED' });
**Parameters:**
- `category` - Event category (e.g., 'app_start', 'feature_used', 'config_change')
- `message` - Event message
- `level` - Event level: 'info' | 'warning' | 'error' | 'debug' (default: 'info')
- `metadata` - Optional additional metadata object
#### `updateHostFilter(captureHosts: HostFilterInput)`
Update the host filter configuration at runtime.
```typescript
telemetry.updateHostFilter({
mode: 'exclude',
hosts: ['analytics.google.com']
});logWalletEvent(walletAddress: string, eventType: string, message: string, metadata?: object)
Log a custom event with wallet address (backend-friendly method). Events are queued and sent in batches.
telemetry.logWalletEvent(
'WalletAddress123...',
'transaction',
'Transaction completed',
{ txHash: '0x...', amount: '100' }
);sendLog(walletAddress: string, eventType: string, message: string, metadata?: object): Promise<void>
Send a log event immediately, bypassing the batch queue. Useful for critical logs.
await telemetry.sendLog(
'WalletAddress123...',
'critical',
'Security alert',
{ alertType: 'suspicious_activity' }
);destroy()
Clean up the telemetry instance, restore original functions, and flush remaining events.
telemetry.destroy();React State Tracking
The SDK provides React hooks for automatically tracking state changes in your React components.
Installation
# Install the SDK
npm install @lavarage/telemetry
# If you want to use React hooks, also install React (peer dependency)
npm install reactQuick Start
import { LavarageTelemetry } from '@lavarage/telemetry';
// Import React hooks from the separate entry point
import { useTrackedState } from '@lavarage/telemetry/react';
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'lavarage-web',
});
function MyComponent() {
// Automatically tracks all state changes
const [count, setCount] = useTrackedState(0, {
stateName: 'counter',
telemetry: telemetry,
action: 'SET_COUNT'
});
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}Available Hooks
useTrackedState(initialState, config)
Wraps React's useState and automatically tracks state changes.
const [state, setState] = useTrackedState(initialValue, {
stateName: 'userPreferences', // Required: name for this state
telemetry: telemetryInstance, // Required: telemetry instance
trackInitial: false, // Optional: track initial state (default: false)
action: 'UPDATE_PREFERENCES', // Optional: action name
metadata: { source: 'settings' }, // Optional: additional metadata
shouldTrack: (prev, next) => { // Optional: filter which changes to track
return prev !== next; // Only track if values actually changed
}
});useTrackedReducer(reducer, initialState, config)
Wraps React's useReducer and automatically tracks state changes with action information.
const [state, dispatch] = useTrackedReducer(reducer, initialState, {
stateName: 'cart',
telemetry: telemetryInstance,
trackInitial: false,
metadata: { userId: '123' }
});
// Dispatch actions normally - they'll be tracked automatically
dispatch({ type: 'ADD_ITEM', payload: { id: 1, name: 'Product' } });useStateTracker(telemetry)
Returns a function to manually track state changes with more control.
const trackState = useStateTracker(telemetry);
const handleChange = (newValue) => {
trackState('theme', currentValue, newValue, 'SET_THEME', {
source: 'user-action'
});
setCurrentValue(newValue);
};Configuration Options
- stateName (required): A unique identifier for this state (e.g., 'cart', 'userPreferences', 'theme')
- telemetry (required): Your telemetry instance
- trackInitial (optional): Whether to track the initial state value (default: false)
- action (optional): Action name to use when tracking (default: 'STATE_CHANGE')
- metadata (optional): Additional context to include with each state change
- shouldTrack (optional): Function to filter which changes to track - useful for avoiding noise
Example: Shopping Cart
import { useTrackedState } from '@lavarage/telemetry/react';
function ShoppingCart() {
const [items, setItems] = useTrackedState([], {
stateName: 'cartItems',
telemetry: telemetry,
action: 'CART_UPDATE',
shouldTrack: (prev, next) => {
// Only track if cart actually changed (not just reference)
return JSON.stringify(prev) !== JSON.stringify(next);
}
});
const addItem = (item) => {
setItems([...items, item]);
// State change is automatically tracked!
};
return (
<div>
{items.map(item => <div key={item.id}>{item.name}</div>)}
<button onClick={() => addItem({ id: 1, name: 'Product' })}>
Add Item
</button>
</div>
);
}Example: User Preferences with useReducer
import { useTrackedReducer } from '@lavarage/telemetry/react';
function preferencesReducer(state, action) {
switch (action.type) {
case 'SET_THEME':
return { ...state, theme: action.payload };
case 'SET_LANGUAGE':
return { ...state, language: action.payload };
default:
return state;
}
}
function UserPreferences() {
const [prefs, dispatch] = useTrackedReducer(
preferencesReducer,
{ theme: 'light', language: 'en' },
{
stateName: 'userPreferences',
telemetry: telemetry,
metadata: { userId: currentUser.id }
}
);
return (
<div>
<button onClick={() => dispatch({ type: 'SET_THEME', payload: 'dark' })}>
Dark Mode
</button>
{/* State changes are automatically tracked with action type! */}
</div>
);
}Event Types
The SDK tracks the following event types:
- login: Triggered when
setWallet()is called - pair_view: Trading pair view events
- error: Console errors, uncaught exceptions, and unhandled promise rejections
- request: Network requests (fetch/Axios)
- system_event: System-level events not tied to any wallet address (displayed in separate dashboard panel)
- log: Custom log events (via
logWalletEvent()orsendLog()) - state_change: React state changes (via
trackStateChange()or React hooks)
Batching
Events are automatically batched and sent to the backend:
- Default batch size: 50 events
- Default flush interval: 5 seconds
- Automatic flush: On page unload (using
keepalivefor reliable delivery)
Backend Usage
The SDK works in both browser and Node.js environments. For backend applications, you can use a subset of features focused on manual logging.
Installation for Backend
npm install @lavarage/telemetry
# For Node.js < 18, also install node-fetch:
npm install node-fetch@2Backend Quick Start
import { LavarageTelemetry } from '@lavarage/telemetry';
// Initialize telemetry for backend
const telemetry = new LavarageTelemetry({
apiEndpoint: 'https://telemetry.lavarage.com',
platform: 'my-backend-service',
batchSize: 100, // Larger batches for backend
flushInterval: 10000, // Flush every 10 seconds
});
// Log events related to a wallet address
telemetry.logWalletEvent(
'DummyWallet123456789',
'transaction',
'Transaction completed successfully',
{
txHash: '0x123...',
amount: '100.5',
token: 'USDC'
}
);
// Log errors with wallet context
telemetry.logWalletEvent(
'DummyWallet123456789',
'error',
'Failed to process transaction',
{
errorCode: 'INSUFFICIENT_FUNDS',
attemptedAmount: '200.0'
}
);
// Send critical logs immediately (bypasses batching)
await telemetry.sendLog(
'DummyWallet123456789',
'critical',
'Security alert: suspicious activity detected',
{
alertType: 'unusual_pattern',
severity: 'high'
}
);Backend API Methods
logWalletEvent(walletAddress: string, eventType: string, message: string, metadata?: object)
Queue a log event with a wallet address. Events are batched and sent automatically.
telemetry.logWalletEvent(
'WalletAddress123...',
'transaction', // Event type (e.g., 'transaction', 'error', 'action')
'Transaction completed', // Log message
{ txHash: '0x...', amount: '100' } // Optional metadata
);sendLog(walletAddress: string, eventType: string, message: string, metadata?: object): Promise<void>
Send a log event immediately, bypassing the batch queue. Useful for critical logs that need immediate delivery.
await telemetry.sendLog(
'WalletAddress123...',
'critical',
'Security alert',
{ alertType: 'suspicious_activity' }
);setWallet(walletAddress: string, walletPlatform?: string)
Set the default wallet address for subsequent events. This is optional for backend use since you can specify the wallet in each log call. You can also optionally specify the wallet platform.
telemetry.setWallet('WalletAddress123...', 'MetaMask');
// Now all events will use this wallet by default
telemetry.logWalletEvent(
null, // Will use the wallet set above
'action',
'User performed action'
);Backend Example: Express.js Middleware
import express from 'express';
import { LavarageTelemetry } from '@lavarage/telemetry';
const telemetry = new LavarageTelemetry({
apiEndpoint: process.env.TELEMETRY_ENDPOINT!,
platform: 'api-server',
});
const app = express();
// Middleware to log wallet-related requests
app.use('/api/wallet/:walletAddress', (req, res, next) => {
const walletAddress = req.params.walletAddress;
// Log the request
telemetry.logWalletEvent(
walletAddress,
'api_request',
`${req.method} ${req.path}`,
{
method: req.method,
path: req.path,
userAgent: req.get('user-agent'),
}
);
next();
});
// Log transaction events
app.post('/api/transactions', async (req, res) => {
const { walletAddress, txHash } = req.body;
try {
// Process transaction...
telemetry.logWalletEvent(
walletAddress,
'transaction',
'Transaction processed successfully',
{ txHash, status: 'success' }
);
res.json({ success: true });
} catch (error) {
telemetry.logWalletEvent(
walletAddress,
'error',
'Transaction failed',
{ txHash, error: error.message }
);
res.status(500).json({ error: error.message });
}
});Backend Example: Error Handler
import { LavarageTelemetry } from '@lavarage/telemetry';
const telemetry = new LavarageTelemetry({
apiEndpoint: process.env.TELEMETRY_ENDPOINT!,
platform: 'api-server',
});
// Global error handler
process.on('uncaughtException', (error) => {
// Extract wallet from error context if available
const walletAddress = (error as any).walletAddress || null;
if (walletAddress) {
telemetry.logWalletEvent(
walletAddress,
'error',
`Uncaught exception: ${error.message}`,
{
stack: error.stack,
name: error.name,
}
);
}
});Browser Support
- Modern browsers with ES2020 support
- Node.js 18+ (native fetch support)
- Node.js < 18 requires
node-fetchpackage
License
MIT
