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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@trace-dock/sdk

v0.5.0

Published

JavaScript/TypeScript SDK for trace-dock logging - Universal logger with HTTP/WebSocket transport

Readme

@trace-dock/sdk

A universal JavaScript/TypeScript logging and tracing SDK for trace-dock. Works in Node.js, browsers, and Tauri applications.

Features

  • 🚀 Universal - Works in Node.js, browsers, and Tauri
  • 📡 Dual Transport - HTTP with optional WebSocket for real-time streaming
  • 🔍 Stack Traces - Automatic stack trace capture for errors and warnings
  • 🏷️ Structured Logging - Support for metadata and context
  • 👶 Child Loggers - Create child loggers with inherited context
  • 🔗 Distributed Tracing - Full tracing support with spans and waterfall visualization
  • Lightweight - Zero dependencies, tree-shakeable
  • 📦 TypeScript - Full TypeScript support with type definitions

Installation

# npm
npm install @trace-dock/sdk

# pnpm
pnpm add @trace-dock/sdk

# yarn
yarn add @trace-dock/sdk

Quick Start

import { createLogger } from '@trace-dock/sdk';

const logger = createLogger({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
});

// Basic logging
logger.debug('Debug message');
logger.info('User logged in', { userId: 123 });
logger.warn('Rate limit approaching', { current: 95, max: 100 });
logger.error('Failed to process request', { error: new Error('Connection timeout') });

Configuration

import { createLogger } from '@trace-dock/sdk';

const logger = createLogger({
  // Required
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  
  // Optional - defaults shown
  enabled: true,                  // Enable/disable logging (default: true)
  sessionId: undefined,           // Auto-generated if not provided
  enableWebSocket: false,         // Enable WebSocket for real-time streaming
  wsEndpoint: undefined,          // Auto-derived from endpoint if not set
  batchSize: 10,                  // Batch size for HTTP transport
  flushInterval: 5000,            // Flush interval in ms
  maxRetries: 3,                  // Max retries for failed requests
  debug: false,                   // Log to console as well
  metadata: {},                   // Default metadata for all logs
  onError: undefined,             // Error callback
});

API

Log Levels

logger.debug(message, metadata?);  // Debug level
logger.info(message, metadata?);   // Info level
logger.warn(message, metadata?);   // Warning level (includes stack trace)
logger.error(message, metadata?);  // Error level (includes stack trace)

Adding Metadata

// Pass metadata as second argument
logger.info('User action', { userId: 123, action: 'click' });

// For errors, pass the Error object in metadata
logger.error('Operation failed', { 
  error: new Error('Connection timeout'),
  endpoint: '/api/users'
});

Child Loggers

Create child loggers that inherit parent context:

const logger = createLogger({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
});

// Create a child logger with additional context
const userLogger = logger.child({ userId: 123, role: 'admin' });

// All logs from userLogger will include userId and role
userLogger.info('User performed action'); // metadata includes { userId: 123, role: 'admin' }

WebSocket Transport

Enable WebSocket for real-time log streaming to the trace-dock UI:

const logger = createLogger({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  enableWebSocket: true,
  // wsEndpoint is auto-derived: ws://localhost:3001/live
});

// Don't forget to disconnect when done
logger.disconnect();

Session Management

Each logger instance gets a unique session ID. You can also set it manually:

const logger = createLogger({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  sessionId: 'user-session-abc123',
});

// Get current session ID
const sessionId = logger.getSessionId();

// Update session ID
logger.setSessionId('new-session-id');

Debug Mode

Enable debug mode to also log to the console:

const logger = createLogger({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  debug: true, // Logs will also appear in console
});

Enable/Disable Logging

You can enable or disable the SDK at runtime to control when logs are sent:

const logger = createLogger({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  enabled: true, // Default: true
});

// Check if logging is enabled
logger.isEnabled(); // true

// Disable logging (no network requests will be made)
logger.disable();
logger.info('This will NOT be sent');

// Re-enable logging
logger.enable();
logger.info('This WILL be sent');

// In debug mode, logs still appear in console even when disabled
const debugLogger = createLogger({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  enabled: false,
  debug: true, // Still logs to console
});

Tracing

The SDK includes a full-featured Tracer for distributed tracing, allowing you to track requests across services with a waterfall timeline visualization.

Basic Tracing

import { createTracer } from '@trace-dock/sdk';

const tracer = createTracer({
  appName: 'my-api',
  endpoint: 'http://localhost:3001/ingest',
});

// Start a trace
const traceId = tracer.startTrace('HTTP GET /users');

// Create spans for operations
const spanId = tracer.startSpan('db.query', {
  operationType: 'query',
  metadata: { table: 'users' },
});

// ... perform the operation ...

// End the span
tracer.endSpan(spanId, 'completed');

// End the trace
tracer.endTrace(traceId, 'completed');

Using withTrace and withSpan

For cleaner code, use the wrapper functions that automatically handle errors:

// Wrap an entire operation in a trace
const result = await tracer.withTrace('process-order', async () => {
  
  // Wrap sub-operations in spans
  const user = await tracer.withSpan('fetch-user', async () => {
    return await db.users.findById(userId);
  }, { operationType: 'db' });
  
  const payment = await tracer.withSpan('process-payment', async () => {
    return await paymentService.charge(user, amount);
  }, { operationType: 'http' });
  
  return { user, payment };
});

Nested Spans

Spans automatically nest based on the current context:

tracer.startTrace('api-request');

const dbSpan = tracer.startSpan('db.transaction');
  
  const querySpan = tracer.startSpan('db.query.users'); // Parent: dbSpan
  tracer.endSpan(querySpan, 'completed');
  
  const insertSpan = tracer.startSpan('db.insert.order'); // Parent: dbSpan
  tracer.endSpan(insertSpan, 'completed');

tracer.endSpan(dbSpan, 'completed');

tracer.endTrace(tracer.getCurrentTraceId()!, 'completed');

Logging Within Traces

Log messages within the trace context:

tracer.startTrace('user-registration');

tracer.log('info', 'Starting user registration', { email: user.email });

const spanId = tracer.startSpan('send-email');
tracer.log('debug', 'Sending welcome email');
tracer.endSpan(spanId, 'completed');

tracer.log('info', 'User registration complete');
tracer.endTrace(tracer.getCurrentTraceId()!, 'completed');

Tracer Configuration

const tracer = createTracer({
  // Required
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  
  // Optional
  sessionId: undefined,        // Auto-generated if not provided
  enabled: true,               // Global enable/disable (default: true)
  enableTracing: true,         // Enable traces/spans (default: true)
  debug: false,                // Log to console as well
  metadata: {},                // Default metadata for all traces
  spanTimeout: 300000,         // Auto-end spans after 5 minutes (ms)
  onError: undefined,          // Error callback
});

Enable/Disable Tracing

The Tracer supports granular control over what gets sent:

const tracer = createTracer({
  appName: 'my-app',
  endpoint: 'http://localhost:3001/ingest',
  enabled: true,        // Global enable (default: true)
  enableTracing: true,  // Enable traces/spans (default: true)
});

// ---- Global Enable/Disable ----

// Check if tracer is globally enabled
tracer.isEnabled(); // true

// Disable everything (no logs, no traces, no spans)
tracer.disable();

// Re-enable everything
tracer.enable();

// ---- Tracing-Specific Control ----

// Check if tracing is enabled
tracer.isTracingEnabled(); // true

// Disable only tracing (logs via tracer.log() still work)
tracer.disableTracing();

// Now traces and spans won't be sent
tracer.startTrace('test'); // Returns a dummy ID, nothing sent
tracer.log('info', 'This IS still sent'); // Logs still work!

// Re-enable tracing
tracer.enableTracing();

This is useful for:

  • Development vs Production: Disable in dev, enable in prod
  • Feature flags: Toggle tracing based on user settings
  • Performance: Disable detailed tracing under high load
  • Debugging: Enable only logs, disable trace overhead

Tracer API Reference

// Trace management
tracer.startTrace(name, metadata?): string           // Returns trace ID
tracer.startTrace(name, options?): string            // Options: { traceId?, parentSpanId?, metadata? }
tracer.endTrace(traceId, status): void               // Status: 'completed' | 'error'

// Span management
tracer.startSpan(name, options?): string             // Returns span ID
tracer.endSpan(spanId, status, metadata?): void

// Wrapper functions (recommended)
tracer.withTrace<T>(name, fn, metadata?): Promise<T>
tracer.withSpan<T>(name, fn, options?): Promise<T>

// Context
tracer.getCurrentTraceId(): string | null
tracer.getCurrentSpanId(): string | null
tracer.getTraceContext(): { traceId, spanId, sessionId } | null  // For distributed tracing

// Logging within trace context
tracer.log(level, message, metadata?): void

// Session
tracer.getSessionId(): string
tracer.setSessionId(sessionId): void

// Enable/Disable
tracer.isEnabled(): boolean                          // Check global enabled state
tracer.enable(): void                                // Enable globally
tracer.disable(): void                               // Disable globally
tracer.isTracingEnabled(): boolean                   // Check if tracing is enabled
tracer.enableTracing(): void                         // Enable traces/spans
tracer.disableTracing(): void                        // Disable traces/spans (logs still work)

Integration Example: Express Middleware

import express from 'express';
import { createTracer } from '@trace-dock/sdk';

const app = express();
const tracer = createTracer({
  appName: 'express-api',
  endpoint: 'http://localhost:3001/ingest',
});

// Tracing middleware
app.use((req, res, next) => {
  const traceId = tracer.startTrace(`${req.method} ${req.path}`, {
    url: req.url,
    method: req.method,
    userAgent: req.headers['user-agent'],
  });
  
  req.traceId = traceId;
  req.tracer = tracer;
  
  res.on('finish', () => {
    tracer.endTrace(traceId, res.statusCode >= 400 ? 'error' : 'completed');
  });
  
  next();
});

// Route with tracing
app.get('/users/:id', async (req, res) => {
  const user = await req.tracer.withSpan('db.findUser', async () => {
    return await db.users.findById(req.params.id);
  }, { operationType: 'db' });
  
  res.json(user);
});

Distributed Tracing (Multi-Service)

The SDK supports distributed tracing across multiple services. You can propagate trace context via HTTP headers to continue a trace in another service.

Service A (Caller)

import { createTracer } from '@trace-dock/sdk';

const tracer = createTracer({
  appName: 'service-a',
  endpoint: 'http://localhost:3001/ingest',
});

async function callServiceB() {
  tracer.startTrace('process-order');
  
  // Get the trace context to propagate
  const context = tracer.getTraceContext();
  
  // Call Service B with trace context in headers
  const response = await fetch('http://service-b/api/process', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-trace-id': context?.traceId || '',
      'x-span-id': context?.spanId || '',
    },
    body: JSON.stringify({ orderId: 123 }),
  });
  
  tracer.endTrace(context!.traceId, 'completed');
}

Service B (Receiver)

import express from 'express';
import { createTracer } from '@trace-dock/sdk';

const app = express();
const tracer = createTracer({
  appName: 'service-b',
  endpoint: 'http://localhost:3001/ingest',
});

app.post('/api/process', async (req, res) => {
  // Extract trace context from headers
  const traceId = req.headers['x-trace-id'] as string;
  const parentSpanId = req.headers['x-span-id'] as string;
  
  // Continue the trace from Service A
  tracer.startTrace('service-b-handler', {
    traceId,              // Use the same trace ID
    parentSpanId,         // Link to the calling span
    metadata: { receivedFrom: 'service-a' },
  });
  
  // Your spans will be linked to the parent trace
  await tracer.withSpan('process-order', async () => {
    // ... do work ...
  });
  
  tracer.endTrace(traceId, 'completed');
  res.json({ success: true });
});

Trace Context API

// Get current trace context for propagation
const context = tracer.getTraceContext();
// Returns: { traceId: string, spanId: string | null, sessionId: string } | null

// Start a trace with an existing trace ID (for distributed tracing)
tracer.startTrace('operation-name', {
  traceId: 'existing-trace-id',      // Continue this trace
  parentSpanId: 'parent-span-id',    // Link to parent span from caller
  metadata: { ... },                  // Additional metadata
});

This enables you to:

  • Track requests across services - See the full journey of a request
  • Visualize service dependencies - Understand how services interact
  • Debug distributed systems - Find where issues occur in the chain

Environment Detection

The SDK automatically detects the runtime environment and includes it in logs:

  • Node.js - Includes Node version, platform, architecture
  • Browser - Includes user agent, current URL
  • Tauri - Includes Tauri version
import { detectEnvironment } from '@trace-dock/sdk';

const env = detectEnvironment();
// { type: 'node' | 'browser' | 'tauri' | 'unknown', ... }

TypeScript Support

Full TypeScript support with exported types:

import type { 
  // Logger types
  LogLevel, 
  LogEntry, 
  LoggerConfig,
  EnvironmentInfo,
  TransportOptions,
  
  // Tracer types
  TracerConfig,
  Trace,
  Span,
  TraceStatus,
} from '@trace-dock/sdk';

Self-Hosted Server

This SDK is designed to work with trace-dock, a self-hosted logging server with a web UI.

# Clone the repository
git clone https://github.com/JeepayJipex/trace-dock.git
cd trace-dock

# Start with Docker
docker-compose up -d

# Or run in development
pnpm install
pnpm dev

License

MIT