@infrasamurai/sdk-js
v0.0.1
Published
TypeScript SDK for InfraSamurai metrics, alerting, and APM tracing
Maintainers
Readme
@infrasamurai/sdk-js
TypeScript SDK for InfraSamurai metrics, alerting, and APM tracing.
Installation
npm install @infrasamurai/sdk-jsFeatures
| Entry Point | Purpose | Runtime |
|-------------|---------|---------|
| @infrasamurai/sdk-js | Core client (metrics & alerts) | Node.js, Browser, Deno, Bun |
| @infrasamurai/sdk-js/node | APM auto-instrumentation | Node.js only |
| @infrasamurai/sdk-js/browser | Browser APM tracing | Browser only |
| @infrasamurai/sdk-js/queues | Queue metrics | Node.js, Deno, Bun |
Quick Start
Metrics & Alerts
import { InfraSamuraiClient } from "@infrasamurai/sdk-js";
const client = new InfraSamuraiClient({
dsn: "your-project-dsn",
environment: "production",
});
// Send a metric
await client.sendMetric({
metricType: "photo_upload_speed",
value: 2.5,
unit: "MB/s",
});
// Send alerts
await client.critical("Server down!");
await client.error("Failed to process payment");
await client.warning("High memory usage");
await client.info("User signed in");Node.js APM (Auto-Instrumentation)
// tracing.ts - Create this file and import it FIRST in your entry point
import { InfraSamuraiNode } from "@infrasamurai/sdk-js/node";
InfraSamuraiNode.init({
dsn: process.env.ALERTSAMURAI_DSN!,
serviceName: "my-api",
serviceVersion: "1.0.0",
environment: process.env.NODE_ENV,
});
// main.ts
import "./tracing"; // MUST be first import!
import { NestFactory } from "@nestjs/core";
// ... rest of your appBrowser APM
import { InfraSamuraiBrowser } from "@infrasamurai/sdk-js/browser";
InfraSamuraiBrowser.init({
dsn: "your-project-dsn",
serviceName: "my-frontend",
environment: "production",
});
// Set user context for all traces
InfraSamuraiBrowser.setUser({
id: "user-123",
email: "[email protected]",
});Queue Metrics
import { InfraSamuraiQueues } from "@infrasamurai/sdk-js/queues";
const queues = InfraSamuraiQueues.init({
dsn: process.env.ALERTSAMURAI_DSN!,
environment: "production",
});
// Record queue metrics periodically
setInterval(async () => {
const stats = await getQueueStats();
await queues.recordMetrics("orders-queue", {
depth: stats.pending,
consumerLag: stats.lag,
processedCount: stats.processed,
failedCount: stats.failed,
});
}, 60000);Core Client
Configuration
const client = new InfraSamuraiClient({
dsn: "your-dsn", // Required - found in project settings
environment: "production", // Optional - default environment
baseUrl: "https://...", // Optional - API endpoint
timeout: 30000, // Optional - request timeout (ms)
retries: 3, // Optional - retry attempts
silent: true, // Optional - suppress console warnings
});Metrics API
await client.sendMetric({
metricType: "photo_upload_speed", // Required - metric name (max 100 chars)
value: 2.5, // Required - numeric value
unit: "MB/s", // Optional - unit (max 50 chars)
environment: "production", // Optional - overrides default
metadata: { userId: "123" }, // Optional - additional context
timestamp: new Date(), // Optional - defaults to now
});Alerts API
await client.sendAlert({
message: "Database connection failed", // Required (max 4000 chars)
priority: "critical", // critical|error|warning|info|debug
environment: "production", // Optional
data: { errorCode: "ECONNREFUSED" }, // Optional context
});
// Convenience methods
await client.critical("Server down!");
await client.error("Payment failed", { orderId: "123" });
await client.warning("High memory usage");
await client.info("User signed in");
await client.debug("Cache miss");Error Handling
The client is fault-tolerant - it never throws errors that could crash your application:
const result = await client.sendMetric({ metricType: "test", value: 123 });
if (!result.success) {
console.error("Failed:", result.error);
// result.disabled === true if DSN is missing
}For explicit error handling:
import {
InfraSamuraiError,
AuthenticationError, // 401 - Invalid DSN
ValidationError, // 400 - Invalid request
NetworkError, // Timeout, connection failure
} from "@infrasamurai/sdk-js";Retry Logic
- Default: 3 retries with exponential backoff (1s → 2s → 4s, max 10s)
- Does NOT retry on 401 (auth) or 400 (validation) errors
Node.js APM
Configuration
import { InfraSamuraiNode } from "@infrasamurai/sdk-js/node";
InfraSamuraiNode.init({
// Required
dsn: process.env.ALERTSAMURAI_DSN!,
serviceName: "my-api",
// Optional
serviceVersion: "1.0.0",
environment: "production",
baseUrl: "https://monitor.infrasamurai.com",
// Sampling (0.0 to 1.0, default: 1.0)
sampleRate: 0.1, // Trace 10% of requests
errorsSampleRate: 1.0, // Capture 100% of errors
sessionSampleRate: 1.0, // Sample by instance
// Auto-instrumentation toggles
instrumentations: {
http: true, // HTTP incoming/outgoing (default: true)
express: true, // Express.js (default: true)
nestjs: true, // NestJS (default: true)
prisma: true, // Prisma ORM (default: true)
redis: true, // Redis/ioredis (default: true)
pg: true, // PostgreSQL (default: true)
grpc: true, // gRPC (default: true)
fs: false, // Filesystem (default: false - noisy)
dns: false, // DNS lookups (default: false - noisy)
},
// Custom attributes for all spans
resourceAttributes: {
"deployment.region": "us-east-1",
},
silent: false, // Suppress warnings
debug: true, // Verbose logging
});Auto-Instrumented Libraries
The Node.js SDK automatically traces:
| Library | What's Captured | |---------|-----------------| | HTTP/HTTPS | All incoming requests, outgoing calls | | Express | Routes, middleware, errors | | NestJS | Controllers, guards, interceptors | | Prisma | All database queries with statements | | PostgreSQL (pg) | Raw SQL queries | | Redis/ioredis | All Redis commands | | gRPC | Client and server calls | | MySQL | Database queries | | MongoDB | Database operations |
Manual Error Capture
try {
await riskyOperation();
} catch (error) {
InfraSamuraiNode.captureError(error, {
component: "PaymentService",
action: "processPayment",
});
}Shutdown
// Flush pending spans before exit (for serverless)
await InfraSamuraiNode.flush();
// Full shutdown
await InfraSamuraiNode.shutdown();Browser APM
Configuration
import { InfraSamuraiBrowser } from "@infrasamurai/sdk-js/browser";
InfraSamuraiBrowser.init({
// Required
dsn: "your-project-dsn",
serviceName: "my-frontend",
// Optional
serviceVersion: "1.0.0",
environment: "production",
// Sampling
sampleRate: 0.1, // Trace 10% of sessions
errorsSampleRate: 1.0, // Capture all errors
// Auto-instrumentation
instrumentations: {
documentLoad: true, // Page load metrics (LCP, FCP, TTFB)
fetch: true, // Fetch/XHR requests
userInteraction: false, // Clicks, form submissions (noisy)
errors: true, // Uncaught errors, unhandled rejections
},
// Distributed tracing - add trace headers to these URLs
propagateTraceHeaderUrls: [
/^https:\/\/api\.example\.com/,
window.location.origin,
],
// URLs to ignore
ignoreUrls: [
/\/health$/,
/google-analytics\.com/,
],
});User Context
// Set user after login
InfraSamuraiBrowser.setUser({
id: "user-123",
email: "[email protected]",
username: "john_doe",
plan: "premium", // Custom attributes
});
// Clear on logout
InfraSamuraiBrowser.clearUser();
// Get current user
const user = InfraSamuraiBrowser.getUser();Manual Tracing
// Wrap async operations
const result = await InfraSamuraiBrowser.trace(
"checkout.process",
async (span) => {
span.setAttribute("cart.items", 5);
return await processCheckout();
}
);Manual Error Capture
InfraSamuraiBrowser.captureError(error, {
component: "CheckoutForm",
action: "submit",
});Queue Metrics
For monitoring Kafka, RabbitMQ, SQS, BullMQ, or any message queue.
Configuration
import { InfraSamuraiQueues } from "@infrasamurai/sdk-js/queues";
const queues = InfraSamuraiQueues.init({
dsn: process.env.ALERTSAMURAI_DSN!,
environment: "production",
timeout: 10000, // Request timeout (ms)
silent: false,
});Recording Metrics
// Full metrics
await queues.recordMetrics("orders-queue", {
depth: 150, // Messages waiting
consumerLag: 50, // Messages behind
dlqCount: 3, // Dead letter queue count
oldestMessageAgeSeconds: 120, // Age of oldest message
processedCount: 1000, // Successfully processed
failedCount: 5, // Failed messages
avgProcessingTimeMs: 45, // Average processing time
enqueueRate: 10.5, // Messages/sec enqueued
dequeueRate: 9.8, // Messages/sec dequeued
});
// Convenience methods
await queues.recordDepth("orders-queue", 150);
await queues.recordConsumerLag("orders-queue", 50);
await queues.recordDlq("orders-queue", 3);
await queues.recordProcessing("orders-queue", 1000, 5, 45);BullMQ Example
import { Queue } from "bullmq";
const queue = new Queue("orders");
setInterval(async () => {
const [waiting, active, failed, delayed] = await Promise.all([
queue.getWaitingCount(),
queue.getActiveCount(),
queue.getFailedCount(),
queue.getDelayedCount(),
]);
await queues.recordMetrics("orders", {
depth: waiting + delayed,
processedCount: active,
failedCount: failed,
});
}, 60000);TypeScript Types
import type {
// Core client
InfraSamuraiConfig,
SendMetricOptions,
SendMetricResponse,
SendAlertOptions,
SendAlertResponse,
AlertPriority,
// Queue metrics
QueueConfig,
QueueMetrics,
QueueMetricsResponse,
} from "@infrasamurai/sdk-js";
// APM types (re-exported from OpenTelemetry)
import type { Span, Tracer, SpanContext } from "@infrasamurai/sdk-js/node";Runtime Compatibility
| Entry Point | Node.js | Browser | Deno | Bun |
|-------------|---------|---------|------|-----|
| @infrasamurai/sdk-js | ✅ | ✅ | ✅ | ✅ |
| @infrasamurai/sdk-js/node | ✅ | ❌ | ❌ | ⚠️ |
| @infrasamurai/sdk-js/browser | ❌ | ✅ | ❌ | ❌ |
| @infrasamurai/sdk-js/queues | ✅ | ❌ | ✅ | ✅ |
Note: Node.js APM auto-instrumentation uses monkey-patching via require-in-the-middle, which doesn't work in Deno and has limited support in Bun.
Requirements
- Node.js 18+ (for native
fetch) or browser environment - TypeScript 5.0+ (for type definitions)
Dependencies
The SDK uses OpenTelemetry for APM tracing:
Required:
@opentelemetry/api@opentelemetry/core@opentelemetry/resources@opentelemetry/sdk-trace-base@opentelemetry/exporter-trace-otlp-http
Optional (for auto-instrumentation):
@opentelemetry/sdk-node@opentelemetry/auto-instrumentations-node@prisma/instrumentation
License
MIT
