npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@statly/observe

v1.2.1

Published

JavaScript SDK for Statly Observe - Error tracking and monitoring

Downloads

738

Readme

Statly Observe SDK for Node.js

npm version License: MIT

Error tracking and monitoring for JavaScript and TypeScript applications. Capture exceptions, track releases, and debug issues faster.

📚 Full Documentation | 🚀 Get Started | 💬 Support

This SDK requires a Statly account. Sign up free at statly.live to get your DSN and start tracking errors in minutes.

Features

  • Automatic error capturing with stack traces
  • Structured Logging: Production-grade logging with automatic scrubbing
  • Distributed Tracing: Visualize function execution and call hierarchies
  • Performance Metrics: Automated capture of latency and success rates
  • Breadcrumbs for debugging context
  • User context tracking
  • Release tracking
  • Framework integrations (Express, Next.js, Fastify)
  • TypeScript support
  • Minimal overhead

Installation

npm install @statly/observe
# or
yarn add @statly/observe
# or
pnpm add @statly/observe

Getting Your DSN

  1. Go to statly.live/dashboard/observe/setup
  2. Create an API key for Observe
  3. Copy your DSN (format: https://<key-prefix>@statly.live/<org-slug>)
  4. Add to your .env file: STATLY_DSN=https://...

Note: The DSN contains only a 16-character key prefix (e.g., sk_live_a1b2c3d4) which is safe to embed in client-side code. For server-side operations requiring full permissions, use the complete API key.

Quick Start

The SDK automatically loads DSN from environment variables, so you can simply:

import { Statly } from '@statly/observe';

// Auto-loads STATLY_DSN from environment
Statly.init();

Or pass it explicitly:

import { Statly } from '@statly/observe';

// Initialize the SDK
Statly.init({
  dsn: 'https://[email protected]/your-org',
  release: '1.0.0',
  environment: 'production',
});

// Errors are captured automatically via global handlers

// Manual capture
try {
  riskyOperation();
} catch (error) {
  Statly.captureException(error);
}

// Capture a message
Statly.captureMessage('User completed checkout', 'info');

// Set user context
Statly.setUser({
  id: 'user-123',
  email: '[email protected]',
});

// Add breadcrumb for debugging
Statly.addBreadcrumb({
  category: 'auth',
  message: 'User logged in',
  level: 'info',
});

# Flush before exit (important for serverless)
await Statly.close();

Tracing & Performance

Statly Observe supports distributed tracing to help you visualize execution flow and measure backend performance.

Automatic Tracing

Use Statly.trace() to wrap functions. It works with both synchronous and asynchronous code:

import { Statly } from '@statly/observe';

const result = await Statly.trace('process_payment', async (span) => {
  span.setTag('provider', 'stripe');
  
  // Your logic here
  const payment = await stripe.charges.create({...});
  
  return payment;
});

Manual Spans

For low-level control, you can start spans manually:

const span = Statly.startSpan('database_query');
try {
  await db.query('...');
  span.setTag('query_type', 'SELECT');
} finally {
  span.finish(); // Reports to Statly
}

Structured Logging

The Logger class provides production-grade structured logging with automatic secret scrubbing, session management, and batching.

Quick Start

import { Logger } from '@statly/observe';

const logger = Logger.create({
  dsn: 'https://[email protected]/your-org',
  environment: 'production',
  loggerName: 'api-server',
});

// Log at different levels
logger.trace('Entering function', { args: [1, 2, 3] });
logger.debug('Processing request', { requestId: 'req_123' });
logger.info('User logged in', { userId: 'user_123' });
logger.warn('Rate limit approaching', { current: 95, limit: 100 });
logger.error('Payment failed', { orderId: 'ord_456', error: 'Card declined' });
logger.fatal('Database connection lost', { host: 'db.example.com' });
logger.audit('User role changed', { userId: 'user_123', newRole: 'admin' });

// Always close before exit
await logger.close();

Child Loggers

Create child loggers with inherited context:

const requestLogger = logger.child({
  context: { requestId: 'req_123' },
  loggerName: 'request-handler',
});

requestLogger.info('Processing request'); // Includes requestId automatically

User Context

Associate logs with users:

logger.setUser({
  id: 'user_123',
  email: '[email protected]',
  name: 'Jane Doe',
});

Secret Scrubbing

The logger automatically scrubs sensitive data (API keys, passwords, credit cards, etc.). Add custom patterns:

const logger = Logger.create({
  dsn: '...',
  scrubPatterns: [
    /my-custom-secret-[a-z0-9]+/gi,
    /internal-token-\d+/g,
  ],
});

Sample Rates

Control log volume with per-level sampling:

const logger = Logger.create({
  dsn: '...',
  sampleRates: {
    trace: 0.01,  // 1% of trace logs
    debug: 0.1,   // 10% of debug logs
    info: 0.5,    // 50% of info logs
    warn: 1.0,    // 100% of warnings
    error: 1.0,   // 100% of errors
    fatal: 1.0,   // 100% of fatal
  },
});

Logger Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | dsn | string | required | Your project's Data Source Name | | environment | string | undefined | Environment name | | release | string | undefined | Release/version identifier | | loggerName | string | undefined | Logger name for filtering | | sessionId | string | auto-generated | Session ID for grouping logs | | user | object | undefined | User context | | defaultContext | object | {} | Default context for all logs | | minLevel | LogLevel | 'trace' | Minimum level to log | | sampleRates | object | all 1.0 | Per-level sample rates | | scrubPatterns | RegExp[] | [] | Additional patterns to scrub | | batchSize | number | 50 | Batch size before flush | | flushInterval | number | 5000 | Flush interval in ms | | maxQueueSize | number | 1000 | Max queue size |

Framework Integrations

Express

import express from 'express';
import { Statly, requestHandler, expressErrorHandler } from '@statly/observe';

const app = express();

// Initialize first
Statly.init({
  dsn: 'https://[email protected]/your-org',
  environment: process.env.NODE_ENV,
});

// Add request handler FIRST (before routes)
app.use(requestHandler());

// Your routes
app.get('/', (req, res) => {
  res.send('Hello World');
});

app.get('/error', (req, res) => {
  throw new Error('Test error');
});

// Add error handler LAST (after routes)
app.use(expressErrorHandler());

app.listen(3000);

Next.js (App Router)

Route Handlers:

// app/api/example/route.ts
import { withStatly } from '@statly/observe';

export const GET = withStatly(async (request) => {
  // Errors are automatically captured
  const data = await fetchData();
  return Response.json({ data });
});

Error Boundary:

// app/error.tsx
'use client';

import { useEffect } from 'react';
import { captureNextJsError } from '@statly/observe';

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    captureNextJsError(error);
  }, [error]);

  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={reset}>Try again</button>
    </div>
  );
}

Server Actions:

'use server';

import { withStatlyServerAction } from '@statly/observe';

export const submitForm = withStatlyServerAction(
  async (formData: FormData) => {
    // Your action code - errors are captured automatically
    const email = formData.get('email');
    await saveToDatabase(email);
  },
  'submitForm' // Action name for grouping
);

Fastify

import Fastify from 'fastify';
import { Statly, statlyFastifyPlugin } from '@statly/observe';

const fastify = Fastify();

Statly.init({
  dsn: 'https://[email protected]/your-org',
});

// Register the plugin
fastify.register(statlyFastifyPlugin, {
  captureValidationErrors: true,
  skipStatusCodes: [400, 401, 403, 404], // Don't capture these as errors
});

fastify.get('/', async () => {
  return { hello: 'world' };
});

fastify.listen({ port: 3000 });

Environment Variables

The SDK automatically loads configuration from environment variables:

| Variable | Description | |----------|-------------| | STATLY_DSN | Your project's DSN (primary) | | NEXT_PUBLIC_STATLY_DSN | DSN for Next.js client-side | | STATLY_OBSERVE_DSN | Alternative DSN variable | | STATLY_ENVIRONMENT | Environment name | | NODE_ENV | Fallback for environment |

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | dsn | string | process.env.STATLY_DSN | Your project's Data Source Name | | environment | string | undefined | Environment name (production, staging, development) | | release | string | undefined | Release/version identifier for tracking | | debug | boolean | false | Enable debug logging to console | | sampleRate | number | 1.0 | Sample rate for events (0.0 to 1.0) | | maxBreadcrumbs | number | 100 | Maximum breadcrumbs to store | | autoCapture | boolean | true | Auto-attach global error handlers | | beforeSend | function | undefined | Callback to modify/filter events before sending |

beforeSend Example

Statly.init({
  dsn: '...',
  beforeSend: (event) => {
    // Filter out specific errors
    if (event.message?.includes('ResizeObserver')) {
      return null; // Drop the event
    }

    // Scrub sensitive data
    if (event.extra?.password) {
      delete event.extra.password;
    }

    return event;
  },
});

API Reference

Statly.captureException(error, context?)

Capture an exception with optional additional context:

try {
  await processPayment(order);
} catch (error) {
  Statly.captureException(error, {
    extra: {
      orderId: order.id,
      amount: order.total,
    },
    tags: {
      paymentProvider: 'stripe',
    },
  });
}

Statly.captureMessage(message, level?)

Capture a message event:

Statly.captureMessage('User signed up', 'info');
Statly.captureMessage('Payment failed after 3 retries', 'warning');
Statly.captureMessage('Database connection lost', 'error');

Levels: 'debug' | 'info' | 'warning' | 'error' | 'fatal'

Statly.setUser(user)

Set user context for all subsequent events:

Statly.setUser({
  id: 'user-123',
  email: '[email protected]',
  username: 'johndoe',
  // Custom fields
  subscription: 'premium',
});

// Clear user on logout
Statly.setUser(null);

Statly.setTag(key, value) / Statly.setTags(tags)

Set tags for filtering and searching:

Statly.setTag('version', '1.0.0');

Statly.setTags({
  environment: 'production',
  server: 'web-1',
  region: 'us-east-1',
});

Statly.addBreadcrumb(breadcrumb)

Add a breadcrumb for debugging context:

Statly.addBreadcrumb({
  message: 'User clicked checkout button',
  category: 'ui.click',
  level: 'info',
  data: {
    buttonId: 'checkout-btn',
    cartItems: 3,
  },
});

Statly.flush() / Statly.close()

// Flush pending events (keeps SDK running)
await Statly.flush();

// Flush and close (use before process exit)
await Statly.close();

TypeScript Support

Full TypeScript support with exported types:

import type {
  StatlyOptions,
  StatlyEvent,
  User,
  Breadcrumb,
  EventLevel,
} from '@statly/observe';

Requirements

  • Node.js 16+
  • Works in browser environments (with bundler)

Resources

Why Statly?

Statly is more than error tracking. Get:

  • Status Pages - Beautiful public status pages for your users
  • Uptime Monitoring - Multi-region HTTP/DNS checks every minute
  • Error Tracking - SDKs for JavaScript, Python, and Go
  • Incident Management - Track and communicate outages

All on Cloudflare's global edge network. Start free →

License

MIT