TypeScript SDK for Metrixly performance monitoring
npm install @metrixly/sdk-v0A lightweight, framework-agnostic performance monitoring library for JavaScript/TypeScript applications. Monitor API endpoint performance and distributed traces with automatic instrumentation for fetch and axios, plus manual tracing capabilities.
- 🚀 Automatic Instrumentation - Zero-config monitoring for fetch and axios HTTP clients
- 📊 Manual Tracing - Create custom traces with spans for business logic and operations
- 🔄 Efficient Batching - Smart batching with configurable thresholds and automatic flushing
- ⚡ Retry Logic - Exponential backoff with jitter for reliable data delivery
- 📦 Tree-Shakeable - Optimized for modern bundlers with minimal overhead
- 🌐 Multi-Environment - Works seamlessly in Node.js, browsers, and edge runtimes
- 💪 TypeScript First - Comprehensive type definitions with excellent IDE support
- 🎯 Framework Agnostic - Use with Next.js, Express, React, Vue, or any JavaScript framework
``bashnpm
npm install @metrixly/sdk
Quick Start
$3
`typescript
import { MetrixlyClient } from '@metrixly/sdk'// Initialize the client with your backend URL and API key
const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key-from-dashboard'
})
// Enable automatic fetch instrumentation
metrixly.enableFetchInstrumentation()
// All fetch calls are now automatically monitored
await fetch('https://api.example.com/users')
`$3
The SDK automatically captures all fetch requests when instrumentation is enabled:
`typescript
import { MetrixlyClient } from '@metrixly/sdk'const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key'
})
// Enable fetch instrumentation
metrixly.enableFetchInstrumentation()
// These requests are automatically tracked
const users = await fetch('https://api.example.com/users')
const posts = await fetch('https://api.example.com/posts')
// Disable when needed
metrixly.disableFetchInstrumentation()
`$3
For applications using axios, enable instrumentation per axios instance:
`typescript
import axios from 'axios'
import { MetrixlyClient } from '@metrixly/sdk'const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key'
})
// Create your axios instance
const api = axios.create({
baseURL: 'https://api.example.com'
})
// Enable instrumentation for this instance
metrixly.enableAxiosInstrumentation(api)
// All requests with this instance are now tracked
await api.get('/users')
await api.post('/posts', { title: 'Hello' })
// Disable when needed
metrixly.disableAxiosInstrumentation(api)
`$3
Create custom traces to monitor business logic and operations:
`typescript
import {MetrixlyClient} from '@metrixly/sdk'const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key'
})
// Start a trace for a complex operation
const trace = metrixly.startTrace('process-order', {
orderId: '12345',
userId: 'user-789'
})
// Add spans for individual steps
trace.addSpan('validate-order', {items: 3})
trace.addSpan('check-inventory')
trace.addSpan('charge-payment', {amount: 99.99})
trace.addSpan('send-confirmation')
// Complete the trace
trace.end('completed', {totalAmount: 99.99})
`$3
Track async operations by measuring durations:
`typescript
const trace = metrixly.startTrace('user-signup')// Measure validation
await validateUserInput(userData)
trace.addSpan('validate-input')
// Measure database operation
await createUserInDatabase(userData)
trace.addSpan('create-user')
// Measure email sending
await sendWelcomeEmail(userData.email)
trace.addSpan('send-email')
// Complete the trace
trace.end('completed', { userId: newUser.id })
`Configuration Options
All configuration options with their defaults:
`typescript
const metrixly = new MetrixlyClient({
// Required
baseUrl: 'https://metrixly.example.com', // Your Metrixly backend URL
apiKey: 'your-api-key', // API key from dashboard
// Optional
batchSize: 10, // Number of items to batch before sending
flushInterval: 30000, // Time in ms between automatic flushes (30s)
maxRetries: 3, // Maximum retry attempts for failed requests
retryDelay: 1000, // Base delay in ms for retry backoff (1s)
enableAutoInstrumentation: true, // Auto-enable fetch instrumentation
debug: false, // Enable debug logging
logger: console // Custom logger implementation
})
`$3
####
baseUrl (required)
The URL where your Metrixly backend is deployed. Must be a valid URL.`typescript
baseUrl: 'https://metrixly.example.com'
`####
apiKey (required)
Your API key from the Metrixly dashboard. Used to authenticate requests and identify your project/application.`typescript
apiKey: 'mtx_1234567890abcdef'
`####
batchSize (optional, default: 10)
Number of metrics or traces to accumulate before automatically sending to the backend. Lower values mean more frequent network requests but lower latency. Higher values reduce network overhead.`typescript
batchSize: 20 // Send every 20 items
`####
flushInterval (optional, default: 30000)
Time in milliseconds between automatic flushes. Even if the batch size isn't reached, data will be sent at this interval.`typescript
flushInterval: 60000 // Flush every 60 seconds
`####
maxRetries (optional, default: 3)
Maximum number of retry attempts for failed network requests. Uses exponential backoff with jitter.`typescript
maxRetries: 5 // Retry up to 5 times
`####
retryDelay (optional, default: 1000)
Base delay in milliseconds for retry backoff. Actual delay increases exponentially: delay * (2 ^ attempt).`typescript
retryDelay: 2000 // Start with 2s delay
`####
enableAutoInstrumentation (optional, default: true)
Automatically enable fetch instrumentation on initialization. Set to false if you want to manually control when instrumentation starts.`typescript
enableAutoInstrumentation: false // Don't auto-enable
`####
debug (optional, default: false)
Enable debug logging to see detailed SDK operations. Useful for troubleshooting.`typescript
debug: true // Enable debug logs
`####
logger (optional, default: console)
Custom logger implementation. Must implement the Logger interface with debug, info, warn, and error methods.`typescript
// Custom logger example
const customLogger = {
debug: (msg, ...args) => { / custom debug / },
info: (msg, ...args) => { / custom info / },
warn: (msg, ...args) => { / custom warn / },
error: (msg, ...args) => { / custom error / }
}const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key',
logger: customLogger
})
`API Reference
$3
Main SDK class for monitoring and tracing.
#### Constructor
`typescript
new MetrixlyClient(config: MetrixlyConfig)
`Creates a new Metrixly client instance. Throws
MetrixlyError if configuration is invalid.#### Methods
#####
enableFetchInstrumentation()Enable automatic instrumentation for the global
fetch function.`typescript
metrixly.enableFetchInstrumentation()
`#####
disableFetchInstrumentation()Disable fetch instrumentation and restore original fetch behavior.
`typescript
metrixly.disableFetchInstrumentation()
`#####
enableAxiosInstrumentation(axiosInstance)Enable instrumentation for a specific axios instance.
`typescript
const api = axios.create({ baseURL: 'https://api.example.com' })
metrixly.enableAxiosInstrumentation(api)
`#####
disableAxiosInstrumentation(axiosInstance)Disable instrumentation for a specific axios instance.
`typescript
metrixly.disableAxiosInstrumentation(api)
`#####
startTrace(name, metadata?)Start a new manual trace.
`typescript
const trace = metrixly.startTrace('operation-name', {
userId: '123',
customField: 'value'
})
`Parameters:
-
name (string): Name of the trace
- metadata (object, optional): Additional context dataReturns:
Trace instance#####
flush()Manually flush all buffered metrics and traces. Returns a promise that resolves when complete.
`typescript
await metrixly.flush()
`Returns:
Promise#####
destroy()Clean up resources and disable all instrumentation. Call before application shutdown.
`typescript
metrixly.destroy()
`$3
Interface for manual tracing operations.
#### Properties
-
id (string, readonly): Unique trace identifier
- name (string, readonly): Name of the trace
- startTime (Date, readonly): When the trace started#### Methods
#####
addSpan(name, duration, metadata?)Add a span to the trace representing an operation.
`typescript
trace.addSpan('database-query', 150, {
query: 'SELECT * FROM users',
rows: 42
})
`Parameters:
-
name (string): Name of the span/operation
- duration (number): Duration in milliseconds
- metadata (object, optional): Additional context data#####
end(status, metadata?)Complete the trace and send it to the backend.
`typescript
trace.end('completed', { result: 'success' })
// or
trace.end('failed', { error: 'timeout' })
`Parameters:
-
status ('completed' | 'failed'): Final status of the trace
- metadata (object, optional): Additional context dataFramework Integration
$3
`typescript
// lib/metrixly.ts
import { MetrixlyClient } from '@metrixly/sdk'export const metrixly = new MetrixlyClient({
baseUrl: process.env.NEXT_PUBLIC_METRIXLY_URL!,
apiKey: process.env.NEXT_PUBLIC_METRIXLY_API_KEY!
})
// Enable fetch instrumentation
metrixly.enableFetchInstrumentation()
``typescript
// app/api/users/route.ts
import { metrixly } from '@/lib/metrixly'export async function GET() {
const trace = metrixly.startTrace('fetch-users')
try {
const users = await fetchUsers()
trace.addSpan('fetch-users')
trace.end('completed')
return Response.json(users)
} catch (error) {
trace.end('failed', { error: error.message })
throw error
}
}
`$3
`typescript
// server.ts
import express from 'express'
import { MetrixlyClient } from '@metrixly/sdk'const app = express()
const metrixly = new MetrixlyClient({
baseUrl: process.env.METRIXLY_URL,
apiKey: process.env.METRIXLY_API_KEY
})
metrixly.enableFetchInstrumentation()
// Middleware to trace requests
app.use((req, res, next) => {
const trace = metrixly.startTrace(
${req.method} ${req.path})
res.on('finish', () => {
trace.end(res.statusCode < 400 ? 'completed' : 'failed', {
statusCode: res.statusCode,
method: req.method,
path: req.path
})
})
next()
})// Graceful shutdown
process.on('SIGTERM', async () => {
await metrixly.flush()
metrixly.destroy()
process.exit(0)
})
`$3
`typescript
// hooks/useMetrixly.ts
import { useEffect } from 'react'
import { metrixly } from '@/lib/metrixly'export function useMetrixly() {
useEffect(() => {
// Enable instrumentation when app mounts
metrixly.enableFetchInstrumentation()
return () => {
// Clean up on unmount
metrixly.disableFetchInstrumentation()
}
}, [])
return metrixly
}
``typescript
// components/UserList.tsx
import { useMetrixly } from '@/hooks/useMetrixly'export function UserList() {
const metrixly = useMetrixly()
const loadUsers = async () => {
const trace = metrixly.startTrace('load-users')
try {
const response = await fetch('/api/users')
const users = await response.json()
trace.addSpan('fetch-users')
trace.end('completed', { count: users.length })
return users
} catch (error) {
trace.end('failed', { error: error.message })
throw error
}
}
// ... rest of component
}
`Troubleshooting
$3
Check your configuration:
- Verify
baseUrl is correct and accessible
- Verify apiKey is valid and matches your project
- Check network connectivity to your Metrixly backendEnable debug logging:
`typescript
const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key',
debug: true // Enable debug logs
})
`Check browser console or server logs for error messages.
$3
Ensure instrumentation is enabled:
`typescript
metrixly.enableFetchInstrumentation()
`Check if fetch is being called after instrumentation is enabled. Instrumentation only affects fetch calls made after
enableFetchInstrumentation() is called.Verify fetch is available in your environment. The SDK requires native fetch support.
$3
Ensure you're passing the axios instance:
`typescript
const api = axios.create({ baseURL: 'https://api.example.com' })
metrixly.enableAxiosInstrumentation(api) // Pass the instance
`Instrumentation is per-instance. If you have multiple axios instances, enable instrumentation for each one.
Check axios version. The SDK requires axios ^1.0.0.
$3
Reduce batch size to send data more frequently:
`typescript
const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key',
batchSize: 5, // Smaller batches
flushInterval: 10000 // Flush more frequently (10s)
})
`Call flush() periodically in long-running applications:
`typescript
setInterval(async () => {
await metrixly.flush()
}, 60000) // Flush every minute
`$3
Ensure you have TypeScript 5.0+ installed:
`bash
npm install -D typescript@^5.0.0
`Check your tsconfig.json includes proper module resolution:
`json
{
"compilerOptions": {
"moduleResolution": "bundler",
"esModuleInterop": true
}
}
`$3
Always flush before shutdown:
`typescript
// Node.js
process.on('SIGTERM', async () => {
await metrixly.flush()
metrixly.destroy()
process.exit(0)
})// Browser (before unload)
window.addEventListener('beforeunload', async () => {
await metrixly.flush()
})
`$3
Ensure your Metrixly backend allows CORS from your application's origin. Configure CORS headers on your backend:
`
Access-Control-Allow-Origin: https://your-app.com
Access-Control-Allow-Headers: X-Api-Key, Content-Type
`$3
The SDK automatically retries failed requests with exponential backoff. Check logs for retry attempts:
`typescript
const metrixly = new MetrixlyClient({
baseUrl: 'https://metrixly.example.com',
apiKey: 'your-api-key',
maxRetries: 5, // Increase retries
retryDelay: 2000, // Increase initial delay
debug: true // See retry attempts in logs
})
`Best Practices
$3
Create a single client instance and export it:
`typescript
// lib/metrixly.ts
export const metrixly = new MetrixlyClient({ ... })
`$3
Always flush buffered data before your application exits:
`typescript
process.on('SIGTERM', async () => {
await metrixly.flush()
metrixly.destroy()
})
`$3
Choose descriptive names that help identify operations:
`typescript
// Good
metrixly.startTrace('user-registration')
metrixly.startTrace('payment-processing')// Avoid
metrixly.startTrace('operation')
metrixly.startTrace('trace1')
`$3
Include relevant information in metadata:
`typescript
const trace = metrixly.startTrace('process-order', {
orderId: order.id,
userId: user.id,
amount: order.total
})
`$3
Always complete traces, even on errors:
`typescript
const trace = metrixly.startTrace('api-call')
try {
await someOperation()
trace.end('completed')
} catch (error) {
trace.end('failed', { error: error.message })
throw error
}
`$3
Focus on critical paths and operations. Too much instrumentation can impact performance.
$3
Balance between network overhead and data freshness:
- High-traffic apps: Larger batch sizes (20-50)
- Low-traffic apps: Smaller batch sizes (5-10)
Development
`bash
Install dependencies
bun installRun tests
bun testRun tests in watch mode
bun test:watchBuild
bun run buildWatch mode for development
bun run devLint
bun run lintFormat code
bun run format
``Contributions are welcome! Please feel free to submit a Pull Request.
MIT
For issues and questions:
- GitHub Issues: https://github.com/yourusername/metrixly/issues
- Documentation: https://metrixly.example.com/docs