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

logify-node-sdk

v0.0.2

Published

Cross-service logging SDK with automatic request and correlation IDs.

Readme

Logify Node SDK

A production-ready, cross-service logging SDK that automatically correlates logs with request and correlation IDs across distributed microservices.

Features

  • 🔗 Automatic Correlation: Request and correlation IDs automatically propagated across services
  • 🚀 Zero Configuration: Works out of the box with sensible defaults
  • 📝 Structured Logging: JSON-formatted logs with consistent schema
  • 🔧 Flexible Configuration: Environment variables, JSON files, or programmatic config
  • 🎯 Context-Aware: AsyncLocalStorage-based request context tracking
  • 📊 Multiple Transports: Console, JSON, and Grafana Loki support
  • 🛡️ Type Safe: Full TypeScript support with comprehensive types
  • High Performance: Optimized with caching and minimal overhead
  • 🧪 Well Tested: Comprehensive unit test coverage

Installation

npm install logify-node-sdk

Quick Start

Express.js Integration

import express from 'express';
import { loadConfigFromObject, createLogger, createExpressMiddleware } from 'logify-node-sdk';

const app = express();

// Configure logger
const config = loadConfigFromObject({
  logLevel: 'info',
  transport: 'console',
  autoModule: true, // Automatically infer module names
});

const logger = createLogger(config);

// Add middleware to capture request context
app.use(createExpressMiddleware(config));

// Use logger in routes
app.get('/users/:id', async (req, res) => {
  const userId = req.params.id;
  
  logger.info('Fetching user', { 
    userId,
    module: 'UserController.getUser' 
  });
  
  try {
    const user = await getUserById(userId);
    logger.info('User fetched successfully', { userId });
    res.json(user);
  } catch (error) {
    logger.error('Failed to fetch user', { 
      userId,
      error // Automatically extracts error details
    });
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(3000, () => {
  logger.info('Server started', { port: 3000 });
});

Configuration

Environment Variables

# Log level (debug, info, warn, error)
LOG_LEVEL=info

# Header names for request/correlation IDs
REQUEST_ID_HEADER=x-request-id
CTID_HEADER=x-correlation-id

# Transport type
LOG_TRANSPORT=console  # console, json, loki

# Auto-detect module names from stack traces
LOG_AUTO_MODULE=true

# Loki configuration (when transport=loki)
LOKI_URL=https://loki.example.com
LOKI_TENANT_ID=your-tenant
LOKI_BASIC_AUTH=base64encodedcreds

Configuration File

Create logify.config.json:

{
  "logLevel": "info",
  "transport": "json",
  "autoModule": true,
  "requestIdHeader": "x-request-id",
  "ctidHeader": "x-correlation-id",
  "loki": {
    "url": "https://loki.example.com",
    "tenantId": "production",
    "basicAuth": "dXNlcjpwYXNz",
    "labels": {
      "service": "user-api",
      "environment": "production"
    }
  }
}
import { loadConfigFromFile, createLogger } from 'logify-node-sdk';

const config = loadConfigFromFile('./logify.config.json');
const logger = createLogger(config);

Programmatic Configuration

import { loadConfigFromObject, createLogger } from 'logify-node-sdk';

const config = loadConfigFromObject({
  logLevel: 'debug',
  transport: 'console',
  autoModule: true,
});

const logger = createLogger(config);

API Reference

Logger Methods

All log methods follow the same signature:

logger.info(message: string, options?: LogOptions): void

Where LogOptions allows any key-value pairs plus special options:

interface LogOptions {
  module?: string;                    // Module override
  error?: Error;                      // Error object (auto-extracted)
  [key: string]: unknown;             // Any additional data
}

Examples

// Simple message
logger.info('User logged in');

// With structured data (no need for "details" wrapper)
logger.info('User logged in', {
  userId: 123, 
  email: '[email protected]'
});

// With module name
logger.info('Processing payment', {
  amount: 100, 
  currency: 'USD',
  module: 'PaymentService.processPayment'
});

// With error handling
try {
  await processPayment(paymentData);
} catch (error) {
  logger.error('Payment processing failed', {
    paymentId: payment.id,
    error // Automatically extracts name, message, stack, cause
  });
}

Child Loggers

Create child loggers with bound context:

// Create child logger with service context
const serviceLogger = logger.child({ 
  service: 'user-service',
  version: '1.2.0',
  module: 'UserService'
});

// All logs from this logger will include the bound context
serviceLogger.info('User created', { userId: 123 });
// Output includes: { service: 'user-service', version: '1.2.0', userId: 123 }

// Child loggers can be nested
const operationLogger = serviceLogger.child({ 
  operation: 'createUser',
  traceId: 'abc123'
});

Outbound Request Propagation

Propagate correlation IDs to downstream services:

import { buildPropagationHeaders } from 'logify-node-sdk';
import axios from 'axios';

// Inside a request handler
const headers = buildPropagationHeaders({
  requestIdHeader: 'x-request-id',
  ctidHeader: 'x-correlation-id',
});

const response = await axios.get('https://api.example.com/users', {
  headers: {
    ...headers,
    'Authorization': 'Bearer token'
  }
});

Log Structure

Every log record has the following JSON structure:

{
  "timestamp": "2024-01-15T10:30:45.123Z",
  "level": "info",
  "message": "User logged in",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "ctid": "a1b2c3d4e5f6789012345678901234567890abcd",
  "module": "AuthController.login",
  "details": {
    "userId": 123,
    "email": "[email protected]"
  }
}

Field Descriptions

  • timestamp: ISO 8601 timestamp
  • level: Log level (debug, info, warn, error)
  • message: Human-readable message
  • requestId: Unique UUID v4 for each request (auto-generated)
  • ctid: 32-character correlation ID (persists across services)
  • module: Module/function name (optional, can be auto-detected)
  • details: Structured additional data (optional)

Request & Correlation IDs

Request ID (requestId)

  • Fresh UUID v4 generated for every inbound request
  • Not persisted beyond the single request
  • Used for tracking individual API calls

Correlation ID (ctid)

  • 32-character lowercase alphanumeric string
  • Persists across connected flows and service boundaries
  • If inbound request has valid ctid header, it's used
  • Otherwise, a new ctid is generated
  • Used for tracing entire user journeys across microservices

Transports

Console Transport

Human-readable JSON output to stdout (default):

const config = loadConfigFromObject({ transport: 'console' });

JSON Transport

Structured JSON lines to stdout (same as console):

const config = loadConfigFromObject({ transport: 'json' });

Loki Transport

Ships logs to Grafana Loki:

const config = loadConfigFromObject({
  transport: 'loki',
  loki: {
    url: 'https://loki.example.com',
    tenantId: 'production',
    basicAuth: 'dXNlcjpwYXNz',
    labels: {
      service: 'user-api',
      environment: 'production'
    }
  }
});

Error Handling

The SDK includes comprehensive error handling:

Configuration Errors

import { ConfigValidationError } from 'logify-node-sdk';

try {
  const config = loadConfigFromObject({ logLevel: 'invalid' });
} catch (error) {
  if (error instanceof ConfigValidationError) {
    console.error('Config validation failed:', error.details);
  }
}

Transport Errors

Loki transport errors are handled gracefully and logged to stderr without affecting application flow.

Performance

  • Stack Trace Caching: Module name inference results are cached
  • Level Filtering: Early return for filtered log levels
  • Async Transport: Loki transport is fire-and-forget with error handling
  • Minimal Overhead: Optimized for high-throughput applications

Testing

Run the test suite:

# Unit tests
npm test

# With coverage
npm run test:coverage

# Watch mode
npm run test:watch

# Smoke test
npm run smoke

Development

# Install dependencies
npm install

# Run linting
npm run lint

# Fix linting issues
npm run lint:fix

# Format code
npm run format

# Build
npm run build

# Run example server
npm run example

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type { 
  LogifyConfig, 
  LogifyLogger, 
  LogOptions, 
  LogRecord,
  RequestContext 
} from 'logify-node-sdk';

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Run npm run lint && npm test
  5. Submit a pull request

License

MIT

Changelog

See CHANGELOG.md for version history.


Need help? Open an issue on GitHub.