sitepong
v0.0.15
Published
Official SitePong SDK for error tracking and monitoring
Maintainers
Readme
Installation
npm install sitepongQuick Start
import sitepong from 'sitepong';
sitepong.init({
apiKey: 'your-api-key',
environment: 'production',
release: '1.0.0',
});
// Errors are automatically captured!
// Or capture manually:
sitepong.captureError(new Error('Something went wrong'));Features
Error Tracking
Automatic error capture for uncaught exceptions and unhandled promise rejections. Works in both browser and Node.js environments.
// Automatic capture - just initialize!
sitepong.init({ apiKey: 'your-api-key' });
// Manual capture with context
try {
riskyOperation();
} catch (error) {
sitepong.captureError(error, {
tags: { component: 'checkout' },
extra: { orderId: '12345' },
});
}
// Capture messages
sitepong.captureMessage('User signed up', 'info', {
user: { id: 'user-123' },
});Session Replay
Record and replay user sessions to see exactly what happened before an error. Privacy-focused with automatic input masking.
sitepong.init({
apiKey: 'your-api-key',
replay: {
enabled: true,
maskInputs: true, // Mask sensitive inputs
blockSelector: '.private', // Block specific elements
sampleRate: 0.5, // Record 50% of sessions
recordNetwork: true, // Capture XHR/fetch requests
recordConsole: true, // Capture console logs
},
});
// Manual control
sitepong.startReplay();
sitepong.stopReplay();
const sessionId = sitepong.getReplaySessionId();Feature Flags
Ship features with confidence using real-time feature flags and A/B testing.
sitepong.init({
apiKey: 'your-api-key',
enableFlags: true,
});
// Wait for flags to load
await sitepong.waitForFlags();
// Boolean flags
if (sitepong.getFlag('new-checkout', false)) {
showNewCheckout();
}
// Multivariate flags / A/B tests
const variant = sitepong.getVariant('button-color', 'blue');
const payload = sitepong.getVariantPayload('pricing-test');
// Get all flags
const allFlags = sitepong.getAllFlags();Product Analytics
Understand user behavior with event tracking and autocapture.
sitepong.init({
apiKey: 'your-api-key',
analytics: {
enabled: true,
autocapturePageviews: true,
autocaptureClicks: true,
autocaptureForms: true,
},
});
// Track custom events
sitepong.track('Purchase Completed', {
product: 'Pro Plan',
revenue: 99,
});
// Identify users
sitepong.identify('user-123', {
name: 'John Doe',
email: '[email protected]',
plan: 'pro',
});
// Group users
sitepong.group('company-456', {
name: 'Acme Inc',
industry: 'Technology',
});
// Manual page views
sitepong.trackPageView('/checkout');Device Intelligence & Fraud Detection
Identify devices and detect fraudulent activity with advanced fingerprinting.
sitepong.init({
apiKey: 'your-api-key',
fingerprint: {
enabled: true,
extendedSignals: true,
},
});
// Get stable visitor ID
const { visitorId, confidence } = await sitepong.getVisitorId();
// Get device signals
const signals = await sitepong.getDeviceSignals();
// Fraud detection
const fraud = await sitepong.getFraudCheck();
if (fraud.riskScore > 0.8) {
blockTransaction();
}Performance Monitoring
Track performance with Web Vitals, custom transactions, and distributed tracing.
sitepong.init({
apiKey: 'your-api-key',
performance: {
enabled: true,
webVitals: true,
navigationTiming: true,
resourceTiming: true,
sampleRate: 1.0,
},
});
// Get Web Vitals
const vitals = sitepong.getWebVitals();
// { LCP: 1200, FID: 50, CLS: 0.1, FCP: 800, TTFB: 200 }
// Custom transactions
const txId = sitepong.startTransaction('checkout-flow');
const spanId = sitepong.startSpan(txId, 'validate-cart');
// ... do work
sitepong.endSpan(txId, spanId);
sitepong.endTransaction(txId);
// Distributed tracing
import { createTraceContext, propagateTrace } from 'sitepong';
const trace = createTraceContext();
fetch('/api/order', {
headers: propagateTrace(trace),
});Cron Monitoring
Monitor scheduled jobs and get alerted when they fail or miss a schedule.
sitepong.init({
apiKey: 'your-api-key',
crons: { enabled: true },
});
// Simple check-in
await sitepong.cronCheckin('daily-backup');
// Start/end pattern
const cron = sitepong.cronStart('nightly-sync');
try {
await performSync();
await cron.ok();
} catch (error) {
await cron.error();
}
// Wrap async functions
await sitepong.cronWrap('hourly-cleanup', async () => {
await cleanupOldRecords();
});Custom Metrics
Track business and application metrics with counters, gauges, and histograms.
sitepong.init({
apiKey: 'your-api-key',
metrics: { enabled: true },
});
// Counters
sitepong.metricIncrement('api.requests', 1, { tags: { endpoint: '/users' } });
// Gauges
sitepong.metricGauge('queue.size', 42);
// Histograms
sitepong.metricHistogram('response.size', 1024);
// Distributions
sitepong.metricDistribution('payment.amount', 99.99);
// Timing
await sitepong.metricTime('db.query', async () => {
return await db.query('SELECT * FROM users');
});
// Manual timer
const timer = sitepong.metricStartTimer('operation.duration');
// ... do work
timer.stop();Database Query Tracking
Monitor database performance and detect N+1 query patterns.
sitepong.init({
apiKey: 'your-api-key',
database: {
enabled: true,
slowQueryThreshold: 100, // Log queries over 100ms
redactParams: true, // Redact sensitive parameters
},
});
// Track queries
const users = await sitepong.dbTrack(
'SELECT * FROM users WHERE id = ?',
() => db.query('SELECT * FROM users WHERE id = ?', [userId])
);
// Detect N+1 patterns
const patterns = sitepong.getDbNPlusOnePatterns();
// [{ query: 'SELECT * FROM orders WHERE user_id = ?', count: 50 }]Production Profiling
Profile your production code to identify performance bottlenecks.
sitepong.init({
apiKey: 'your-api-key',
profiling: {
enabled: true,
sampleRate: 0.1, // Profile 10% of operations
maxDuration: 30000, // Max 30s profiles
},
});
// Profile async operations
const result = await sitepong.profile('processOrder', async () => {
return await processOrder(orderId);
});
// Manual spans
const endSpan = sitepong.startProfileSpan('validate');
// ... validation logic
endSpan();React Integration
First-class React support with components and hooks.
import { ... } from 'sitepong/react';Provider & Error Boundary
import { SitePongProvider, SitePongErrorBoundary } from 'sitepong/react';
function App() {
return (
<SitePongProvider
apiKey="your-api-key"
config={{
environment: 'production',
analytics: { enabled: true, autocapturePageviews: true },
replay: { enabled: true },
}}
>
<SitePongErrorBoundary fallback={<ErrorPage />}>
<YourApp />
</SitePongErrorBoundary>
</SitePongProvider>
);
}Hooks
import {
// Core
useSitePong,
useCaptureException,
useSetUser,
// Feature Flags
useFeatureFlag,
useExperiment,
// Analytics
useTrack,
useIdentify,
// Fingerprinting
useVisitorId,
useFraudCheck,
// Performance
useWebVitals,
usePerformanceTransaction,
// Replay
useReplay,
} from 'sitepong/react';
function CheckoutButton() {
const track = useTrack();
const showNewDesign = useFeatureFlag('new-checkout-design', false);
const { variant } = useExperiment('button-color');
const handleClick = () => {
track('Checkout Started', { items: cart.length });
// ...
};
return (
<button
onClick={handleClick}
style={{ background: variant === 'red' ? 'red' : 'blue' }}
>
{showNewDesign ? 'Complete Purchase' : 'Checkout'}
</button>
);
}Framework Integration
Next.js
// app/providers.tsx
'use client';
import { SitePongProvider } from 'sitepong/react';
export function Providers({ children }) {
return (
<SitePongProvider
apiKey={process.env.NEXT_PUBLIC_SITEPONG_KEY}
config={{
environment: process.env.NODE_ENV,
replay: { enabled: true },
}}
>
{children}
</SitePongProvider>
);
}Express
import express from 'express';
import sitepong from 'sitepong';
const app = express();
sitepong.init({
apiKey: process.env.SITEPONG_KEY,
environment: 'production',
});
// Error handling middleware
app.use((err, req, res, next) => {
sitepong.captureError(err, {
extra: {
url: req.url,
method: req.method,
userId: req.user?.id,
},
});
next(err);
});Node.js
import sitepong from 'sitepong';
sitepong.init({
apiKey: process.env.SITEPONG_KEY,
environment: process.env.NODE_ENV,
});
// Uncaught exceptions and unhandled rejections
// are automatically capturedConfiguration Reference
sitepong.init({
// Required
apiKey: 'your-api-key',
// Core
endpoint: 'https://ingest.sitepong.com',
environment: 'production',
release: '1.0.0',
autoCapture: true,
maxBatchSize: 10,
flushInterval: 5000,
debug: false,
// Feature Flags
enableFlags: false,
flagsEndpoint: undefined,
// Analytics
analytics: {
enabled: false,
autocapturePageviews: false,
autocaptureClicks: false,
autocaptureForms: false,
},
// Session Replay
replay: {
enabled: false,
maskInputs: true,
blockSelector: undefined,
maskSelector: undefined,
sampleRate: 1.0,
maxSessionDuration: 3600000,
recordNetwork: false,
recordConsole: false,
},
// Performance
performance: {
enabled: false,
webVitals: true,
navigationTiming: true,
resourceTiming: false,
sampleRate: 1.0,
},
// Fingerprinting
fingerprint: {
enabled: false,
extendedSignals: false,
},
// Cron Monitoring
crons: {
enabled: false,
},
// Custom Metrics
metrics: {
enabled: false,
flushInterval: 10000,
maxBatchSize: 100,
},
// Database Tracking
database: {
enabled: false,
slowQueryThreshold: 100,
redactParams: true,
},
// Profiling
profiling: {
enabled: false,
sampleRate: 0.1,
maxDuration: 30000,
},
});API Reference
Core
| Method | Description |
|--------|-------------|
| init(config) | Initialize the SDK |
| captureError(error, context?) | Capture an error |
| captureMessage(message, level?, context?) | Capture a message |
| setUser(user) | Set user context |
| setTags(tags) | Set tags |
| setContext(context) | Set additional context |
| flush() | Flush the error queue |
Feature Flags
| Method | Description |
|--------|-------------|
| getFlag(key, defaultValue?) | Get boolean flag |
| getVariant(key, defaultValue?) | Get variant key |
| getVariantPayload(key, defaultValue?) | Get variant payload |
| getAllFlags() | Get all flags |
| waitForFlags() | Wait for flags to load |
| areFlagsReady() | Check if flags are loaded |
| refreshFlags() | Refresh flags from server |
Analytics
| Method | Description |
|--------|-------------|
| track(event, properties?) | Track custom event |
| trackPageView(url?, properties?) | Track page view |
| identify(userId, traits?) | Identify user |
| group(groupId, traits?) | Group users |
| resetAnalytics() | Reset analytics state |
Session Replay
| Method | Description |
|--------|-------------|
| startReplay() | Start recording |
| stopReplay() | Stop recording |
| isReplayRecording() | Check if recording |
| getReplaySessionId() | Get session ID |
Performance
| Method | Description |
|--------|-------------|
| startTransaction(name, data?) | Start transaction |
| endTransaction(id, status?) | End transaction |
| startSpan(txId, name, data?) | Start span |
| endSpan(txId, spanId, status?) | End span |
| getWebVitals() | Get Web Vitals |
Fingerprinting
| Method | Description |
|--------|-------------|
| getVisitorId() | Get visitor ID |
| getDeviceSignals() | Get device signals |
| getFraudCheck() | Run fraud check |
Metrics
| Method | Description |
|--------|-------------|
| metricIncrement(name, value?, options?) | Increment counter |
| metricGauge(name, value, options?) | Set gauge |
| metricHistogram(name, value, options?) | Record histogram |
| metricDistribution(name, value, options?) | Record distribution |
| metricTime(name, fn, options?) | Time async function |
| metricStartTimer(name, options?) | Start manual timer |
Cron Monitoring
| Method | Description |
|--------|-------------|
| cronCheckin(slug, options?) | Simple check-in |
| cronStart(slug, environment?) | Start cron job |
| cronWrap(slug, fn, environment?) | Wrap async function |
Database
| Method | Description |
|--------|-------------|
| dbTrack(query, fn, source?) | Track async query |
| dbTrackSync(query, fn, source?) | Track sync query |
| getDbQueryCount() | Get query count |
| getDbNPlusOnePatterns() | Get N+1 patterns |
Profiling
| Method | Description |
|--------|-------------|
| profile(name, fn, metadata?) | Profile async function |
| startProfileSpan(name, metadata?) | Start profile span |
| getProfiles() | Get all profiles |
| getLatestProfile() | Get latest profile |
| flushProfiles() | Flush profiles |
Documentation
For full documentation, visit sitepong.com/docs.
License
MIT
